串行通信 C++ ReadFile()

Posted

技术标签:

【中文标题】串行通信 C++ ReadFile()【英文标题】:Serial Communication C++ ReadFile() 【发布时间】:2015-04-21 18:46:10 【问题描述】:

我创建了 2 个函数来通过串行端口进行读写,我正在使用 Visual Studios 2012、Windows 7、64 位操作系统和 RS-232 串行线在 C++ 中进行编码。我连接的板应该在按下按钮时发送 5 个字符 TRG 1,代码有效,但输出并不总是正确的值。

char serialRead()

    char input[5];
    DCB dcBus;
    HANDLE hSerial;
    DWORD  bytesRead, eventMask;
    COMMTIMEOUTS timeouts;
    hSerial = CreateFile (L"\\\\.\\COM13", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
    if (hSerial == INVALID_HANDLE_VALUE)
    
        cout << "error opening handle\n";
    
    else
    
        cout << "port opened\n";
    
    dcBus.DCBlength = sizeof(dcBus);
    if ((GetCommState(hSerial, &dcBus) == 0))
    
        cout << "error getting comm state\n";
    
    dcBus.BaudRate = CBR_9600;
    dcBus.ByteSize = DATABITS_8;
    dcBus.Parity = NOPARITY;
    dcBus.StopBits = ONESTOPBIT;
    if ((GetCommState(hSerial, &dcBus) == 0))
    
        cout << "error setting comm state\n";
    
    if ((GetCommTimeouts(hSerial, &timeouts) == 0))
    
        cout << "error getting timeouts\n";
    
    timeouts.ReadIntervalTimeout = 10;
    timeouts.ReadTotalTimeoutMultiplier = 1;
    timeouts.ReadTotalTimeoutConstant = 500;
    timeouts.WriteTotalTimeoutMultiplier = 1;
    timeouts.WriteTotalTimeoutConstant = 500;
    if (SetCommTimeouts(hSerial, &timeouts) == 0)
    
        cout << "error setting timeouts\n";
    
    if (SetCommMask(hSerial, EV_RXCHAR) == 0)
    
        cout << "error setting comm mask\n";
    
    if (WaitCommEvent(hSerial, &eventMask, NULL))
    
        if (ReadFile(hSerial, &input, 5, &bytesRead, NULL) !=0)
        
            for (int i = 0; i < sizeof(input); i++)
            
                cout << input[i];
            
            cout << endl;
        
        else 
        
            cout << "error reading file\n";
        
    
    else
    
        cout << "error waiting for comm event\n";
    
    switch (input[4])
    
    case '1' :
        CloseHandle(hSerial);
        return '1';
        break;
    case '2' :
        CloseHandle(hSerial);
        return '2';
        break;
    case '3' :
        CloseHandle(hSerial);
        return '3';
        break;
    case '4' :
        CloseHandle(hSerial);
        return '4';
        break;
    case '5':
        CloseHandle(hSerial);
        return '5';
        break;
    default :
        CloseHandle(hSerial);
        return '9';
        break;
    

在正确配置端口并且正在传输数据的意义上,代码运行成功。输出各不相同,大多数时候输出将打印整个“TRG 1”,但随机(似乎),输出将是“TRG||”或“T||||”,即它将成为字符串的一部分,并且每个丢失的字符都将替换为“|”而不是正确的字符。这是一个问题,因为我希望能够为触发器发送不同的值并运行该变量的开关。

我对串行通信比较陌生,不是专家级程序员,所以我想知道发生了什么?

【问题讨论】:

检查 ReadFile() 返回的 bytesRead 的值 @zdan 我在 ReadFile 之后插入了cout &lt;&lt;sizeof(bytesRead) &lt;&lt; endl;,它每次都说 4,即使它返回 "TRG 1" 或 "TRG||" 或 "T|||| " 不,sizeof(bytesRead) 告诉你保存 bytesRead 的 DWORD 的大小(当然是 4)。只要做 cout 【参考方案1】:

串行通信不是基于数据包的。信息不会以包装形式提供给您,因为它们必须可以一口气阅读整个信息。相反,它是一个流,因此您可以阅读半条消息、整条消息、多条消息等。

正如 zdan 在 cmets 中所说,您需要检查从 ReadFile 读取的字节数,并使用它来组成 5 个字符的包,即您的消息。 具体来说,只有前几个字符直到返回的读取字节数是有效的;其他都是垃圾。

【讨论】:

所以我需要添加一个循环来一次读取 1 个字节,直到读取 5 个字节?那么那应该每次都返回完整的字符流? 这个答案有效,因为它解释了遇到的问题,找到了解决方案,将 readfile 函数限制为一次从缓冲区读取 1 个字节,直到找到正确数量的字符

以上是关于串行通信 C++ ReadFile()的主要内容,如果未能解决你的问题,请参考以下文章

通过 IOCP 进行串行通信

串行通信 C++

arduino 和 Visual Studio C++,2 路串行通信

如何在 Linux 上通过 C++ 中的串行接口与 Arduino 通信?

Microsoft Visual C++ 2010 和 Arduino UNO 之间通过 USB 进行串行通信

PC和Arduino之间通过USB的串行通信