如何在 C++ 中轮询 com 端口

how to poll a com port in c++

这就是轮询com口的全部代码,根据modbus-RTU协议,设备无响应。我不知道如何让设备响应我。设备地址和功能代码足以回答。这些是前两个字符(0x15、0x03 ...) 我不知道我做错了什么!

有一个密码:

#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <TCHAR.h>
using namespace std;
#pragma warning(disable:4996)
//обработчик COM порта
HANDLE hSerial;
//название порта
LPCTSTR sPortName = L"COM3";
int ReadCOM()
{
    int a = 0;
    DWORD iSize;
    char sReceivedChar = { 0 };
    char recBuf[100] = { 0 };
    recBuf[0] = '[=10=]';
    while (!a)
    {
        //получение ответа
        ReadFile(hSerial, &sReceivedChar, 1, &iSize, 0);  // получаем 1 байт

        if (iSize > 0)   // если что-то принято, выводим
        {
            cout << "Answer: " << sReceivedChar;
            strcat(recBuf, &sReceivedChar);
        }
        else
        {
            cin >> a;
        }
    }
    CloseHandle(hSerial);
    return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{

    //настройка параметров соединения (В данном случае COM порта)
    DCB *dcbSerialParams = (DCB*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DCB));;
    dcbSerialParams->DCBlength = sizeof(dcbSerialParams);
    if (BuildCommDCB(L"baud=9600 parity=E data=8 stop=2", dcbSerialParams))
    {
        std::cout << "success 1" << std::endl;
    }
    else
    {
        std::cout << "failure 1" << std::endl;
    }
    dcbSerialParams->fNull = TRUE;


    //установка таймаута приема и передачи порта
    COMMTIMEOUTS CommTimeOuts;
    CommTimeOuts.ReadIntervalTimeout = 1000;
    CommTimeOuts.ReadTotalTimeoutConstant = CommTimeOuts.ReadTotalTimeoutMultiplier = 100;
    CommTimeOuts.WriteTotalTimeoutConstant = CommTimeOuts.WriteTotalTimeoutMultiplier = 100;


    //открытие порта для чтения/записи
    hSerial = CreateFile(sPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    //проверка роботоспособности (не работает)
    if (hSerial == INVALID_HANDLE_VALUE)
    {
        if (GetLastError() == ERROR_FILE_NOT_FOUND)
        {
            cout << "wrn::Serial port does NOT exist.\n";
        }
        else
        {
            cout << "wrn::Some other error occurred.\n";
        }
    }
    //(работает) пишем соответствующее сообщение
    else
    {
        cout << "suc::Serial port DOES exist.\n";
    }
    //запись свойств порта
    if (!SetCommState(hSerial, dcbSerialParams))
    {
        cout << "faulure 2" << endl;
    }
    if (!SetCommTimeouts(hSerial, &CommTimeOuts))
    {
        cout << "failure 3" << endl;
    }
    //Освобождение DCB
    HeapFree(GetProcessHeap(), 0, dcbSerialParams);

    //char data[] = { 0x15, 0x03, 0x6B, 0x03, 0x37, 0x7E };
    char data[] = { 0x15, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A};
 
    DWORD dwSize = sizeof(data);            // размер этой строки
    DWORD dwBytesWritten;               // тут будет количество собственно переданных байт
    BOOL iRet = WriteFile(hSerial, data, dwSize, &dwBytesWritten, NULL);
    //нормальная работа
    if (iRet)
    {
        cout << "nor :: " << dwSize << " Bytes in string. " << dwBytesWritten << " Bytes sended. " << endl;
    }
    //ошибка передачи
    else
    {
        cout << "wrn :: " << "db = " << dwBytesWritten << "\nds = " << dwSize << endl;
    }


    ReadCOM();
    return 0;
}

您不需要堆分配 DCB;只需使用堆栈变量。此外,您在指针上使用 sizeof,因此不会相应地填充 DCBlength 字段。只需执行以下操作:

DCB dcbSerialParams = { 0 };
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (BuildCommDCB(L"baud=9600 parity=E data=8 stop=2", &dcbSerialParams))
....

同样在 ReadCOM 中,虽然 DWORD iSize; 是一个 OUT 参数,但您应该将其初始化为零以避免在调试时出现潜在的运行时错误(“变量 x 未被初始化就被使用”)

您是否使用终端程序检查了您的请求字符串 f.e。 hterm? 据我所知,只有两个 tx 字符不会从设备中得到答案,帧末尾也有一个 crc

https://www.der-hammer.info/pages/terminal.html

错误在校验和中,感谢您的帮助。

char data[] = { 0x15, 0x03, 0x00, 0x00, 0x00, 0x01, **0x87**, **0x1E**};