【问题标题】:Com port max speedCom 端口最大速度
【发布时间】:2014-08-11 19:48:24
【问题描述】:

我有一个硬件以以下形式向 com 端口发送数据:“HxxxxVxxxx”,其中 x = 数字:例如:(H1234V5678)。

我想问,我应该设置什么采样率才能尽快发送。 (波特率 9600,8 位,奇偶校验:无,停止位:1)。 用 Java 或 C# 编写的程序能够接收这些数据的整体,而不是部分。

每22ms发送一次数据,并接收这样的数据时:

2014-08-11 18:48:39.669  56 36 36 37 
2014-08-11 18:48:39.674  48 30 0D 0A 
2014-08-11 18:48:39.687  56 36 
2014-08-11 18:48:39.692  36 39 48 30 
2014-08-11 18:48:39.696  0D 0A 
2014-08-11 18:48:39.712  56 36 36 38 
2014-08-11 18:48:39.716  48 30 0D 0A 
2014-08-11 18:48:39.732  56 36 
2014-08-11 18:48:39.737  36 37 48 30 
2014-08-11 18:48:39.742  0D 0A 
2014-08-11 18:48:39.753  56 

但我想:

2014-08-11 18:48:39.600  56 36 36 37 48 30 0D 0A 
2014-08-11 18:48:39.622  56 36 36 37 48 30 0D 0A 
2014-08-11 18:48:39.644  56 36 36 37 48 30 0D 0A 
2014-08-11 18:48:39.666  56 36 36 37 48 30 0D 0A 
2014-08-11 18:48:39.688  56 36 36 37 48 30 0D 0A 

c#代码:

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff");
    int bytes = comport.BytesToRead;
    byte[] buffer = new byte[bytes];
    comport.Read(buffer, 0, bytes);

    File.AppendAllText(@"c:\file.txt", timestamp + "  "+ByteArrayToHexString(buffer) +"\n" + Environment.NewLine);
}

【问题讨论】:

    标签: c# serial-port port


    【解决方案1】:

    您收到的数据格式似乎与“HxxxxVxxxx”略有不同

    按照我阅读您的日志的方式,您收到的是“V66H0\r\n”。 (\r = 回车,\n = 换行)

    如果您可以保证所有单独的命令都以 \r\n (0x0D,0x0A) 结尾,那么您有两种选择:

    1. 创建一个缓冲区并不断添加,直到遇到 0x0D 0x0A,然后您可以将其作为一行处理。

    2. 您可以将代码更改为使用同步SerialPort.ReadLine() 方法,而不是使用异步SerialPort.DataRecieved 事件,该方法将一次读取整行。

    这显然是简化的,但它应该像这样工作:

    public bool KeepRunning = true;
    while(KeepRunning)
    {
        string command = serialport.ReadLine();
        processCommand(command);
    }
    

    其中serialport 是一个已经打开的SerialPort 对象,而processCommand 是一些可以处理整行的方法。

    【讨论】:

    • 我刚刚注意到\r\n 就在您发布此内容时。 @user3357505 这就是你在我的回答中提到的问题的解决方法。
    【解决方案2】:

    更改波特率不会给您想要的结果 . SerialPort 类(也不是任何基于 Stream 类试图模拟的类)保证接收到的确切数据量将是您请求的量。如果您想要 8 字节块,则需要缓冲传入的数据,并且每次获得 8 字节的数据时,您都会返回结果。

    您需要在读取串行端口和File.AppendAllText 之间放置一个层来进行缓冲,这样您就可以积累到 8 个字节的数据,然后再写入文件。

    private byte[] buffer = new byte[8];
    private int bufferOffset = 0;
    
    private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        int totalBytesToRead = comport.BytesToRead;
        int totalBytesRead = 0;
    
        while (totalBytesToRead > totalBytesRead)
        {
            //Chooses the remaining size in the buffer or the remaining bytes available to read, whichever is smaller.
            var bytesToRead = Math.Min(buffer.Length - bufferOffset, totalBytesToRead - totalBytesRead);
    
            var bytesRead = comport.Read(buffer, bufferOffset, bytesToRead);
    
            bufferOffset += bytesRead;
            totalBytesRead += bytesRead;
    
            //If we have filled our buffer write it out to the file.
            if (bufferOffset == buffer.Length)
            {
                string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff");
                File.AppendAllText(@"c:\file.txt", timestamp + "  " + ByteArrayToHexString(buffer) + "\n" + Environment.NewLine);
                bufferOffset = 0;
            }
        }
    }
    

    【讨论】:

    • 问题是,有时硬件发送:H1234V0 那只是 7 个字节,有时:H1234V5678 那就是 10 个字节
    • @user3357505 在您的示例文本中,您的十六进制始终以 OD OA 结尾(又名:\r\n)是否始终以该字符串结尾?
    • 是的。始终以 H 开头并以 \r\n 结尾
    • @user3357505 见Tremmors answer 然后,最好的办法是循环直到你看到\r\n 或使用ReadLine
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-09
    • 2012-12-24
    • 2011-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多