1

私はこの質問について少し確信が持てませんが、現在の設計で常に問題に遭遇しており、誰かがこれに対する別のアプローチを示すことができれば、本当に素晴らしいことです.

私のプログラムは、rs232 を介して非同期コマンドをデバイスに書き込みますが、受信したデータを常に読み取って反応します。

これはすべてうまく機能しますが、初期化フェーズでは、プログラムを続行させる前に、応答を待つ必要がある一連のコマンドを送信する必要があります。

さて、この部分は単純な C で行う必要があり、思いついたのはグローバル var と while ループを使用することだけでした。しかし、これは本当にきれいではないと思います。

これを疑似コードの例として取り上げます。

OnReceive(data){
 switch determineCommand(data)
   case CMD1:
      config.value1 = data.value1             
   case CMD2:
      config.value2 = data.value2
   default:
      print data
}

DoCommandChain(){
  Send(CMD1)
  If("Send(CMD1)" got its response){
    Send(CMD2)
  }
}

さて、問題は「XYが応答を受け取った場合」です-これを検出するためにいくつかの変数を使用したくないため、これは単なる指標であるため、Send(CMD1)の戻り値に依存できないためです。 CMD1 が送信されました - 受信された対応するものはありませんでした。

この混乱を良い方法で解決するために、何を検索/読むことができるか知りたいので、ここで質問しています。

今のところ、これに対する私の最善の考えは、特定の応答が受信された場合に監視するタイマー保護機能を何らかの方法でセットアップすることです。次に、この応答のステータスに応じて、次の応答に進むSendか、最後の応答を再試行します。

このような:

Instead of `Send(CMD1)` -> `DoUntilResponse(Send(CMD1),Timeout,NumberOfRetries)`

DoUntilResponse(function,Timeout,NumberOfRetries){
   registerExpectedResponse(CMD1, gotResponse) //awaiting some response for CMD1

   for(i=0 ; i!=Numberofretries; i++){
       if (Send(CMD1) == successfulSend ){
          while(not timeout){
             if gotResponse then break;
             }
          if gotResponse then break;
      }           
   }

}

編集:

明確にするために:シリアル接続や関数の起動方法について心配していませんOnReceive-これはすべてすでに機能しています。明確なアイデアが得られないのは、ポーリングを使用せずに、できれば純粋な C で上記の擬似コードを解決する方法です。

4

2 に答える 2

1

書き込み操作と読み取り操作が異なるスレッドで実行されると仮定すると、次のアルゴリズムを使用します。

スレッドを書き込みます。
    期待される応答を登録します。
    デバイスにパケットを送信します
    タイムアウトしてReceivedイベントを待ちます。イベントが設定されている場合は、続行します。タイムアウト -
    エラーを報告して終了します(または追加の試行を行います)。

スレッドを読み取ります。
受信したパケットごとに:
    入力バッファに追加します。
    バッファを分析します。有効な応答が含まれている場合は、「Received」イベントを設定し、
    書き込みスレッドを解放し、入力バッファをクリアして、読み取りを続行します。
    入力バッファに認識されないデータが含まれている場合は、エラーを報告し、バッファをクリアします
    そして読み続けます。
    入力バッファに期待される応答の始まりが含まれている場合、
    読み続けてください。

スレッド化とイベント通知はOS固有です。C ++コンパイラがマルチスレッドをサポートしていない場合は、Boostなどのポータブルライブラリを使用するか、OS固有のAPIを使用してください。シリアル通信はストリーム指向であるため、読み取りスレッドはストリーム解析ロジックを実装していることに注意してください。

編集。

「期待される応答を登録する」とは、「タイプXのコマンドがデバイスに送信される」という意味よりもいくつかのプログラム変数を設定することを意味します。この変数によると、読み取りスレッドはパケットを受信することを想定しています。パケットは、通信プロトコル(アプリケーション固有)に従ってデバイスから送信される必要があります。別の受信パケットは、一般的に有効である可能性がありますが、これはデバイスに送信されたばかりのコマンドへの応答ではないため、エラーとして処理する必要があります。

別の方法:予想される応答サイズを設定します。この場合、読み取りスレッドは予想される量のデータを受信すると、Receivedイベントを設定し、パケット認識タスクを送信者に任せます。

于 2012-11-27T15:24:54.263 に答える
0

これはオペレーティング システム固有です。Linux や Unix では、poll(2) (またはおそらくselect(2 ) のような多重化システムコールの使用を検討する必要があります。これは、ファイル記述子の最大数を制限するため、廃止されたと感じています。C10K問題を参照してください)。

C標準はシリアルポートについて知りません。

于 2012-11-27T15:16:33.770 に答える