#99 Article 1134 Posted at 1996/09/02 23:01:27 by みやちゃん (MAP2821) [COMM]

Subject: Re: Re: Re: Q:Windows 通信ポートリセット /1132 /1131 /1130

>>Win32APIで、ClearCommError()なんてのができたみたいですが
>>3.1ではどうだったんでしょう。
>残念なことに、Win16ではそのAPIはないみたいです。
>今調べたら、32sでも見当たらないし・・・

そーいえば私も昨年中はこれの関係でかなり苦しんだ記憶があります。
私の場合は、GetCommError で返されてくるステータスを監視し、
目的とするステータスデータがクリアされるまでループを組みました。

というのも、エラーが発生していると言うことはその原因がある訳ですから
あらかじめエラーが立たないようにステータスを監視してしまおうという論法です。
ですから実際にエラーが立ってからよりも、
エラーが発生する前に原因をチェックしている訳です。
これは主に送信タイムアウトや送信キューのオーバーフローが原因の場合ですが、
受信時のオーバーランなどにも有効かと思います。
また、ケーブル不良などの外的要因はソフト的には原因が取り除かれない訳ですから
エラーから復帰しても意味がないと判断しています。

原理となるシーケンスは次の通りです。

BYTE ComErr;
COMSTAT cstat;

BOOL SendCommBuff(char *buf)
{
	WriteComm(COM1,buf,lstrlen(buf));
	do{
		ComErr=GetCommError(COM1,&cstat)){
		if(ComErr){
			FlushComm(COM1,0);
			return FALSE;
		}
	}while(cstat.cbOutQue>0);
	return TRUE;
}

見ての通り *buf に入れられているテキストデータを送信する部分ですが、
必ず送信キューがクリアされてからリターンするようにしています。
(エラー発生時は無条件に送信キューをクリアしてリターンする。
 ステータスは変数 ComErr cstat に返される。)

鉛筆を削るのに例えると、ナイフで削る度に定規で測るようなものでしょうか。

ただしこれは完全に一方通行を想定していますから実際の組み込みでは
受信に対するチェックなどを入れなければなりません。
まぁ、受信についてはキューとは別の大きなバッファにどんどん蓄積していき、
必要とする場合にテキストファイル感覚で1文字単位、または1行単位に
読み出せる構造を作った方が早いでしょうし、
少なくとも受信キューを読み出す間隔が十分短ければ
オーバーランエラーは発生しませんからね。

GetCommError 自体がきちんとエラーステータスをクリアしロックを解除しても
原因が取り除かれていなければすぐにまた同じエラーが発生しますしね。


また、エラーが起こった場合、それがプログラム上の問題
(送信キューのオーバーフローなど)ではない場合は
通信を中断してしまうのは当然のことだと思いますけどね。
で、その間にユーザにチェックさせるのは必要ではないかと。
全体を考えればかりそめの復帰よりもエラーの原因を潰す方が重要ですし。

							みやちゃん