0

私はC#とシリアル通信の世界に不慣れです。いくつかのチュートリアルを読んだ後、私はなんとかコミュニケーションを機能させることができました。私はここで別の同様の質問をしましたが、正しい質問をしたとは思いません。最後の質問で与えられたアドバイスに従い、コードを少し変更して、マイクロコントローラーから次のようなシリアルメッセージを送信するようにしました。

SxxxxxxxxxxxxxxxxxxxxxxxxE

xは、さまざまな数値、プラス記号とマイナス記号、およびコンマを表します。私が送信する文字列は常に同じ長さで、常にSで始まり、Eで終わります(これが悪い場合は変更できます)。私が抱えている問題は、シリアルラインを読み込もうとすると、一度にメッセージの一部しか表示されないため、次のようになります。

Sxxxxxxx
xxxxx
xxxxESxxx

この情報をマイクロコントローラーから継続的に送信していますが、特定の時間にのみアクセスしたいので、メッセージのすべての部分を受信し、それを元に戻してから返す関数を作成しようとしています。働き。問題は、現時点ではそれをどのように行うのかわからないということです。

どんな助けでも大歓迎です!

これは私が遊んでいるコードです:

    SerialPort serialHC = new SerialPort(); // serial connection dealing with Hand Controller

     public string receiveCommandHC()
    {

        string messageHC = "";
        if (serialHC.IsOpen)
        {
            //serialHC.DiscardInBuffer();
            //messageHC = serialHC.ReadLine();
            messageHC = serialHC.ReadTo("*");
            //tempMsgHC = serialHC.ReadTo("*");
            //i = tempMsgHC.IndexOf("S");
            //tempMsgHC.Remove(0,i);
            //messageHC = tempMsgHC;

            //serialHC.Read(bufferHC = new byte[serialHC.BytesToRead], 0, serialHC.BytesToRead);
        }
        return messageHC;

以前はメッセージの終わりを「*」にしていました

ここで例をたどってみたところ、これが私が得たものです。 受信したシリアルメッセージ

これは私が送信しているものです(パテを使用してチェックします) ここに画像の説明を入力してください

4

1 に答える 1

2

データを受け取ったとき、実際に行動することはできないようです。必ずしも完全なメッセージがあるとは限りません。したがって、完全なメッセージがあることが検出されるまで、読んだ内容をバッファリングする必要があります。

これを行うためのより効率的な方法があるかもしれませんが、私はそれらにあまり精通していません。したがって、これを処理するための単純なアルゴリズムがあります。単純なステートマシンとして実装できます。

初期化:

  1. 可能な限り最大のメッセージを保持するのに十分な大きさのバッファーを割り当てます。これにより、メッセージを処理する準備ができるまで、受信データを読み込んでいる間、メッセージが保持されます。

  2. データを読み込むための固定サイズのバッファを割り当てます。

  3. 「メッセージ待ち」状態に入ります。

メッセージを待っています:

  1. 「S」が見つかるまで、またはメッセージの終わりに達するまで、各記号を読んでください。
  2. 「S」が見つかった場合は、「メッセージを読み込んでいます」状態に入ります。
  3. 「S」が見つからない場合は、次のメッセージを待ちます。

メッセージを読む:

  1. 「E」が見つかるか、メッセージの終わりに達するまで、データ内のすべてのシンボルをメッセージバッファにコピーします。
  2. 「E」が見つかった場合は、メッセージバッファの内容を処理するようにスケジュールし、それをクリアして、「メッセージを待機中」状態にします。
  3. 「E」が見つからない場合は、次のメッセージを待ちます。

アルゴリズムの本質を捉えたコードは次のとおりです。

enum ReadState { Waiting, Reading, Finished }
static string ReadMessage(SerialPort port)
{
    var messageBuffer = new StringBuilder("S");
    var state = ReadState.Waiting;
    while (state != ReadState.Finished)
    {
        switch (state)
        {
        case ReadState.Waiting:
            if (port.ReadChar() == 'S')
            {
                state = ReadState.Reading;
            }
            break;
        case ReadState.Reading:
            messageBuffer.Append(port.ReadTo("E"));
            state = ReadState.Finished;
            break;
        }
    }
    return messageBuffer.ToString();
}

私は当初、これをはるかに低いレベルで考えていましたが、SerialPortクラスにはこれを少し簡単にするいくつかのメソッドがあるようです。

于 2012-01-28T07:10:38.917 に答える