バッファリング機能付きシリアル通信(SCI) for H8-300h

 概要
H8-tinyのSCI機能を用いてPC間とシリアル通信を行うためのプログラムです。
バッファリング機能付きなので送受信時にCPU時間を浪費せずに済みます。

 キーワード
H8-300h, H8tiny, SCI, シリアル通信

 注記
きっちりとしたライブラリ化はあえてしていません。
動作実績のある1コード片として参考にしていただけたら幸いです。
HOS上で動かすために書いたので一部HOS依存です。
  • UB型はunsigned charのtypedefです。
  • VP_INT exinfはuTRON仕様の拡張引数です。使っていません。
  • エラーハンドリングは未実装です。
  • h83664f.hはHOS添付のものです。秋月コンパイラに付属のものとは変数名が若干異なります。
著者への質問・つっこみはこちらまで。

 ソールファイル
sci.h
sci.c

 コンパイル・動作確認済み環境
ハードウェア:AKI−H8/3664F(QFP) タイニーマイコンキット(秋月電子)
開発環境: windows XP + cygwin + gcc3.3 + hosv4
動作実績:第11回川崎ロボット競技大会 リミットカズラ で使用。

 説明
基本的な流れは次の通り:
  1. 割り込みハンドラsci_int_handler()を登録する
  2. 初期化関数sci_init()を呼ぶ
  3. sci_read()で受信。sci_write()で送信
初期化の仕方や、割り込みハンドラの登録の仕方は処理系に依存するところなのでお好きな方法を選んでください。 以下はHOS-V4を用いる場合での利用例です。

HOSコンフィギュレータ(SCI関連処理のみ抜粋)
	INCLUDE("\"main.h\"");	/* task_sciが宣言されている */
	INCLUDE("< sci.h >");

	/* SCI3 */
	/* 初期化関数を登録 */
	ATT_INI({TA_HLNG, 0, sci_init});
	/* 割り込みハンドラを登録(23はSCIの割り込み番号) */
	ATT_ISR({TA_HLNG, 0, 23, sci_int_handler});

	/* タスク生成 */
	CRE_TSK(TSKID_SCI, {TA_HLNG|TA_ACT, 0, task_sci, 1, 256, NULL});
					
sci_initとsci_int_handlerはsci.h内で宣言されています。 task_sciはユーザ定義関数です。

 ユーザ定義コード
	#include < i2c.h >

	/* バージョン文字列 */
	const char g_strVersion[] = "LimitKazura ver. 1.0(LC12)";
	const size_t g_nVersionLength = 26;

	/* メイン関数 */
	int main(void)
	{
		/* カーネル起動 */
		sta_hos();

		return 0;
	}

	/* SCIからの指令を処理 */
	void task_sci(VP_INT exinf)
	{
		unsigned char cmd, buff[5];
		while(TRUE){
			/* 受信バッファが空でなければ */
			if(sci_read(&cmd, 1) == 1){
				/* 送信バッファにバージョン文字列を書き込む(自動的に送信開始) */
				sci_write((UB*)g_strVersion, g_nVersionLength + 1);
			}
			dly_tsk(20);
		}
	}
					

 リファレンス
 RX_BUFFER_LENGTH
受信バッファの長さを指定する定数です。
sci.h内で#defineされているので適宜調整してください。
RX_BUFFER_LENGTH以上のデータが受信バッファにたまってしまった場合(バッファオーバラン)の 動作は不定です。

 TX_BUFFER_LENGTH
送信バッファの長さを指定する定数です。 sci.h内で#defineされているので適宜調整してください。 TX_BUFFER_LENGTH以上のデータを送信される前に書き込んでしまった場合(バッファオーバラン)の 動作は不定です。

 void sci_init(VP_INT exinf)
 exinf  itron拡張引数。未使用。
初期化処理を実行します。 その他の関数を利用する前に一度だけ呼び出してください。 ボーレートなどの設定は関数内でハードコーディングしていますので、 必要に応じて書き換えてください。

 void sci_int_handler(VP_INT exinf)
 exinf  itron拡張引数。未使用。
割り込みハンドラです。処理系に依存した方法で登録してください。 実際の送受信処理を司ります。

 void sci_flush_rx(void)
受信バッファをクリアします。
 void sci_flush_tx(void)
送信バッファをクリアします。

 size_t sci_read(UB* data, size_t n)
 data  受信バッファの内容を受け取るバッファへのポインタ
 n  読み出すデータ長。単位はバイト。
 戻り値  実際に読み出されたデータ長。単位はバイト。
受信バッファにたまっているデータを読み出します。 dataにnullを指定した場合は、受信バッファにたまっているデータ長を返します。 たとえば
 while(sci_read(0, 0) < 10);
とすれば受信バッファに10バイトたまるまでウェイトをかけられます。 dataに適切なユーザ定義変数へのポインタを指定した場合、 受信バッファにたまっているデータを、古い順にnバイト分をdataにコピーします。 もし受信バッファにたまっているデータ長がnよりも小さい場合は、受信バッファの全ての内容が dataにコピーされます。 読み出されたデータは受信バッファから削除されます(実際にはリングバッファのインデックスを進めるだけ)。

 size_t sci_write(UB* data, size_t n)
 data  送信バッファへ書き込む内容を保持するバッファへのポインタ
 n  書き込むデータ長。単位はバイト。
 戻り値  実際に書き込まれたデータ長。単位はバイト。
送信データを送信バッファに書き込みます。 dataにnullを指定した場合は、送信バッファにたまっている(送信待ちになっている)データ長を返します。 dataに適切なユーザ定義変数へのポインタを指定した場合、 送信バッファの末尾に、dataの内容を追加します。 送信バッファの内容は、書き込まれた順番に自動的に送信されます。