標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第283回]

●RS232C受信プログラムの説明です(6)

WindowsAPIを使ってRS232Cの受信プログラムを作ったのですが、最初に書いたプログラムを実行してみると、どうもおかしい。
うまく受信できないのです。

最初は機械語的感覚でプログラムを作りましたから、受信バッファに受信データが入っていたら、何バイト受信できたか確認して、そのバイト数分のデータを引き取る、という感じのプログラムを書きました。
ところがそうすると、文字化けはする、データは落っことす、まあさんざんな状態でまともに受信できません。

ずっと以前に作った、BASIC制御ボード、ZBKボードの受信プログラムは、そのやり方で作っているはずなのですが、どこかが違っているようです。
またいろいろさぐっていけば、そういうやり方の場合のプログラム技法なるものもあるのでしょうが、そんなことにこだわっていると、肝心の組立キットがいつになっても完成させることができません。

で、とりあえずわかっている(というかカットアンドトライでたどりついた)方法で受信プログラムを作ってしまうことにしました。

●受信プログラムはタイムアウトでリターンします

今回の受信プログラムは使用目的が限られています。
汎用目的ではなくて、「つくるCPU(MYCPU80)」の上にのっている「TK80」からの送信データを受信するという目的だけのプログラムです。
となると、送信されてくるデータはそれほど大きなものではないはずですし、しかもそれは「STORE DATA」キーを押すことで、一括して送信されてくるひとかたまりのデータになります。

そういうことなら、受信の途中でちびちび読まなくても、受信が終わってから全データを読み込むようにした方がプログラムがうんと簡単になります。
受信が終わったことはどうやれば知ることができるでしょうか?
それを可能にするのがタイムアウトなのです。

送られてくるデータは最後のデータまで、ほぼ切れ目なく送信されてきます。
それなら、通常考えられる程度の遅延時間を大きくオーバーしても、次のデータが送られてこなかったら、「送信の終り」と判断してもよいでしょう。
RS232Cのいろいろなパラメータ設定の中に、受信データのタイムアウト時間の設定、というものがあります。
これを利用して、指定したタイムアウト時間を超えても次のデータが受信されなかったらブレイクして、メインルーチンにもどってくる、というように設定をします。


// set timeout
        COMMTIMEOUTS timeout;
        timeout.ReadIntervalTimeout=100;//ms
        if(!SetCommTimeouts(hcom,&timeout))return 0;


●COMMTIMEOUTS構造体とSetCommTimeouts()

タイムアウトに関係するパラメータは、COMMTIMEOUTS構造体にあります。
そのなかの .ReadIntervalTimeoutにタイムアウトするまでの時間(単位msec)を設定します。
適当な値ですが、100(ms)を指定しました。
書き換えたCOMMTIMEOUTS構造体の値をRS232Cに反映させるには、WindowsAPIのSetCommTimeoutsを実行します。

以上で、OPEN()の処理はやっと完了です。
ここまでの実行で、RS232Cにアクセスすることができるようになります。

●ReadFile()

RS232Cの受信処理を行うには、WindowsAPIの、ReadFile()を使います。


//  rs232c read
        if(!ReadFile(hcom,&inbf,4096,&rdbytes,NULL))printf("%s READ ERROR\n",comname);

ReadFileについてもMSDNのサイトに説明があります。


readFile()の説明の下の方に、次のような記述があります。
タイムアウトに関する記述です。



いいかげんな値を設定すると、通信途中でブレイクしてしまいますよ、という注意のようです。

さて、r232.cppではinbfという名前の記憶場所を確保したうえで、ReadFile()を呼びます。
プログラムの先頭でinbfの定義をしています。


char inbf[4096]="\0";

受信する最大バイト数としては、4096を指定しています(この数については後でまた説明をします)。
ReadFile()の実行によって、受信スタンバイになり、受信タイムアウト(スタンバイではタイムアウトしません。データを受信する間隔が指定時間以上になると、タイムアウトになります)でMain()に戻ってきます。
そのときrdbytesには、実際に受信したバイト数が入れられます。

ですから、受信完了してmain()に戻ってきたら、rdbytesの値のバイト数のデータをinbfから読み取ればよいのです。
2009.7.19upload

前へ
次へ
ホームページトップへ戻る