如何在C#中向串行设备发送字节?

如何在C#中向串行设备发送字节?,c#,serial-port,C#,Serial Port,我有一个设备,它使用串行(通过USB适配器)与我的电脑接口。我真的很难让它在C#中很好地播放。我知道它工作正常,因为供应商提供的软件按预期运行。我还知道,由于测试模式反复发送“OK”,我能够使用代码接收数据 这是我的密码: private SerialPort port; public SerialConnection() { this.port = new SerialPort("COM3", 38400, Parity.None, 8, StopBi

我有一个设备,它使用串行(通过USB适配器)与我的电脑接口。我真的很难让它在C#中很好地播放。我知道它工作正常,因为供应商提供的软件按预期运行。我还知道,由于测试模式反复发送“OK”,我能够使用代码接收数据

这是我的密码:

    private SerialPort port;

    public SerialConnection()
    {
        this.port = new SerialPort("COM3", 38400, Parity.None, 8, StopBits.One);
        this.port.WriteTimeout = 2000; port.ReadTimeout = 2000;

        this.port.Open();

        this.port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
    }

    public void SendCommand(byte[] command)
    {
        this.port.Write(command,0,command.Length);
        string chars = "";
        foreach (byte charbyte in command) chars += (char)charbyte;
        Console.WriteLine(" -> " + chars);
    }

    void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        string data = this.port.ReadLine();
        Console.WriteLine(" <- " + data);
    }
但似乎没有什么东西被送回

我不知道下一步该怎么办。有人有什么建议吗


对于一个次要问题,我发布了一些PortMon日志。我认为它们在这里可能也很有用,因此它们是:

  • -过滤掉所有
    IOCTL\u SERIAL\u GET\u COMMSTATUS
    条目

  • 你试过换房子吗?在接收数据之前,设备可能需要在控制引脚上进行一些握手。

    您应该打开RtsEnable或DtrEnable属性,设备将忽略您发送的任何内容,也不会从这些信号中在线检测到您时发送回任何内容。不过,将握手属性设置为RTS应该可以做到这一点

    请注意,ReadLine()方法将一直阻塞,直到它获得换行符为止。您没有发送一个,因此您也无法取回一个。使用Read()将是一个更好的测试


    首先使用已知的工作程序进行一些基本的故障排除,消除布线问题、错误的波特率或设备不回显。使用超级终端或油灰。

    每个RS-232设备都需要使用某种机制来通知对方正在进行的通信。有三个基本机制:

    • 基于硬件的RTS/CTS通过两条专用线路,通常用于控制单个数据块的发送
    • 基于硬件的DTR/DSR通过两条专用电线,通常用于控制整个通信会话
    • 通过一对专用字符(请注意,在这种情况下,需要对数据进行编码以防止与控制字符发生冲突)实现基于softwa的XON/XOFF
    (开始更新)

    旧版应用程序中的初始队列长度和超时:

    1  IOCTL_SERIAL_SET_QUEUE_SIZE  InSize: 1024 OutSize: 1024
    2  IOCTL_SERIAL_SET_TIMEOUT  RI:2000 RM:0 RC:2000 WM:0 WC:2000
    
    而你没有设置它们。尝试使用和设置队列大小。同样,使用和设置超时

    (完)

    在您的情况下,传统应用程序会:

    12  IOCTL_SERIAL_CLR_RTS
    13  IOCTL_SERIAL_SET_DTR
    
    16  IOCTL_SERIAL_SET_HANDFLOW  Shake:1 Replace:0 XonLimit:0 XoffLimit:0
    18  IOCTL_SERIAL_SET_RTS
    …
    21  IOCTL_SERIAL_CLR_RTS
    
    当你这样做时:

    12  IOCTL_SERIAL_CLR_RTS
    13  IOCTL_SERIAL_CLR_DTR
    
    16  IOCTL_SERIAL_SET_HANDFLOW  Shake:0 Replace:0 XonLimit:4096 XoffLimit:4096
    
    您没有设置DTR(数据终端就绪)信号,因此设备不希望串行线路上有任何数据或命令。因此设置为
    true

    第二个问题是你没有打开握手。传统应用程序可以:

    12  IOCTL_SERIAL_CLR_RTS
    13  IOCTL_SERIAL_SET_DTR
    
    16  IOCTL_SERIAL_SET_HANDFLOW  Shake:1 Replace:0 XonLimit:0 XoffLimit:0
    18  IOCTL_SERIAL_SET_RTS
    …
    21  IOCTL_SERIAL_CLR_RTS
    
    当你这样做时:

    12  IOCTL_SERIAL_CLR_RTS
    13  IOCTL_SERIAL_CLR_DTR
    
    16  IOCTL_SERIAL_SET_HANDFLOW  Shake:0 Replace:0 XonLimit:4096 XoffLimit:4096
    
    通过设置为打开它

    此外,您似乎经常打开、关闭和重新配置串行端口。尝试设置端口,然后在整个会话中使用相同的
    SerialPort
    实例。不要尝试重新打开它,因为这将导致重新配置物理端口引脚的状态

    串行通信不是魔术,但它对设置非常敏感,各种设备需要特殊设置和处理。命令的正确时间也可能是一个问题

    如果您确实有一些设备的技术文档,请务必阅读两遍,并在第一时间遵守。至少应正确记录握手模式、命令等

    如果您没有任何文档,请尝试逐一消除差异


    更新:发送和接收数据

    您编写了发送命令
    “Ping”
    (从十六进制解码为ASCII)。然而,您并没有提到发送和命令终止序列。通常,串行设备期望一个行尾序列(通常是CR LF)作为命令的终止。在设备接收到包括line end在内的完整命令之前,它无法回复

    通过调用
    ReadLine
    ,您正在处理数据接收事件-但是,在该位置,您不能期望有完整的数据行(即,包括能够检测到完整行的行端)。您应该检查提供的事件参数并逐字节读取输入

    创建一个包装器类是一个好主意,它将提供定制的发送命令、接收响应、发送数据和接收数据功能。包装器必须在内部与代码的其余部分异步工作。这样,您将拥有一个可用的自定义API和一个性能良好的串行端口处理

    请注意,
    SerialPort.NewLine
    属性用于指定行尾序列的外观。(在您的另一个问题中,您提到您试图将其设置为特殊字符集。这确实是错误的。)


    有一段时间我是串行通信英雄(那时我们没有vmware,只有两台486驱动的PC和一对直接连接的调制解调器来开发和调试通信应用程序:-),但我希望这至少有一点帮助

    最后但并非最不重要的是一些常用术语:

    • DTE-数据终端设备=您的计算机
    • DCE-数据通信设备=您的设备,例如调制解调器
      • 汤姆

        我也有过类似的问题

        我要打赌的是,ReadLine()只有在收到一个\r\n或某个.NET认为是新行的内容后才会返回。

        在您的日志中,我没有看到Winbird报告任何新行字符,我相信应用程序正在逐字节读取,而不是等待换行

        因此,您可以向它发送许多字节的数据,它将继续阻塞,直到收到正确的新行字符

        所以给SerialPort.Read一个尝试,一次读取一个字节作为启动器

        public int Read (
        byte[] buffer,
        int offset,
        int count
        
        )

        如果这不能修复它,您可能需要考虑下面的

        我的一些问题通过添加一些Thread.Sleep()得到了解决,因为我意识到PC的UART速度不快