如何在 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
错误在校验和中,感谢您的帮助。
char data[] = { 0x15, 0x03, 0x00, 0x00, 0x00, 0x01, **0x87**, **0x1E**};
这就是轮询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
错误在校验和中,感谢您的帮助。
char data[] = { 0x15, 0x03, 0x00, 0x00, 0x00, 0x01, **0x87**, **0x1E**};