Windows CE 6.0 デバイスでのシリアル通信にOpenNETCF.IO.Serial (オープン ソース、こちらのシリアル コードを参照) を使用するアプリケーションを作成しています。このアプリケーションは、Compact Framework 2.0 の C# でコーディングされています。これから説明する問題がこれらの詳細に特に関連しているとは思いませんが、その点で間違っていることが証明される可能性があります.
私が抱えている問題は、デバイス自体が再起動されるまで、一見ランダムに (断続的な問題として、まだ確実に複製できないという意味で)、データの送信または受信に失敗することです。Windows CE デバイスは、まったく異なるアプリケーションを実行するシステムと通信します。この他のシステムを再起動し、通信ケーブルを切断/再接続しても、この問題は解決されないようで、Windows CE デバイスを再起動するだけです。
この問題が発生する唯一の兆候は、OpenNETCF の起動 (OpenNETCF.IO.Serial クラスで "TxDone();" を探します) からの TxDone イベントの欠如と、接続されているという事実を知っているときにデータが受信されないことです。システムがデータを送信しています。
当社のシリアル通信では、1 ~ 255 (0x01 ~ 0xFF) の任意の文字値を送受信できます。Null 値は破棄されます。
私のシリアル設定は、38400 ボー、8 データ ビット、パリティなし、1 ストップ ビット (38400、8n1) です。入力および出力バッファ サイズを 256 バイトに設定しました。メッセージは可変長であるため、DataReceived イベントは 1 つ以上の文字を受信するたびに発生し、出力バッファーに 1 つ以上のバイトがある場合に送信が発生します。
ハンドシェイクは使用されません。これは RS422 であるため、RX+、RX-、TX+、TX- の 4 つの信号のみが使用されています。
「DataReceived」イベントを受け取り、入力バッファーからすべてのデータを読み取り、コード内に独自のバッファーを作成して、DataReceived イベントの外で暇なときにそれを解析します。コマンド メッセージを受信すると、クイック確認メッセージを返信します。他のシステムは、Windows CE デバイスからコマンド メッセージを受信すると、クイック確認メッセージを返信します。確認メッセージは単純な「はい、了解しました」として意図されているため、それ以上の返信はありません。私のコードでは、複数のスレッドを介して送受信するため、lock キーワードを使用して、複数のスレッドで複数のメッセージを同時に送信しないようにしています。コードを再確認したところ、どのロックにもかかっていないことがわかりました。
この時点で、空でないときに入力バッファーから読み取って送信バッファーに書き込むのではなく、変数やプロパティを設定する必要があるかどうかなど、シリアル通信のしくみについて明らかな何かを継続的に見逃していないかどうか疑問に思っています。
洞察、チェックするオプション、提案、アイデアなどは大歓迎です。これは私が何ヶ月も自分で取り組んできたことです。ここで受け取った回答やコメントがこの問題の解決に役立つことを願っています. 前もって感謝します。
編集、2011 年 2 月 24 日:
(1) Windows CE デバイスが通信しているシステムの起動時にのみエラーを再現できるようであり、起動するたびに再現できるわけではありません。信号も調べましたが、コモンモード電圧は変動しますが、システムの起動時に発生するノイズの振幅は、問題が発生するかどうかとは関係ないようです。 -問題が再発したピークまで)。
問題はますますハードウェアに関連しているように聞こえますが、私が見ている症状の原因を突き止めようとしています。少なくとも私が到達できた場所では、実際にハードウェアが故障またはシャットダウンしているようには見えないためです。信号を測定します。申し訳ありませんが、ハードウェア部品の部品番号はお答えできませんので、使用されている部品についてはお尋ねにならないでください。
(2) @ctacke の提案に従って、保守性のためにすべての送信が同じ場所を通過するようにしました。私が入れたスレッドセーフは基本的に次のとおりです。
lock(transmitLockObj)
{
try
{
comPort.Output = data;
}
[various catches and error handling for each]
}
(3) 38400 ボーで約 300 ミリ秒の時間間隔で 10 バイト未満の送受信が行われたテストで、UART OVERRUN エラーが発生しました。エラーが発生すると、次のループ反復に進み、ReadFile を実行せず、TxDone イベント (またはその他の行チェック手順) を実行しません。また、ポートを閉じて再度開いても問題が解決しないだけでなく、デバイスがまだ実行されている間にソフトウェアを再起動しても何も起こりません。ハードウェアの再起動のみ。
私の DataReceived イベントは次のとおりです。
try
{
byte[] input = comPort.Input; //set so Input gets FULL RX buffer
lock(bufferLockObj)
{
for (int i = 0; i < input.Length; i++)
{
_rxRawBuffer.Enqueue(input[i]);
//timer regularly checks this buffer and parses data elsewhere
//there, it is "lock(bufferLockObj){dataByte = _rxRawBuffer.Dequeue();}"
//so wait is kept short in DataReceived, while remaining safe
}
}
}
catch (Exception exc)
{
//[exception logging and handling]
//hasn't gotten here, so no point in showing
}
ただし、WriteFile 呼び出しがタイムアウトした直後に、テストで初めて UART OVERRUN エラーが発生し始めました。正直なところ、自分のコードが UART OVERRUN 状態を引き起こしていることがわかりません。
考え?ハードウェアまたはソフトウェア関連で、チェックできると思われるものはすべてチェックしています。