首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C# - SerialPort.read()速度问题

C# - SerialPort.read()速度问题
EN

Stack Overflow用户
提问于 2021-05-21 02:22:40
回答 1查看 99关注 0票数 0

我的代码旨在从串行设备获取数据,并将其内容打印到MS Forms应用程序。我使用的IDE是Visual Studio 2019 - Community。

设备确实发送了一个大小可变的数据包。首先,我必须解码数据包的“报头”,以获得进一步处理的关键信息,即第一个数据包通道和数据包长度。

由于数据包既不包含行结尾,也不包含末尾的固定字符,因此函数SerialPort.ReadTo()SerialPort.ReadLine()没有什么用处。因此,只能使用SerialPort.Read(buf,offset,count)

由于发送相当大的数据包(512字节)确实需要时间,因此我实现了一个计算所需等待时间的函数,该函数定义为(1000ms/baud-rate*(8*byte-count))+100ms

在测试时,我遇到了延迟,远远超过了期望的等待时间,因此为函数的不同部分实现了一个度量函数。

在常规情况下(具有所需的等待时间),我在控制台上的日志除外,如下所示:Load Header(+122ms) Load Data (+326ms) Transform (+3ms)

但只有少数数量可变的记录才是这样的,通常是10条,之后,执行时间就更糟糕了:

Load Header(+972ms) Load Data (+990ms) Transform (+2ms)

在这里您可以看到完整的函数:

代码语言:javascript
复制
private void decodeWriteResponse(int identifier, object sender, SerialDataReceivedEventArgs e)
    {
        /* MEASURE TIME NOW */
        long start = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();

        var serialPort = (SerialPort)sender;                    //new serial port object
        int delay = ComPort.getWaitTime(7);                     //Returns the wait time (1s/baudrate * bytecount *8) +100ms Additional
        Task.Delay(delay).Wait();                               //wait until the device has send all its data!
        byte[] databytes = new byte[6];                          //new buffer
        try
        {
            serialPort.Read(databytes, 0, 6);                    //read the data
        }
        catch (Exception) { };

        /* MEASURE TIME NOW */
        long between_header = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();

        /* Read the Data from Port */
        int rec_len = databytes[1] | databytes[2] << 8;         //Extract number of channels
        int start_chnl = databytes[3] | databytes[4] << 8;      //Extract the first channel

        delay = ComPort.getWaitTime(rec_len+7);                 //get wait time
        Task.Delay(delay).Wait();                               //wait until the device has send all its data!
        byte[] buf = new byte[rec_len-3];                       //new buffer

        try
        {
            serialPort.Read(buf, 0, rec_len-3);                  //read the data
        }
        catch (Exception) {}


        /* MEASURE TIME NOW */
        long after_load = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();

        /* Now perform spectrum analysis */
        decodeSpectrumData(buf, start_chnl, rec_len-4);

       /*MEASURE TIME NOW */
       long end = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
       Form.rtxtDataArea.AppendText("Load Header(+" + (between_header - start).ToString() + "ms) Load Data (+" + (after_load - between_header).ToString() + "ms) Transform (+" + (end - after_load) + "ms)\n");



        /*Update the Write handler */
        loadSpectrumHandler(1);

    }

导致此问题的原因是什么?我已经在Visual Studio中使用"debug“和"Release”独立测试了这一点,但没有区别。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-21 03:17:56

与其试图计算消息到达端口需要多长时间,为什么不直接在一个循环中读取数据,直到得到所有数据呢?例如,读取报头并计算消息大小。然后读取该字节数。例如:

代码语言:javascript
复制
// See if there are at least enough bytes for a header
if (serialPort.BytesToRead >= 6) {
    byte[] databytes = new byte[6];
    serialPort.Read(databytes, 0, 6);
    // Parse the header - you have to create this function
    int calculatedMsgSize = ValidateHeader(databytes);
    byte [] msg = new byte[calculatedMsgSize];
    int bytesRead = 0;
    while (bytesRead < calculatedMsgSize) {
        if (serialPort.BytesToRead) {
            bytesRead += serialPort.Read(msg, bytesRead,
                Math.min(calculatedMsgSize - bytesRead, serialPort.BytesToRead));
        }
    }
    // You should now have a complete message
    HandleMsg(msg);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67626023

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档