U A R T 0
T.クロック非同期型シリアルI/Oモード
1)プログラム例−T 垂れ流し実験
2)プログラム例−U 受信割り込み
3)プログラム例−V UARTを使ってGPSデータをLCDに表示する
U.クロック同期型シリアルI/Oモード
T.クロック非同期型シリアルI/Oモード
R8C/M12AにはシリアルインターフェイスであるUART0が1チャンネルあります。クロック同期型シリアルI/Oモードとクロック非同期型シリアルI/Oモードの2種類のモードがあります。ここでは、クロック非同期型シリアルI/Oモードについて実験してみます。
UART0で使える端子は、以下の通りです。
| CLK0
| 転送クロック
| P1_6
|
| RXD0 |
受信 |
P1_4、P1_5、P4_6 |
| TXD0 |
送信 |
P1_4、P4_2、P4_6 |
それぞれのRXD0、TXD0の組み合わせを選択することができます。それぞれのポート機能マッピングレジスタを以下のように設定することで選択可能になります。
| P1_4 |
:RXD0端子 |
・・・ |
pmh1=0x02; (または p14sel0=0;p14sel1=1;p14sel2=0;) |
| P1_4 |
:TXD0端子 |
・・・ |
pmh1=0x01; (または p14sel0=1;p14sel1=0;p14sel2=0;) |
| P1_5 |
:RXD0端子 |
・・・ |
pmh1=0x04;pmh1e=0x00; (または p15sel0=1;p15sel1=0;p15sel2=0) |
| P4_2 |
:TXD0端子 |
・・・ |
pml4=0x20;(または p42sel0=0;p42sel1=1;) |
| P4_6 |
:TXD0端子 |
・・・ |
pmh4=0x20;(または p46el0=0;p46sel1=1;p46sel2=0;) pmh4e=0x00; |
| P4_6 |
:RXD0端子 |
・・・ |
pmh4=0x10;(または p46sel0=1;p46sel1=0;p46sel2=0;) pmh4e=0x00;
|
(1)UART0送受信モードレジスタ(U0MR)
クロック同期か非同期、パリティ、ストップビットなどを決定します。
| ビット |
シンボル |
ビ ッ ト 名 |
設定値 |
| 7 |
|
予約ビット |
0に設定する |
| 6 |
PRYE |
パリティ許可ビット |
0:パリティ禁止
1:パリティ許可 |
| 5 |
PRY |
パリティ奇数/偶数選択ビット |
0:奇数パリティ
1:偶数パリティ |
| 4 |
STPS |
ストップビット長選択ビット |
0:1ストップビット
1:2ストップビット |
| 3 |
CKDIR |
内部/外部クロック選択ビット |
0:内部クロック
1:外部クロック |
| 2 |
SMD2 |
シリアルI/Oモード選択ビット |
000:シリアルインターフェイス無効
001:クロック同期形シリアルI/Oモード
100:UARTモード転送データ長7ビット
101:UARTモード転送データ長8ビット
110:UARTモード転送データ長9ビット |
| 1 |
SMD1 |
| 0 |
SMD0 |
ここで、クロック非同期形8ビット長、ストップビット1、ノーパリティにする場合
u0mr = 0x05;
(2)UART0ビットレートレジスタ(U0BRG)
送受信の速度(ビットレート)を決めます。ビットb7〜b0 の8ビットで決めます。設定値をnとすると、カウントソースをn+1回分周した周波数の16分周がビット・レートになります。UART0送受信制御レジスタ(U0C0)で決めるカウントソースビットをf1(20MHz)とすると、9600bpsのビット・レートにするときのU0BRGの設定値は、
20MHz/9600/16=130.2=130(小数点以下を四捨五入)=129+1=0x81+1
u0brg = 0x81; となる。
同様に、同じカウントソースf1のとき、ビット・レートと設定値の関係は以下の通りである。
| u0brg = |
0x86; |
14400bps |
| 〃 = |
0x64; |
19200bps |
| 〃 = |
0x42; |
28800bps |
カウントソースf8のとき、ビット・レートと設定値の関係は以下の通りである。
| u0brg = |
0x32; |
4800bps |
| 〃 = |
0x64; |
2400bps |
(3)UART0送信バッファレジスタ(U0TB)
送信バッファレジスタU0TB(16ビット)は、下位8ビット、上位8ビット単位で取り扱うことが可能である。
下位8ビット U0TBL: b7 〜 b0
上位8ビット U0TBH: b15 〜 b8
(4)UART0送受信制御レジスタ0(U0C0)
| ビット |
シンボル |
ビット名 |
機能 |
| 7 |
UFORM |
転送フォーマット選択ビット |
0:LSBファースト
1:MSBファースト |
| 6 |
CKPOL |
CLK極性選択ビット |
クロック同期形シリアル
I/Oモードのとき有効 |
| 5 |
NCH |
データ出力選択ビット |
0:TXD0端子はCMOS出力
1:TXD0端子はNチャネル
オープンドライン出力 |
| 4 |
DFE |
RXD0デジタルフィルタ許可ビット |
0:デジタルフィルタ禁止
1:デジタルフィルタ許可 |
| 3 |
TXEPT |
送信レジスタ空フラグ |
0:送信レジスタにデータあり(送信中)
1:送信レジスタにデータなし(送信完了)
|
| 2 |
|
予約ビット |
0に設定 |
| 1 |
CLK1 |
U0BRGカウントソース選択ビット |
00:f1
01:f8
10:f32
11:設定不可 |
| 0 |
CLK0 |
ここでは、LSBファースト、カウントソースf1,デジタルフィルタ許可
u0c0 = 0x10;
(5)UART0送受信制御レジスタ1(U0C1)
| ビット |
シンボル |
ビット名 |
機能 |
| 7 |
予約ビット |
|
00に設定 |
| 6 |
| 5 |
U0RRM |
UART0連続受信モード許可ビット |
0:連続受信モード禁止
1:連続受信モード許可 |
| 4 |
U0IRS |
UART0送信割り込み要因選択ビット |
0:送信バッファ空
1:送信完了 |
| 3 |
RI |
受信完了フラグ |
0:U0RBレジスタにデータなし
1:U0RBレジスタにデータあり
|
| 2 |
RE |
受信許可ビット |
0:受信禁止
1:受信許可
|
| 1 |
TI |
送信バッファ空フラグ |
0:U0TBレジスタにデータあり
1:U0TBレジスタにデータなし |
| 0 |
TE |
送信許可ビット |
0;送信禁止
1:送信許可 |
受信許可ビット、送信許可ビットは1
(6)モジュールスタンバイ制御レジスタ(MSTCR)
UART0スタンバイビットを有効にします
mstuart = 0;
または、mstcr = 0x00;
(7)UART0受信バッファレジスタ(U0RB)
16ビットレジスタ、受信データは、b0〜b7に格納されるので、
data = u0rb & 0x00ff; のようにして下位8ビットを取り出す。
(8)UART0割り込みフラグと許可レジスタ(U0IR)
| ビット |
シンボル |
ビット名 |
機能 |
| 7 |
U0TIF |
UART0送信割り込みフラグ |
0:送信割り込み要求なし
1:送信割り込み要求あり |
| 6 |
U0RIF |
UART0受信割り込みフラグ |
0:受信割り込み要求なし
1:受信割り込み要求あり |
| 5 |
|
|
|
| 4 |
|
|
|
| 3 |
U0TIE |
UART0送信割り込み許可ビット |
0:送信割り込み禁止
1:送信割り込み許可
|
| 2 |
U0RIE |
UART0受信割り込み許可ビット |
0:受信割り込み禁止
1:受信割り込み許可
|
| 1 |
|
|
|
| 0 |
|
|
|
◎プログラム例−T(垂れ流し実験)
p1_4をTXD0に、p1_5ををRXD0 に割り当てる。9600bpsでパソコンに接続した通信ソフトTeraTermの画面に「送信テスト」と表示し、パソコンキーボードからの入力値を表示するプログラムです。UART0の初期設定は、(1)〜(5)にしたがって設定しています。
◎1文字受信関数
UART0送受信制御レジスタ1(U0C1)のRIビットが1であれば、受信データがUART0受信バッファレジスタU0RB(16ビット)に格納される。
/* 1文字受信関数 */
int UART0_rx(void)
{
unsigned int data;
char err;
while(ri_u0c1 != 1);// 受信バッファレジスタをチェック
data = u0rb & 0x00ff;// 下位8ビットを抽出
return data;
}
◎1文字送信関数
UART0送受信制御レジスタ1(U0C1)のTIビットが0であれば、送信データがUART0送信バッファレジスタU0TB(16ビット)にデータがあるので、空になるまで送信を続ける。
/* 1文字送信関数 */
int UART0_tx(char data)
{
while(ti_u0c1 != 1);// 送信バッファ空フラグ
u0tbl = data; //
}
◎メインプログラム EM_UART0.c
#include<stdio.h>
#include "sfr_r8m12a.h"
void main(void);
void init(void);
void set_UART0(void);
int UART0_rx(void);
int UART0_tx(unsigned char r);
void UART0_tx_str(char *str);
void CRLF(void);
void main(void)
{
unsigned int i;
unsigned char rd = 0; // 受信データ格納変数
unsigned char d;
int ret;
init();
set_UART0();
UART0_tx_str("UART0");
CRLF();
UART0_tx_str("送信テスト\n\r");
while(1){ // エコーバック
d=UART0_rx();
UART0_tx(d);
}
}
/* I/O 初期化関数 */
void init(void)
{
int i;
prc0 = 1; // プロテクトレジスタ解除
hocoe = 1; // 高速オンチップオシレータ発振開始
for(i=0;i<50;i++); // 発振安定まで待つ
hscksel = 1; // 高速オンチップオシレータ選択ビットを1にする
scksel = 1; // システム基準クロックを高速にする
prc0 = 0; // プロテクトレジスタ禁止
/**********************************************/
pd1= 0x13; // 0001 0011設定
p1 = 0xff;
}
void set_UART0(void)
{
mstcr = 0x00; // モジュールスタンバ制御イレジスタを0にする
pmh1 = 0x05; // p1_4をTXD0、p1_5をRXD0に割り当てる
pmh1e = 0x00;
u0mr = 0x05; // 8ビット長、パリティなし、ストップビットなし
u0brg = 0x81; // uart0初期化 20MHZ/(9600*16)-1=0x81
dfe_u0c0= 1; // ディジタルフィルタ許可
te_u0c1 = 1; // 送信許可
re_u0c1 = 1; // 受信許可
}
/* 1文字受信関数 */
int UART0_rx(void)
{
unsigned int data;
char err;
while(ri_u0c1 != 1);
data = u0rb & 0x00ff;
return data;
}
/* 1文字送信関数 */
int UART0_tx(char data)
{
while(ti_u0c1 != 1);// 送信バッファ空フラグ
u0tbl = data;
}
/* 文字列送信関数 */
void UART0_tx_str(char *str)
{
while(*str != '\0'){
UART0_tx(*str);
str++;
}
}
/* 改行表示関数 */
void CRLF(void)
{
UART0_tx(0x0a);
UART0_tx(0x0d);
}

TeraTermの表示画面
プロジェクトファイルのダウンロード
◎プログラム例−U(受信割り込み)
UART0のプログラム例Uとして、P1_4をTXD0、P1_5をRXD0に割り当て、UART0 受信割り込みを使う実験をします。キーボードから入力した文字をTeraTerm画面とI2C LCDの両方に表示します。キーボードから”1”を入力すると、TetaTerm画面にECHO BACKされた”1”が表示され、LCD画面には、”LED-ON"と表示され、ボード上のLEDが点灯します。キーボードから”0”を入力するとLCD画面には、”LED-OFF"と表示され、ボード上のLEDが消灯します。

TeraTermの表示画面

使用したボード モニター画面の1に対応してLCD基盤のLEDが点灯している
1)メインプログラム UART0_I2C_LCD.c
#include "sfr_r8m12a.h"
#include "i2clcd_ctrl.h"
unsigned int i;
unsigned char rd = 0; // 受信データ格納変数
unsigned char d;
int ret;
unsigned char str0[8];
void main(void)
{
init();
set_UART0();
I2C_LCD_init(); // LCD初期化
I2C_SDA_OUT; // SDAピン出力に設定
I2C_LCD_cursor(1,0); // 1行目0より表示
I2C_LCD_str("ストロベリ"); // 表示文字列出力
wait_ms(1000);
I2C_LCD_cursor(1,0); // 1行目0より表示
I2C_LCD_str("UART_I2C LCD");
wait_ms(1000);
// I2C_LCD_clear(); // LCDクリヤーの後は最低でも2ms以上ウエイト
asm("FSET I");
UART0_tx_str("LCD + ECHO テスト\n\r");
str0[0]=' ';str0[1]='T';str0[2]='E';str0[3]='S';str0[4]='\n';str0[5]='\r';
UART0_tx_str(str0);
u0rif = 0; // 受信割り込みフラグクリア
while(u0rif != 1){ // エコーバック
u0rif = 0;
rd=UART0_rx();
UART0_tx(d);
}
}
void init(void)
{
int i;
/**** 高速オンチップオシレータで動作する場合 ****/
prc0 = 1; // プロテクトレジスタ解除
hocoe = 1; // 高速オンチップオシレータ発振開始
for(i=0;i<50;i++); //発振安定まで待つ
hscksel=1; // 高速オンチップオシレータ選択ビットを1にする
scksel =1; // システム基準クロックを高速にする
prc0 = 0; // プロテクトレジスタ禁止
pd1 =0x93; // pd1入出力設定 1001 0011
p1 =0x00;
pd3 =0xff;
}
#pragma interrupt _uart0_receive(vect=18) // UART0受信割り込み関数
void _uart0_receive(void)
{
unsigned char r_data;
r_data = u0rb & 0x00ff;
if(r_data =='0'){
p1_7=1;
I2C_LCD_cursor(2,0); // 2行目0より表示
I2C_LCD_str("OFF");
CRLF();
}
else if(r_data=='1'){
p1_7=0;
I2C_LCD_cursor(2,0); // 2行目0より表示
I2C_LCD_str("ON ");
CRLF();
}
u0rif = 0;
}
2)uart0.c
UART0関連の関数をまとめたファイルです。ここでは、 p1_4をTXD0、p1_5をRXD0 に割り当てています。
#include "sfr_r8m12a.h"
#include "i2clcd_ctrl.h"
void set_UART0(void)
{
mstcr = 0x00; // モジュールスタンバ制御イレジスタを0にする
pmh1 = 0x05; // p1_4をTXD0、p1_5をRXD0に割り当てる
pmh1e = 0x00;
u0mr = 0x05; // 8ビット長、パリティなし、ストップビットなし
u0brg = 0x81; // uart0初期化 20MHZ/(9600*16)-1=0x81
dfe_u0c0= 1; // ディジタルフィルタ許可
te_u0c1 = 1; // 送信許可
re_u0c1 = 1; // 受信許可
ilvl9_addr.bit.b0=1;// UART0割り込みレベル1に設定
ilvl9_addr.bit.b1=0;
u0rie = 1; // 受信割り込み許可
}
・
・
他のUART0関係の関数は例1)プログラムと同じです。
・
・
3)i2clcd_ctrl.c、i2clcd_ctrl.h
以前、使用した第4章「I2C接続LCDを制御する」で使用した"i2clcd_ctrl.c"と同じです。
4)i2clcd_ctrl.h
以前、4章「I2C接続LCDを制御する」で使用した"i2clcd_ctrl.h"にUART0関連の関数を追加したものです。
I2C_LCD + UART0 のヘッダーファイル
#define I2C_S_SCL p1_1=1 // I2Cクロック p1_1を1にする
#define I2C_C_SCL p1_1=0 // I2Cクロック p1_1を0にする
#define I2C_S_SDA p1_0=1 // I2Cデータ p1_0を1にする
#define I2C_C_SDA p1_0=0 // I2Cデータ p1_0を0にする
#define I2C_SDA_IN pd1_0=0 // p1_0を入力ポートに設定
#define I2C_SDA_OUT pd1_0=1 // p1_0を出力ポートに設定
#define I2C_SDA_data p1_0 // データポートをp1_0に設定
#define AD 0x7c // アドレス 0B 0111 110+0(c/w)
#define CLOCK 20000
void init(void);
/********************* I2C関連 **************************/
void wait_us(unsigned long usec);// us単位のタイマ
void wait_ms(unsigned long msec);// ms単位のタイマ
void delay(void);// 6usの遅延関数
void I2C_start(void);// I2C開始
void I2C_stop(void);// I2Cストップ
void ack(void);// ACKNOWLEDGE信号受信
void I2C_H_CLK(void);// クロックHigh
void I2C_L_CLK(void);// クロックLow
void I2C_LCD_init(void);// lcd初期化関数
int I2C_write(unsigned char data);// 書き込みの基本関数
static unsigned char I2C_read(void);// 読み込みの基本関数
void I2C_LCD_cmd(unsigned char cmd);// 液晶へのコマンド出力関数
void I2C_LCD_data(unsigned char data);// 液晶への1文字出力関数
void I2C_LCD_str(char* ptr);// 液晶への文字列表示関数
void I2C_LCD_clear(void);// 液晶のクリャー関数
// カーソル位置設定関数 line(行数):1 or 2 cursor(左端からの位置):0〜f
void I2C_LCD_cursor(unsigned char line,unsigned char cursor);
/********************* UART0関連 ************************/
void set_UART0(void);
int UART0_rx(void);
int UART0_tx(unsigned char r);
void UART0_tx_str(char *str);
void CRLF(void);
プロジェクトファイルのダウンロード
◎プログラム例−V(UART0を使ってGPSデータをLCDに表示する)
GPSモジュールは3,000円〜10,000円程度で様々な種類が出回っており、それぞれ、 一長一短があり、自分の利用の仕方によって選択されたら良いと思います。秋月電子、ストロベリーリナックス、若松通商などから販売されています。データ形式は、NMEA-0183フォーマット形式。通信速度は4800〜9600BPSとなっています。R8CにはいずれもUART0を使って取り込むことになります。今回は、ストロベリーリナックスのSUP500F使っています。RS232Cではなく、UARTで直接出力がでていること、専用のプラスチックケースが出ているので、組み込んで自走式のGPSボートGPSカーを作成する際に都合がよいと考えてのことです。
測地系の設定がデフォルトではWGS-84になっているようなので、測地系を付属のソフトを使って、パソコン上から「TOKYO Japan」に変更してやる必要があるので、いづれにしてRS232Cに変換するボードは用意しておくほうが良いと思います。ADM3202ANなどのRS232CインターフェイスICを使ってUARTレベルをRS232Cレベルに変換する必要があります。
NMEA-0183の出力形式は、この機種の場合は、1秒毎にセンテンスと呼ばれる$マークの付いた6つの形式が1行毎に出力され、更新されるようになっています。そのなかで、RMCセンテンスは以下のような77バイトのデータが出力されます。CR、LFはキャリッジリターン、ラインフィードの意味です。
$GPMRMC、hhmmss、X、ddmm.mmmm、N、dddmm.mmmm、E、nnn.n、ddd.d、ddmmyy、ddd.d、X、a*cc[CR][LF]
hhmmss 測位時刻(UTC、時、分、秒)
X 測位状態 A:単独測位中またはDGPS測位中 V:未測位
ddmm.mmmm 緯度(度、分、1/10000分)
N N:北緯、S:南緯
dddmm.mmmm 経度(度、分、1/10000分)
E E:東経、W:西経
nnn.n 経度(000.0〜270.0、単位:ノット)
ddd.d 真方位による進行方向(000.0〜359.9、単位:度)
ddmmyy 日付(日、月、年)
ddd.d 磁気偏差(000.0〜180.0、単位:度)
X E:磁気偏差が東より (真方位−磁気偏差=磁気方位) W:磁気偏差が西より (真方位+磁気偏差=磁気方位)
a 測位モード N:未測位 A:単独測位中 D:DGPS測位中
*cc 最初の1文字(*)に続いて 2桁のチェックサムを示します(00〜FF)
今回は、緯度、経度、時間のみが必要なので、$GPRMCのセンテンスを使っています。$GPRMCセンテンスには自走式の船舶や車の場合にも利用できる対地速度(Speed
over ground)や進行方向の方角(Course over ground)などのデータも取得できるので、$GPRMCのセンテンスが一番便利かと思います。それぞれの利用状況に応じて取り出すセンテンスを変えれば良いと思います。
◎プログラム
プログラムでは、センテンスを取り出すために、それぞれのセンテンスの最後の[CR][LF]を目印にして、そのつぎの文字列のセンテンスが取り出そうとしているセンテンスと同じかどうかをチェックするようにしています。チェックした目的のセンテンスだった場合は、先頭から最後の[CR][LF]、つまり、C言語のコードで ’¥n’ の手前までの文字列を配列変数 rx_data[] に取り込みます。表示したい目的とするデータは配列の先頭から何番目に入っているかは判っていますので、それを取り出してLCDに表示しています。プログラムは、一見複雑そうに思えますが、実際は極めて単純な処理をしているだけです。
時刻はUTC(Universal Time Coordinateed)で表示されていますので、UTC+9=JST(Japan Standard Time)になっていますので、以下の計算式で変換して24時間表示になるようにしています。
UTC+9 > 24 の場合は、 JST = UTC − 15
UTC+9 <= 24 の場合は、 JST = UTC + 9
GPSモジュールとのデータのやりとりはUART0を使い、P4_2をTXD0、P4_6をRXD0に割り当てています。LCDの表示は、P1_0〜P1_5を割り当てています。ここでは、ストロベリリナックスGPSモジュールSiRFastarVSUP500Fを使っていますが、どの製品でも同じプログラムで動作すると思います。LCDの表示画面は以下のようになっています。
液晶画面の位置 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
1行目 N 緯度 H M S
2行目 E 経度 時間 分 秒
1)メインプログラム GPS_LCD_STR.c
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "sfr_r8m12a.h"
#include "lcd_ctrl.h"
unsigned char str1[16];
unsigned char str2[16];
//unsigned int i;
//unsigned char r_data;
unsigned char rx_data; /* 受信データ格納変数 */
unsigned char rd[255]; /* 受信バッファ 受信データ格納配列*/
unsigned char ch[4]; /* 時間データ格納配列 時間 */
unsigned char cm[4]; /* 時間データ格納配列 分 */
unsigned char cs[4]; /* 時間データ格納配列 秒 */
unsigned char nh; /* 時間データの数値化データ 時間 */
unsigned char nm; /* 時間データの数値化データ 分 */
unsigned char ns; /* 時間データの数値化データ 秒 */
unsigned char *data="$GPRMC";/* RMCセンテンス抽出用文字列 */
unsigned char compdata[10]; /* RMCセンテンスと比較する文字列 */
unsigned char pflag=1; /* 文字列一致判定フラグ */
void main(void)
{
unsigned int i;
int ret;
init();
lcd_init();
lcd_clear();
set_UART0();
asm("FSET I");
wait_us(1000);
for(i=0;i<16;i++){/* LCD表示配列の初期化 */
str1[i]=' ';
str2[i]=' ';
}
while(1);
}
void init(void)
{
int i;
/**** 高速オンチップオシレータで動作する場合 ****/
prc0 = 1; // プロテクトレジスタ解除
hocoe = 1; // 高速オンチップオシレータ発振開始
for(i=0;i<50;i++);//発振安定まで待つ
hscksel =1; // 高速オンチップオシレータ選択ビットを1にする
scksel =1; // システム基準クロックを高速にする
prc0 = 0; // プロテクトレジスタ禁止
pd1 = 0xff; // ポートディレクションレジスタ1 全て出力ポート設定
p1 = 0x00;
pur4 = 0b11100100;
pd4 = 0x04; //p4_2(TXD0)出力p4_6(RXD0)入力
}
void set_UART0(void)
{
mstcr = 0x00;// モジュールスタンバイ制御レジスタを0にする mstuart=0でも可
pml4 = 0x20;// p4_2をTXD0に割り当て
pmh4 = 0x10;// p4_6をRXD0に割り当て
pmh4e = 0x00;// p4機能マッピング拡張レジスタ
u0mr = 0x05;// 8ビット長,パリティなし,ストップビット1
/*****GPS 4800BPSのとき*****/
// u0c0 =0x19; // uart0送受信制御レジスタ カウンタリソース f8 ディジタルフィツタ許可
// u0brg =0x20; // uart0初期化 U0BRG = 20MHz/(4800*16*8)-1=32.55=0x20
/*****GPS 9600BPSのとき*****/
u0c0 =0x18; // uart0送受信制御レジスタ カウンタリソース f1 ディジタルフィツタ許可
u0brg =0x81; // uart0初期化 U0BRG = 20MHz/(9600*16)-1=0x81
te_u0c1 =1; // 送信許可
re_u0c1 =1; // 受信許可
ilvl9_addr.bit.b0=1;// UART0割り込みレベル1に設定
ilvl9_addr.bit.b1=0;
u0rie =1; // 受信割り込み許可
}
/* UART0 割り込み関数 */
#pragma interrupt _uart0_receive(vect=18)
void _uart0_receive(void)
{
unsigned int i;
/* 受信データ取り込み */
while(1){ // RMCセンテンスの取り出し
do{
i=0;
do{
rx_data=UART0_rx();
rd[i]=rx_data;
i++;
}while(rx_data != '\n'); //改行文字の場合は取り込み停止
rd[i]='\0';
// $GPRMCの文字列を取り出す
for(i=0;i<6;i++){
compdata[i]=rd[i];// 先頭から6文字をcompdataに
}
compdata[i]='\0'; // compdataの最後尾に\0を追加(文字列にする)
pflag=strcmp(data,compdata);// dataとcompdataが一致したらpflagに1が入る
}while(pflag != 0);// pflagが1($GPRMCに一致)になるまで繰り返す
/***** 時刻切り取り *****/
// 秒の部分切り取り
cs[0] = rd[11];
cs[1] = rd[12];
ns = atoi(ts_c);
str2[14] = ns/10+0x30;
str2[15] = ns%10+0x30;;
// 分の部分切り取り
cm[0] = rd[9];
cm[1] = rd[10];
nm = atoi(tm_c);
str2[12] = nm/10+0x30;
str2[13] = nm%10+0x30;
// 時間部分のみ切り取り
ch[0] = rd[7];
ch[1] = rd[8];
nh = atoi(th_c);
if(nh >=15){
nh = nh - 15;
}
else{
nh = nh+9;
}
str2[10] = nh /10+0x30;
str2[11] = nh %10+0x30;
/**** 緯度データ取り込み ****/
for(i=0;i<10;i++){
str1[i+1]=rd[i+20];// 1行目に表示
}
/* 経度データの取り込み ****/
for(i=0;i<9;i++){
str2[i+1]=rd[i+32];// 2行目に表示
}
str1[0]='N';
str1[9]= ' ';
str1[10]=' ';
str1[11]='H';
str1[12]=' ';
str1[13]='M';
str1[14]=' ';
str1[15]='S';
str2[0]='E';
str2[9]= ' ';
lcd_str(str1,1);
lcd_str(str2,2);
wait_us(10000);
}
u0rif=0;
}
/* 1文字受信 */
int UART0_rx(void)
{
unsigned int data;
char err;
while(ri_u0c1 !=1);
data=u0rb & 0x00ff;
return data;
}
/* 1文字送信 */
int UART0_tx(char data)
{
while(ti_u0c1 !=1);// 送信バッファ空フラグ
u0tbl = data;
}
/* 文字列送信関数 */
void UART0_tx_str(char *str)
{
while( *str != '\0'){
UART0_tx(*str);
str++;
}
}
2)ヘッダーファイル lcd_ctrl.h
/********************************************************/
/* lcd_ctrl.h */
/********************************************************/
#define CLOCK 20000
#define LCD p1 // LCDのデータポート
/* LCDのレジスターセレクション */
#define RS_High (p1_4=1)
#define RS_Low (p1_4=0)
/* LCDのディスプレーイネーブル */
#define E_High (p1_5=1)
#define E_Low (p1_5=0)
void init(void);
void lcd_init(void); // LCD初期化関数
void lcd_clear(void); // LCD画面クリアー
void lcd_cursor_off(void);// LCDカーソルOFF
void lcd_out(unsigned char code,unsigned char flag);// データ出力関数
void lcd_data(unsigned char asci);// 一文字出力関数
void lcd_cmd(unsigned char cmd);// コマンド出力関数
void lcd_str(unsigned char *str,unsigned char line);// 文字列出力関数
void wait_us(unsigned long usec);// us単位のウエイト関数
void set_UART0(void); // UART初期設定関数
int UART0_rx(void); // UART受信関数
int UART0_tx(unsigned char r); // UART一文字送信関数
void UART0_tx_str(char *str); // UART文字列送信関数
LCD制御プログラム lcd_ctrl.c は以前使ったものと同じです。

プロジェクトファイルのダウンロード
メニューに戻る
U.クロック同期形シリアルI/Oモード
クロック同期型シリアルI/Oモードとは、受信側と送信側が転送クロックで同期をとり、データの送受信を行うモードです。3本の入出力端子(CLK0、RXD0、TXD0)を使います。転送データフォーマットにおける、転送データ長は8ビット固定です。転送クロックは、U0MRレジスタのCKDIRビットが0の時は内部クロック、1の時は、外部クロックを使います。 クロック同期型シリアルI/Oモードでは、送信側を動作させることによりシフトクロックを発生させて、受信側はそのクロックに同期して受信データを受信します。ここでは、2台のCPUボードを繋いでI2C通信をする場合を考えていますので、マスタ側は内部クロックを選択し、スレーブ側は外部クロックを選択することになります。従って、データを受信する側は、データ受信状態にするために送信側からのダミークロックを受信して送信を許可することによってデータが受信可能状態になります。
◎クロック同期形で使用する端子端子は、以下の通りです
| 端子名 |
機 能 |
選択 |
| TXD0(p1_4) |
シリアルデータ出力 |
受信だけの時はダミーデータ出力 |
| RXD0(p1_5) |
シリアルデータ入力 |
|
| CLK0(p1_6) |
転送クロック出力 |
u0mrレジスタのckdir=1 |
| 転送クロック入力 |
u0mrレジスタのckdir=0 |
ここでは、各レジスタを以下のように設定しています。
◎送信側の設定
| 送信バッファレジスタ(U0TB) |
u0tbl |
b0〜b7 |
送信データ設定 |
| 送受信モードレジスタ(U0MR) |
ckdir |
= 0x01; |
内部クロックを選択する |
| ビットレートレジスタ(U0BRG) |
u0brg |
= 0x81; |
|
| 送受信制御レジスタ1(U0C1) |
te_u0c1 |
= 1; |
送信許可 |
| ti_u0c1 |
= 0; |
u0tbレジスタにデータあり |
| u0irs_u0c1 |
0:送信バッファ空
1:送信完了 |
送信割り込み要因 |
| 送受信制御レジスタ0(U0C0) |
CLK1、CLK0 |
00:f1
01:f8
10:f32 |
カウントソース選択ビット |
| texpt |
0:送信中
1:送信完了 |
送信レジスタ空フラグ |
| nch |
|
データ出力選択ビット |
| ckpol |
0:立ち下がりで出力
1:立ち上がりで出力 |
CLK極性選択ビット |
| ukform |
0:LSBファースト
1:MSBファースト |
転送フォーマット選択ビット |
◎受信側の設定
| 受信バッファレジスタ(U0RB) |
u0rbl |
b0〜b7 |
受信データを読む |
| oer_u0rb |
0:なし、1:あり |
オーバーランエラーフラグ |
| 送受信モードレジスタ(U0MR) |
ckdir |
= 0x09; |
外部クロックを選択する |
| ビットレートレジスタ(U0BRG) |
u0brg |
= 0x81; |
|
| 送受信制御レジスタ1(U0C1) |
re_u0c1 |
= 1; |
受信許可 |
| ri_u0c1 |
0:完了
1:未完了 |
受信完了フラグ |
| uorrm_u0c1 |
0:連続受信モード禁止
1:連続受信モード許可 |
連続受信モード許可ビット |
| 送受信制御レジスタ0(U0C0) |
CLK1、CLK0 |
00:f1
01:f8
10:f32 |
カウントソース選択ビット |
| dfe |
|
RXD0デジタルフィルタ許可 |
| ckpol |
0:立ち上がりで
データ入力
1:立ち下がりで
データ入力 |
CLK極性選択ビット |
| ukform |
0:LSBファースト
1:MSBファースト |
転送フォーマット選択ビット |
メニューに戻る