こんにちは,小坂です。 リングバッファの振る舞いについて,学生向けのWebページに書きましたので,こちらにも流します。 リングバッファを用いたシリアル通信受信に関して (1)リングバッファ リングバッファといえども,バッファはただのメモリの領域(C言語からはunsigned char の配列に見える)です。このバッファに関連したポインタが2つあります。1つは現在バッファ中のどこに書き込んでいるかを示すポインタ[書き込みポインタ](本物のポインタ変数を用いるか,配列要素番号を格納したint型変数を用いる2つの方法があります。実用では本物のポインタ変数を使うのですが,学習のためならint型変数にポインタの役割を負わせ,配列要素番号で指すことにするのがよいでしょう)もう1つは現在バッファ中のどこを読み出しているのかを示すポインタ[読み出しポインタ]です。 正確に言うと[書き込みポインタ]は,次のデータを格納する場所を指しており,[読み出しポインタ]は次にデータを取り出す場所を指しています。 そして,初期状態では,2つのポインタは配列の先頭を指しています。 (2)受信割り込み関数 受信バッファフルを割り込み要因とした受信割り込み関数は次のような動作をします。(ただし,割り込み作業に関すること(レジスタの退避など)にはここでは触れません) 1)シリアル通信機能から受信データをもらい,[書き込みポインタ]の場所に格納します。 2)[書き込みポインタ]を1増加させ,次の受信に備えます。ただし,あらかじめ用意されたバッファ領域から外れた場合は先頭に戻し,次の受信に備えます。 3)シリアル通信機能に対し,受信データ貰い受け後に行なうべき処理をします。 (3)1文字受信関数 ユーザプログラムから呼び出される,1文字受信関数は次のようになっています。 ユーザプログラムにどのように受信データを渡し,受信データがない時にどうするかはいろいろ方法があるところですが,ANSIのgetchar()を真似すると次のような関数仕様になります。すなわち,受信データが存在するときは受信データを返す。このデータの値の範囲は0〜0xff(0〜255)です。受信データがないときは0xffff(-1)を返すようにします。 実際の作業は 1)[書き込みポインタ]と[読み出しポインタ]が同じ値の時は,受信データが存在しないと考えて-1を返すため,[返す値変数]に-1を格納します。。 2)そうでない時は[読み出しポインタ]の位置にあるデータを返すことにして,[返す値変数]にこのデータを保存します。そして[読み出しポインタ]を1増加させ,次の読み出しに備えます。ただし,あらかじめ用意されたバッファ領域から外れた場合は先頭に戻し,次の読み出しに備えます。 3)[返す値変数]を呼び出し側に返しながらこの関数は終ります。 (4)受信バッファオーバーフロー [読み出しポインタ]は[書き込みポインタ]を追い越すことはないのですが,ユーザプログラムが他の仕事で忙しくてなかなか1文字受信関数を呼び出して受信データを読み出してくれない場合には,[書き込みポインタ]が[読み出しポインタ]を追い越してしまう現象が起こります。(あるいはプログラムを追い越し禁止にしておいて,オーバーフローエラーフラッグを立てることもあります。) このような場合には受信バッファサイズを大きくしてあげることが必要になります。または,追い越しそうになったらシリアル通信のフロー制御で,相手に待ってもらうことも考えられます。 **************************************************** 〒193 0997 八王子市椚田町1220-2 東京工業高等専門学校 情報工学科 小坂敏文 phone0426-68-5199 Fax68-5098