【问题标题】:C++ Serial port data received incorrectlyC++ 串口数据接收不正确
【发布时间】:2021-12-27 00:18:45
【问题描述】:

从串口接收到的数据,不正确,有时变了!

  if (WaitCommEvent(hSerial, &eventMask, NULL))
{
    if (ReadFile(hSerial, &input, 14, &bytesRead, NULL) !=0)
    {
        for (int i = 0; i < sizeof(input); i++)
        {
            cout << hex <<(int)input[i]<<endl;
        }
    }
    else
    {
        cout << "error reading file\n";
    }
}
else
{
    cout << "error waiting for comm event\n";
}

数据是:

50
ffffffaf
0
e
2
42
2
b
d
0
1
1
50
ffffffe5

当我使用 Pyserial 获取数据时,数据是:

50AF000E0242020B0D00010150E5

如您所见,我得到了额外的 'ffffff' 并错过了一些 '0'!而且因为遗漏了数据,有时'af'变成了'2f'!

我的代码有什么问题吗?

【问题讨论】:

  • 你为什么忽略bytesRead
  • 猜猜当你把一个值为0xAF的char转换成(int)时会发生什么?不,您不会获得带有 0xAF 的 int 值。
  • 如果inputchar 数组,请尝试将其声明为unsigned char 数组。例如:unsigned char input[32];
  • bytesRead 应该怎么做?永远是 14 岁!
  • 我使用 (int) 使其可读,否则显示的数据类似于 »♫☻

标签: c++ winapi serial-port


【解决方案1】:

问题不在于数据,数据本身很好。是你打印的数据有问题。

您没有考虑到 input 正在使用 signed char 类型,当分配给 signed int 时会得到 sign-extended。这就是在打印值为0xAF0xE5char 时,ffffffafffffffe5 中额外的fs 的来源,因为它们的高位在这两种情况下都是1 并且得到携带到扩展位中,例如:

0x50       =                            01010000
0x00000050 = 00000000 00000000 00000000 01010000
             <--------------------------^ 

0xAF       =                            10101111
0xFFFFFFAF = 11111111 11111111 11111111 10101111
             <--------------------------^ 

0xE5       =                            11100101
0xFFFFFFE5 = 11111111 11111111 11111111 11100101
             <--------------------------^ 

另一方面,无符号值是zero-extended

0x50       =                            01010000
0x00000050 = 00000000 00000000 00000000 01010000
             <-------------------------| 

0xAF       =                            10101111
0x000000AF = 00000000 00000000 00000000 10101111
             <-------------------------| 

0xE5       =                            11100101
0x000000E5 = 00000000 00000000 00000000 11100101
             <-------------------------| 

您也没有考虑到默认情况下,std::coutstd::hex 将仅使用 1 个十六进制数字打印数值 0..15,因此不会打印任何前导 0 十六进制数字。 ebd 是与0e0b0d 相同的数值。如果您想打印 0s,您必须告诉 std::cout 将值填充到至少 2 个十六进制数字。

试试这个:

char input[...];
...
if (ReadFile(hSerial, &input, 14, &bytesRead, NULL))
{
    for (int i = 0; i < bytesRead; ++i)
    {
       cout << hex << setw(2) << setfill('0') << static_cast<int>(static_cast<unsigned char>(input[i])) << endl;
    }
}

如果您将input 更改为使用unsigned char 而不是char,那么您可以删除该类型转换:

unsigned char input[...];
...
if (ReadFile(hSerial, &input, 14, &bytesRead, NULL))
{
    for (int i = 0; i < bytesRead; ++i)
    {
       cout << hex << setw(2) << setfill('0') << static_cast<int>(input[i]) << endl;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多