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
   te_u0c1  =  1
   re_u0c1  =  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ファースト
転送フォーマット選択ビット


メニューに戻る