ひとつ前へ WWWルートへ mad@mail.wind.ne.jp

RS232のデバッグ

株式会社 数理設計研究所 Hal.T 2006/02/02
Index
 GID事業部強震計を作っている。回線速度は19200BPS、8bit,NP,1stop、3軸で毎秒100データ(16文字)が流れ続ける。1文字当たり10ビットなので毎秒16000ビットとなり、文字コードの間でほとんど隙間無くたれながされる通信が起きている。ところが、このデータ通信の開始時にどうもうまくいかない。
 GID事業部の矢澤君が突っつきまわして【Win32API シリアル受信プログラム デバッグの一例】なるレポートを作成した。しかし、どうも気に入らない。なぜ気に入らないのか、それは【トラブル解決の一般規則】にも書いてあるが、明瞭な原因が特定されていないことにある。つまりデバッグの一例ではあるが、失敗例でもあるわけだ。そこで、後を引き継いで試みたのがこのレポートである。

問題の定義

最初に【トラブル解決の一般規則】より
  • 要因を細分し、唯一のきっかけ、または一連の操作後には確実に現象が発生するようにすべきであり、これが最初に実行されるべき手続=実験である。
 強震計ソフトでは、エラーを報告するまでに多くの手順を踏んでいる。回線の初期化、文字列をデータブロックに切り出す手順、これらのどこでエラーが起きているのか?
 見かけでは回線のオープンは成功し、最初に1パックのデータを切り出す以前にエラーが起きているように見える。read関数の帰り値が最初のエラー報告場所だ。これをつっつきまわしたのが【Win32API シリアル受信プログラム デバッグの一例】となっている。この報告が気に入らないのは

原因 受信開始までの時間が長いと受信バッファがオーバーフローします
対策 fAbortOnErrorでエラー抑制

ですませている点にあり、確実に問題点を特定して対処したわけではないように見えるのだ。

問題の特定と対策

着目点 回線がオープンされる前からデータが流れていれば何が起きるか?

 CreateFile で回線がオープンされればLSIが初期化されます。つまりシリアル・パラレル変換のレジスタが通信の流れとは無関係にリセットされ、モードセットが実行された後の最初のスタートビットで非同期通信が開始します。しかし、そのスタートビットは期待する非同期通信のスタートビットではなく、単なるデータである確率が小さくありません。この結果フレーミングエラーが起きる。

 この推定の元にCrateFileの直後にエラーコードを読み出してみました→ClearCommError(...);
エラーコードとして  CE_FRAME 0x0008 winbase.h  が出て図星です。
 もちろん時間がたてば  CE_RXOVER 0x0001 winbase.h も検出されます。

 そこで、CrateFileそのものが成功しているかどうかは事前に検査しておき、通常の読み出しを開始する前に検査して、エラー状態をクリアします。
DWORD cer;  COMSTAT cst;   int c1;
for(cer=1; cer; ) {
  ClearCommError(ComPortForm->rs->ComHandle, &cer, &cst);
  c1 = ComPortForm->rs->Read(rx_buf, 1024);
}
 これを通信開始のしょっぱなに挿入してエラー回復をさせると解決しました。通信途中のエラーに対処するためには同じようにすればいいでしょう。

..end