【问题标题】:Boost asio serial port writes corrupted data from 18 byteBoost asio串口从18字节写入损坏的数据
【发布时间】:2013-12-10 11:29:34
【问题描述】:

我在使用 boost 将数据写入串行端口时遇到问题。 我从这里使用稍微修改的 minicom_client 类: https://code.google.com/p/vkbrd/source/browse/trunk/src/Dg5Emulator/MiniComClient.h https://code.google.com/p/vkbrd/source/browse/trunk/src/Dg5Emulator/MiniComClient.cpp

消息中的前 17 个字节发送良好,但其余字节替换为:

FD FD FD FD AB AB AB AB AB AB AB AB EE FE EE FE 00 00 00 etc

消息长度正确。

当我打电话时

for (int i = 0; i < 128; ++i)
    miniComClient.do_write(i);

我在第二面收到这个:

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F FD FD FD FD AB AB AB AB 
AB AB AB AB EE FE EE FE 00 00 00 00 00 00 00 00 2E F1 5C 42 BD 8B 07 18 
40 6D C1 03 E8 9E 40 02 00 00 00 00 00 00 00 00 04 00 00 00 01 00 00 00 
F4 62 00 00 FD FD FD FD 40 54 40 02 FD FD FD FD AB AB AB AB AB AB AB AB 
00 00 00 00 00 00 00 00 2F F1 5C 43 BF 8B 07 18 A0 A3 3B 02 38 A5 3B 02 
00 00 00 00 00 00 00 00 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
FD FD FD FD AB AB AB AB AB AB AB AB EE FE EE FE 00 00 00 00 00 00 00 00 
2E F1 5C 42 BD 8B 07 18 40 6D C1 03 E8 9E 40 02 00 00 00 00 00 00 00 00 
04 00 00 00 01 00 00 00 F4 62 00 00 FD FD FD FD 40 54 40 02 FD FD FD FD 
AB AB AB AB AB AB AB AB 00 00 00 00 00 00 00 00 2F F1 5C 43 BF 8B 07 18 
A0 A3 3B 02 38 A5 3B 02 00 00 00 00 00 00 00 00   

我有三次检查波特率、停止位和奇偶校验。

有没有办法改变发送缓冲区的大小?也许这是其他一些问题。

【问题讨论】:

  • 请在您的问题中包含相关的源代码
  • 我添加了指向标头和源的链接,并在我的回答中解释了修改。

标签: boost serial-port boost-asio send


【解决方案1】:

0xfdfdfdfd、0xababababa 和 0xfeeefeee 等值是 magic numbers

换句话说,您正在查看从堆中分配的未初始化内存。这是串行端口编程中一个非常标准的错误,假设您通过一次读取获得整个消息。只有当你调试你的程序时才会发生这种情况,它会减慢它的速度。绝不会在全速运行时,串行端口是非常慢的设备。您必须注意 read_complete() 函数中的bytes_transferred,并且在收到所有字节之前解释接收到的数据。这需要跟踪总数据,缓冲部分数据,并清楚了解何时收到完整响应。

数据变成垃圾的字节值也是一个幻数。 0x10 是换行控制字符的 ASCII 码。这通常用作消息结束指示器。请务必将您在线路另一端使用的任何软件配置为不检查行终止符,而仅显示它实际接收到的字节。

【讨论】:

  • 我用RealTerm和Hercules工具接收对方的数据,所以这个问题和数据发送有关。感谢您指出魔术数字。我正在进一步搜索。
  • 再次感谢您,但是当我将呼叫更改为仅发送 0x02 时,它会在同一个地方中断,因此换行符在这里不是问题。
【解决方案2】:

这个问题的原因是我对原始代码的“轻微”修改。

我想让整个字节数组的编写更简单(而不是在循环中调用 do_write()),所以我添加了方法:

void miniComClient::do_write_buffer( QByteArray msg )
    bool write_in_progress = !writeMsgs.empty(); // is there anything currently being written? 

    for(int i = 0; i < msg.size(); ++i)
        writeMsgs.push_back(msg[i]); // store in write buffer 

    if (!write_in_progress) // if nothing is currently being written, then start 
            write_start();
}

但最糟糕的是我尝试优化事物,所以我将 write_start() 修改为类似这样(发送缓冲区中的所有内容而不是下一个字节):

void miniComClient::write_start( void )
{
    // Start an asynchronous write and call write_complete when it completes or fails 
    boost::asio::async_write(serialPort, 
            boost::asio::buffer(&writeMsgs.front(), writeMsgs.size()), 
            boost::bind(&miniComClient::write_complete, 
            this, 
            boost::asio::placeholders::error));
}

这是一个可怕的错误,因为 writeMsgs 是 std:deque 类型,因此它不会连续存储在内存中,因此它会从我想要的位置发送一些字节,然后发送垃圾。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-24
    • 1970-01-01
    • 2020-08-05
    • 1970-01-01
    相关资源
    最近更新 更多