同一台Windows计算机上的串行端口通信不起作用

本文关键字:串行端口 通信 不起作用 计算机 Windows 一台 | 更新日期: 2023-09-27 18:05:26

对不起,快速问题:

我有这个硬件设置:

同一台机器:"Com3" -> USB -> 转串行 ->

转 USB -> "Com4">

我按照MSDN SerialPort Class和MSDN SerialPort.ReadLine((来构建这个例程:

SerialPort SendSerialPort = new SerialPort("Com3", 9600);
SerialPort ReceiveSerialPort = new SerialPort("Com4", 9600);
SendSerialPort.Open();
ReceiveSerialPort.Open();
SendSerialPort.WriteLine("Test");
var message = ReceiveSerialPort.ReadLine(); // control stops here
SendSerialPort.Close();
ReceiveSerialPort.Close();
Console.WriteLine(message);

但是,当我倾向于ReadLine()时,我的控制停止并等待。我没想到。

我希望收到字符串Test并将其分配给我的var message。你能告诉我我在这里做错了什么吗?

编辑

我使用串行端口实用程序应用程序测试了我的硬件,它工作得很好

同一台Windows计算机上的串行端口通信不起作用

我已经改变了你链接的例子:

要实际运行两个端口来回读取和写入,您实际上需要实现线程来读取和写入两者。

使用计时器是个好主意。

public static void Main()
{
    SerialPort SendSerialPort = new SerialPort("Com3", 9600);
    SerialPort ReceiveSerialPort = new SerialPort("Com4", 9600);
    StringComparer stringComparer = StringComparer.OrdinalIgnoreCase;
    Thread readThread = new Thread(Read);
    // Set the read/write timeouts
    _serialPort.ReadTimeout = 500;
    _serialPort.WriteTimeout = 500;
    SendSerialPort.Open();
    ReceiveSerialPort.Open();
    bool _continue = true;
    readThread.Start();
    Console.Write("Name: ");
    name = Console.ReadLine();
    Console.WriteLine("Type QUIT to exit");
    while (_continue)
    {
        message = Console.ReadLine();
        if (stringComparer.Equals("quit", message))
            _continue = false;
        else
            SendSerialPort.WriteLine(String.Format("<{0}>: {1}", name, message));
    }
    readThread.Join();
    SendSerialPort.Close();
}
public static void Read()
{
    while (_continue)
    {
        try
        {
            string message = ReceiveSerialPort.ReadLine();
            Console.WriteLine(message);
        }
        catch (TimeoutException) { }
    }
}
通常,

写入数据中会有一个开始值和结束值,以告诉另一个端口消息已完成,并且端口还会验证它们是否正在读取它们应该读取的数据,通常使用如何处理该数据的命令。(超出此问题的范围(。

同样缺乏和重要的是您的港口的初始化。

我更喜欢使用默认构造函数(仅首选项(

SerialPort Constructor ()

然后设置任何值,如下所示:

_serialPort.BaudRate = SetPortBaudRate(_serialPort.BaudRate);
_serialPort.Parity = SetPortParity(_serialPort.Parity);
_serialPort.DataBits = SetPortDataBits(_serialPort.DataBits);
_serialPort.StopBits = SetPortStopBits(_serialPort.StopBits);
_serialPort.Handshake = SetPortHandshake(_serialPort.Handshake);

所有构造函数都将给出以下值:

如果未指定任何属性值

,则此构造函数使用默认属性值。例如,DataBits 属性默认为 8,奇偶校验属性默认为 None 枚举值,StopBits 属性默认为 1,默认端口名称为 COM1。

甚至握手也有默认值。如果你看一下源代码。

private const Handshake defaultHandshake = Handshake.None;

你的代码问题就在这一行

var message = ReceiveSerialPort.ReadLine();

你阻止你的代码等待一行,如果该行永远不会到达,它将永远保留在这里或值设置为ReadTimeout

那么为什么队伍从来没有到达呢?

问题可能是 WriteLine("Test"); 中的错误,您应该处理错误,或者可能是您的 in 阻止了您的代码ReadLine()WriteLine("Test")设法通过之前,您可以在两者之间插入一个Thread.Sleep(100),但这并没有真正改善代码。

注意:您的代码有时也会按原样工作,具体取决于这些争用条件。

这种从串行端口同步/阻塞读取在代码中似乎很简单,只有一行;但它会在您的通信协议中产生很多负面的副作用。

一个更好的解决方案(考虑到你喜欢从微控制器读取/写入数据(是按照Yvette的建议使用线程,或者使用异步读取Stream.BeginRead(Byte[],Int32,Int32,AsyncCallback,Object(,我更喜欢。

异步读取将在串行端口上传入某些内容时引发事件。这种编程策略的基本思想是不做步骤编程,而是期望结果,然后正确处理它。

在异步读取AutoResetEvent的通信协议中非常有用,因此您发送了一些东西,然后启动AutoResetEvent,如果异步预期结果到达,您将设置此事件并且您的代码可以继续,如果没有到达,AutoResetEvent将超时,您可以处理此问题。

当有可用数据时,它无法阻止。 您发送的内容要么卡在传输缓冲区中,要么由于接线错误而丢失,要么触发错误或被忽略。 如果它适用于另一个程序,那么接线错误就不会成为问题。

请记住,仅设置波特率是不够的,还必须使用设置数据位、奇偶校验和停止位属性来匹配设备设置。不匹配可能会触发错误,只有在为 ErrorReceived 事件编写事件处理程序时才能看到这种错误。 永远不要跳过该事件,如果您从不检查,可能会出现混淆问题。

最重要的是,握手属性必须正确设置。 正确的值取决于端口如何连接在一起,不连接它们太常见了。 首先将其设置为"握手。无",以便 DSR 和 CTS 信号的错误状态不会阻止接收,DTR 和 RTS 信号的错误状态不会阻止传输。 请注意,另一个程序启用硬件握手是很常见的,不匹配肯定会导致通信停止。

如果使用同步读取而不是 DataReceived 事件,则通常应处理设备未响应的可能性。 要么是因为它已断电,根本没有连接或出现故障。 为此使用 ReadTimeout 属性,以便程序无法挂起。 瞄准高点,10000毫秒是一个合理的选择。

请注意这个问题的随机性,使用另一个程序可以轻松正确配置端口,现在它会突然工作。 请注意,启动线程不会执行任何操作,现在将是该线程卡住,Join(( 调用将死锁。