2

目前在我的大学里,我们正在这些旧的 56k 调制解调器之间进行通信。由于从 PC 到调制解调器的消息通过串行端口,我想使用 System.IO.Ports.SerialPort .NET 类。

我编写了相当大的 C# 应用程序来与调制解调器通信,拨号到其他调制解调器并通过它们进行通信。在我设法在两个调制解调器之间建立连接之前,一切都很好。发生这种情况时,两个调制解调器(应该如此)从 COMMAND 模式(我可以将 Hayes 的命令发送到调制解调器)切换到 DATA 模式(我发送到调制解调器的所有数据都被转发到另一个调制解调器)。

我的应用程序可以发送东西到串口,也可以从串口接收东西。它安装在两台连接的 PC 上。但是当我在我的应用程序中输入一些内容时,例如“你好”,另一端没有收到它。奇怪的部分来了。这是我通过串行端口发送消息的方式('port' 是 SerialPort 类的实例,'data' 是字符串的实例):

port.Write(data);

所以它有效。它必须工作。特别是,因为如果我使用我的应用程序一方面发送,另一方面使用 PuTTy 接收 - 它可以工作!连接到有效串行端口的 PuTTy 收到我的消息。它还暗示,不仅我的信息到达了第一个调制解调器;它通过网络发送到另一个调制解调器,然后另一个调制解调器通过串行端口将它发送到接收PC。但这还不是全部。当我使用我的应用程序接收时,我使用 SerialPort.DataReceived 事件,如下所示(当然方法已被 +=ed 到事件处理程序):

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 的调制解调器)处于命令模式时,它可以工作。例如,当我向调制解调器发送“AT”Hayes 的命令(这意味着只是一个“ping”)时,调制解调器会响应“OK”,然后我会收到它。SerialPort.DataReceived 事件触发。但是当这个调制解调器处于数据模式时(当我无法向它发送 Hayes 的命令时),它接收到来自发送调制解调器的消息,并将其转发到串行端口 - 什么都没有。事件甚至不会触发。我检查得很好。

有点奇怪!

这只是让我得出结论,调制解调器向串行端口发送消息的方式在 DATA 模式和 COMMAND 模式下略有不同,并且 PuTTy 以某种方式确实理解了另一种方式,而 SerialPort 类则没有。

我真的不明白这个。

4

2 回答 2

2

SerialDataReceivedEventHandler没有触发,因为没有Handshake正确设置。

我不得不使用硬件流控制,它Handshake.RequestToSend现在对我有用。

于 2013-09-13T18:41:07.417 回答
2

您说当调制解调器处于命令模式时 DataReceived 事件不会触发,作为在串行/调制解调器通信方面有个人经验的人,我敢说您在从串行端口收集数据时正在执行一些阻塞操作。

到目前为止,我已经完成了几个使用 SerialPort 类的项目来处理使用 .NET40 的调制解调器通信,并且通信按预期工作。

我最好的猜测是你的方法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
    }
}

您没有提供有关数据处理的详细信息,所以我只能猜测该代码中有某种块。

在提供的样本中,有两个要点:

  1. 独占读取数据,但只有当有数据要读取时,不要等待数据
  2. 尽快处理锁外接收到的数据并完成函数执行

此外,提供的代码(以类似的形式)总是在多线程应用程序中使用,因此 Main 上的 [MTAThread] 属性!

解决串行通信问题的最快方法之一可能是从 http://com0com.sourceforge.net/安装虚拟串行端口 com0com, 并尝试在没有调制解调器的情况下进行直接通信,以确保数据交换正常工作。

实际上你可以在你的应用程序中使用它。只需安装一对虚拟 com 端口,将您的应用程序连接到一个串行端口,将 putty 连接到另一个,当您在 putty 上看到 ATZ 时,只需回复 OK\r\n :) 但是如果您正在使用引脚读数,那么 putty 不能帮助你,至少我不知道从腻子改变标志的方法。

我知道该线程有点旧,但欢迎提供一些反馈。

快乐编码。

于 2013-09-12T21:24:32.417 回答