2

現在私の大学では、これらの古い 56k モデム間で通信を行っています。PC からモデムへのメッセージはシリアル ポートを経由するので、System.IO.Ports.SerialPort .NET クラスを使用することを考えました。

モデムと通信し、他のモデムにダイヤルし、それらを介して通信するためのかなり大きな C# アプリケーションを作成しました。2 つのモデム間の接続を確立するまでは、すべて正常に機能していました。これが起こると、両方のモデムが (当然のことながら) COMMAND モード (Hayes のコマンドをモデムに送信できる) から DATA モード (モデムに送信したすべてのデータが他のモデムに転送される) に切り替わります。

私のアプリケーションは、シリアルポートから物事を受信するだけでなく、物事を送信することもできます。接続されている両方の PC にインストールされます。しかし、アプリケーションに「Hello」などと入力すると、反対側で受信されません。そして、ここに奇妙な部分があります。シリアル ポートを介してメッセージを送信する方法を次に示します (「ポート」は SerialPort クラスのインスタンス、「データ」は文字列のインスタンスです)。

port.Write(data);

それでうまくいきます。それは働かなければなりません。特に、アプリケーションを一方に送信し、もう一方に PuTTy を使用すると、うまくいきます。有効なシリアル ポートに接続された PuTTy がメッセージを受信します。また、メッセージが最初のモデムに届くだけではないことも暗示しています。ネットワーク経由で他のモデムに送信され、他のモデムはシリアル ポートを介して受信 PC に送信します。しかし、それだけではありません。アプリケーションを使用して受信する場合、次のように SerialPort.DataReceived イベントを使用します (もちろん、メソッドはイベント ハンドラーに += されています)。

void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    //this message box should pop up if event hit:
    MessageBox.Show("Data from serial port received!");
    //calling my method to handle incoming message
    DataReceived((SerialPort)sender); 
}

また、モデム (受信 PC に接続されているもの) が COMMAND モードの場合に機能します。たとえば、「AT」Hayes のコマンドをモデムに送信すると (これは「ping」以外の何物でもありません)、モデムは「OK」と応答し、それを受信します。SerialPort.DataReceived イベントが発生します。しかし、このモデムが DATA モードの場合 (Hayes のコマンドを送信できない場合)、送信側モデムからメッセージを受信し、それをシリアル ポートに転送しますが、何もしません。イベントも発生しません。よく確認しました。

それは奇妙だ!

これは、モデムがメッセージをシリアルポートに送信する方法が、DATA モードと COMMAND モードでわずかに異なり、PuTTy が何らかの方法でそれを理解し、SerialPort クラスが理解していないという結論に達するだけです。

私は本当にこれを理解していません。

4

2 に答える 2

2

が正しく設定されていないSerialDataReceivedEventHandlerため、 は発火しませんでした。Handshake

私はハードウェア フロー コントロールを使用する必要がありましたがHandshake.RequestToSend、それは現在も機能しています。

于 2013-09-13T18:41:07.417 に答える
2

モデムがコマンド モードの場合、DataReceived イベントは発生しないと述べました。また、シリアル/モデム通信の個人的な経験を持つ人として、シリアル ポートからデータを収集するときにブロック操作を行っているとあえて言います。

これまで、.NET40 を使用してモデム通信を処理するために SerialPort クラスでいくつかのプロジェクトを実行しましたが、通信は期待どおりに機能しました。

私の最善の推測は、あなたのメソッドDataReceived((SerialPort)sender); データの受信をブロックしています。

受信したデータを収集するときにデッドロックを回避するために、ロック内のポートからデータを読み取りますが、それらをロックの外で処理し、処理が何かを実行して終了することを確認します (長いことを何も実行しないと、受信がハングします)、何かお気に入り:

void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    var com = sender as SerialPort;
    var lst = new List<byte>();

    if (com != null)
    {
        lock (com)
        {
            do
            {
                if (com.BytesToRead == 0) break;
                var one = com.ReadByte();
                if (one >= 0 && one < 256) lst.Add(Convert.ToByte(one));
            } while (one >= 0 && one < 256);

            // lst.ToArray(); // get bytes
        }

        // ... // do something with received data
    }
}

あなたはデータ処理に関する詳細を提供していないので、そのコード内にある種のブロックがあると推測することしかできません.

提供されたサンプルには、次の 2 つの主要なポイントがあります。

  1. データを排他的に読み取りますが、読み取るデータがある場合にのみ、データを待機しません
  2. ロック外で受信したデータをできるだけ速く処理し、関数の実行を終了する

また、提供されたコード (同様の形式) は常にマルチスレッド アプリで使用されていたため、メインの [MTAThread] 属性!

シリアル通信をトラブルシューティングする最速の方法の 1 つは、 http: //com0com.sourceforge.net/ から仮想シリアル ポート com0com をインストールし、 モデムを使用せずに直接通信を試みて、データ交換が機能することを確認することです。

実際にアプリケーションで使用できます。1 組の仮想 COM ポートをインストールし、アプリケーションを 1 つのシリアル ポートに接続し、パテを他のポートに接続します。パテに ATZ が表示されたら、OK で応答するだけです\r\n :) しかし、ピンの読み取りを使用している場合、パテはできません。少なくとも、パテからフラグを変更する方法がわかりません。

スレッドが少し古いことは承知していますが、フィードバックを歓迎します。

ハッピーコッディング。

于 2013-09-12T21:24:32.417 に答える