Top -> SH7125 -> シリアル通信を使う

シリアル通信を使う

 マイコン同士やマイコンとPCでシリアル通信を行う、SCIモジュールを使ってみます。

初期設定
 レジスタの設定
void SCI1_setup(int br){
	int i;
	
	STB.CR3.BIT._SCI1=0;		// SCI1 動作開始
	SCI1.SCSCR.BYTE = 0x00;
	SCI1.SCSCR.BIT.CKE = 0x00;	// クロックソース
	SCI1.SCSMR.BYTE = 0x00;		// 調歩同期式,
					// 8bit,
					// パリティ無し,
					// ストップビット1,
					// マルチプロセッサ無し
	SCI1.SCSMR.BIT.CKS = 0;		// クロック
	SCI1.SCSDCR.BIT.DIR = 0x00;	// LSBから送受信
	
	SCI1.SCBRR = Pphi*2*1000000/64/br-(115200>br);
					// ボーレートの設定
	
	for(i=0;i<65000;i++);		// 1byte期間待つ
	PFC.PACRL1.BIT.PA3MD = 1;	// PA3 端子機能設定 RXD1入力
	PFC.PACRL2.BIT.PA4MD = 1;	// PA4 端子機能設定 TXD1出力
	SCI1.SCSCR.BYTE = 0x30;		// 送受信許可
}
 Pphiは通常25[MHz]です。(Pphi=25)
 ボーレートの計算が怪しいかもしれません。
当方の環境では115200bpsより速くすると通信できなくなります。

 teraterm等は以下のような設定にします。
調歩同期式
データ長:8ビット
パリティ:なし
ストップビット:1
フロー制御:なし

送信用の関数
void SCI1_tx(char data){
	while(SCI1.SCSSR.BIT.TDRE == 0);	// SCTDRが空くまで待つ
	SCI1.SCSSR.BIT.TDRE = 0;		// フラグクリア
	
	SCI1.SCTDR = data;			// SCTDRに送信データを書き込む
}
 前(正確には前の前)の送信が終わるとTDREのビットが立つのでそれを待ち、送信データを書き込みます。
 マイコンの動作から見るとシリアル通信はかなり遅いので、ここで多少なりとも待たされることになります。

受信用の関数
char SCI1_rx(void){
	char data;
	
	while (SCI1.SCSSR.BIT.RDRF == 0);	// 受信待ち
	SCI1.SCSSR.BIT.RDRF = 0;		// フラグクリア
	data = SCI1.SCRDR;
	
	return data;
}
 1文字受信し、その値を返します。
 ここで注意すべきは、何かしら受信するまでwhileで待ち続けるということ。 受信を待たずに、RDRFがゼロだったらエラーを返すような関数にした方が良いかもしれませんね。

関数を使ってみる
 では、上記の関数を使ってみましょう。
 パソコンから受信した文字をそのまま返します。
 ここでは、ボーレートを9600bpsとしているので、teratermでの設定も同様にしてください。
void main(void){
	char data;
	
	SCI1_setup(9600);
	
	while(1){
		data = SCI1_rx();	//パソコンから受信
		SCI1_tx(data);		//受信したデータをそのまま返す
	}
}

便利な関数たちを作ってみました

lib_SCI_buff_101217.zip

準備
void intSCI1_tx_buff(void);
 intprg.cのINT_SCI1_TXI1内から上記関数を呼び出してください。
 また、resetprg.cの#define SR_Initは0x00000000にします。

 通常の送信関数では、前の1バイトの送信が終わるのを待ってから次の1バイトを送信用のレジスタに書き込むのですが、9600bpsでは1文字送るのに0.8msと、長い間待つことになります。
 その待ち時間を減らすため、送信データをバッファに蓄えておき、送信が終わったことを示す割り込みによって次のデータに移ります。
 バッファがいっぱいにならない限りは送信待ちがなく、プログラムがストップしないようになっています。

初期化
void SCI1_setup(int);
 引数はボーレートです。

送信
void SCI1_printf(char *, ...);
void SCI1_tx_str(char *);
char SCI1_tx_char(char);
void SCI1_tx_d(long);
void SCI1_tx_x(long);
void SCI1_tx_X(long);
 基本的にはSCI1_printfを使えばokです。使い方は普通のprintfと同じで、%d,%x,%X,%c,%sに対応しています。
 そのほかのSCI1_tx_str〜Xの関数は、それぞれの文字/数字だけを送りたいときに使うと、SCI1_printfよりもほんの少しだけ速いはずです。

受信
char SCI1_rx_char(void);
char SCI1_rx_char_nowait(void);
unsigned int SCI1_rx_d(void);
 SCI1_rx_charは1文字受信。受信するまで待ちます。
 _nowaitは受信を待たず、もしデータが来ていないときは0x15を返します。
 _dは、キーボードなどからの数字入力を受け付けます。数字入力後、エンターキーで確定し、unsigned int型の数値にして返します。