5

マイクロコントローラーをデスクトップ上のプログラムと通信させようとしています。両端で Xbee 無線とのシリアル ポート接続を使用しています。

マイクロコントローラーからデスクトップに何かを送信し、デスクトップ上のプログラムがマイクロコントローラーに何かを送信すると、通信は正常に機能します。

ただし、デスクトップ プログラムが特定の応答を送信するまで、コントローラーからデスクトップ プログラムに継続的に情報を送信する必要がある場合、それは機能しません。

これが私が話しているコードです:

    unsigned char ans = 'N';
    unsigned int count = 0;

    void main(void)
    {


        while(1)
        {
            if(count == 0)
            {
                Configure();
                count = 1;
            }

                  //there is some more code here but is irrelevant to the serial communication

         }

    }


void Configure()
{


    //Repeat this until the user accepts the sent string as correct
    while(ans == 'N')
    {

        BuildString();
        Send();
        Receive();
    }
}

void Send()
{
    unsigned int i;

    TMOD = 0x20;
    TH1 = 0xFD;
    SCON = 0x50;
    TR1 = 1;

    for(i=0; i<4; i++)
    {
        SBUF = toSend[i];
        while(TI == 0);
        TI = 0;
    }   

}

void Receive()
{
    unsigned int j;

    TMOD = 0x20;
    TH1 = 0xFD;
    SCON = 0x50;
    TR1 = 1;


    for(j=0; j<2; j++)
    {
        while(RI == 0);
        Received[j] = SBUF;
        RI = 0; 
    }


    if(count == 0)
        ans = Received[1];

    else
    {   
        RunType = Received[0];
        Move = Received[1];
    }


}

BuildString() 関数は、いくつかのセンサー入力に基づいて単純に文字列を構築します。通常、送受信関数は問題なく動作しますが、上記の Configure() 関数のように、連続して送受信する必要がある場合は機能しません。

助言がありますか?本当に感謝しています。

4

2 に答える 2

4

問題は、送信機能と受信機能の両方がポーリングされ、ブロックされていることです。receive 関数を呼び出すと、完全なメッセージが受信された後にのみ返されます。送信機能についてはディトしますが、送信の場合、期間はおそらく短くなります(プログラムは、送信するメッセージがある場合にのみ送信を呼び出すのが一般的ですが、受信はメッセージが到着するまで何日も待つことができます.

非同期通信が必要な場合は、割り込みベースの通信を使用するのが最善です。少なくとも受信用で、理想的には送信と受信の両方です。

ポーリングされた通信を使用してこれを実装することもできますが、次の文字をバッファから読み書きするために、文字が受信可能かどうか (または tx-empty かどうか) をチェックする関数を作成する必要があります。

割り込みベースの通信の利点は次のとおりです。

  • 全二重
  • 使用される CPU 時間が短縮されます (待機ループは必要ありません)。
  • 電力が少ない (CPU が低電力/スタンバイ モードになり、割り込みでウェイクアップできるようになります。ポーリングには常にフル パワーが必要です)

最初のステップとして、割り込みベースの受信を実装 (または取得) することをお勧めします。送信機能がまだブロックされている場合でも、最小限の労力で全二重操作が可能になります。OS (rtos/scheduler) を持っていない場合は、同期メカニズムを考える必要があります。最も単純な形式は、使用可能なメッセージがある場合は受信側でメッセージを処理し、(完全な) メッセージがない場合はすぐに返すことです。

幸運を。

コメントの後に編集 する メッセージごとに、コントローラーから送信されたメッセージにデスクトップが反応している場合、動作しているように見えることがあります。コントローラーの受信側に大きな FIFO バッファー (つまり 64 バイト) がある場合、これは機能する可能性があります。私が知っているほとんどのコントローラーには、これがありません。多くの場合、文字バッファーは 1 つしかありません。これは、レジスタの OVERFLOW ビットを使用して検出できます。これが設定されている場合、文字は受信時に失われます。

いくつかのユースケース: * 一度に 2 つのメッセージを送信したい (例: init + do_something)。PC は最初のメッセージに応答しますが、コントローラーはまだ送信中であり、ほとんどのデータをドロップします。* コントローラーが receive() 関数を実行する前に、PC が送信を開始します。パケットの先頭にあるデータが失われる可能性があります * 通信が中断されると、デッドロックが発生する可能性があります (つまり、コントローラーとデスクトップの両方が相手側から何かが送信されるのを待っています。

診断するには、オーバーフロー ビットを確認します。設定されている場合は、データが失われているため、割り込み関数で作業する必要があります。可能であれば、両側を監視します (少なくとも状態。たとえば、送信用の LED が点滅し、受信用の LED が点滅します)。

rs232 モニターが役立つ場合があります (これには追加のポートが必要です。複数の rs232 ポートを監視してタイムスタンプを提供できる (フリーウェアを含む) アプリケーションは多数あります。したがって、通信の順序を観察できます。Google は私を見つけました :リンク;過去数年間、いくつかの同様のユーティリティを使用してきました。

于 2009-10-24T19:25:47.863 に答える
1

書かれたプログラムは4バイトを送信してから2バイトを読み取る必要があります(レジスタが正しいと仮定しますが、それがまったく機能するようになった場合はおそらく正しいでしょう)4バイトを再度送信します...おそらくそうではありません送信部分にぶら下がっていますが、受信側は常に2バイトの読み取りを待機しているため、何らかの理由で2バイトが入力レジスタに到着しない場合は、永遠に待機し続けます.

システムにストレスを与えると(バイトの送信が速すぎる)、入力バッファがオーバーフローし、バイトが失われる可能性がありますか?したがって、2バイトを取得することはありません。そして行き詰まります。

  1. 立ち往生している場所をデバッグできますか? それは実際に受信ループにありますか?
  2. 一度に 1 バイトずつ手動で送信できるように、PC からマイクロへの送信を調整できますか?
  3. micro と xbee インターフェースの間にハンドシェイクはありますか? それはマイクロによって抑制できますか?
于 2009-10-25T15:38:38.380 に答える