如何使用 Windows 从 C++ 中的 RS485 COM 端口读取数据?
How can I read from an RS485 COM port in C++ with Windows?
我尝试通过 RS485(通过 USB 到 RS485 转换器)控制电压源。我在 Visual Studio 中使用标准 C++。
我写了下面的代码。写入工作正常,电压源响应所有输入,但读回字节对我来说很困难。
例如,答案可能是以下字符串:“12.000”(31 32 2E 30 30 30 0A)
#include <iostream>
#include <string.h>
#include <windows.h>
#include <msports.h>
#include <stdlib.h>
const unsigned char oe = static_cast<unsigned char>(148);
int main()
{
//create new handle
HANDLE hComm;
hComm = CreateFile(L"\\.\COM5",
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
printf("CreateFile handle failed ERROR: %d.\n", GetLastError());
/*
//Timwouts
COMMTIMEOUTS CTO;
CTO.ReadIntervalTimeout = 500;
CTO.ReadTotalTimeoutConstant = 500;
CTO.ReadTotalTimeoutMultiplier = 500;
CTO.WriteTotalTimeoutConstant = 500;
CTO.WriteTotalTimeoutMultiplier = 500;
//build DCB strukture
DCB dcb;
if (!BuildCommDCB(L"COM5 baud=115200 parity=N data=8 stop=1", &dcb))
{
MessageBox(0, L"Error BuildCommDCB", L"Test", MB_OK);
}
if (!SetCommTimeouts(hComm, &CTO))
{
MessageBox(0, L"Error CommTimeouts", L"Test", MB_OK);
}
*/
//Variables for read RS485
char sBuffer[1024];
//Variables for user input values
char parameter1;
float floatV;
char parameter2;
while (true) {
std::cout << "Hallo, was m" << oe << "chten Sie tun?\n";
std::cin >> parameter1 >> floatV >> parameter2;
//std::cout << "parameter1: " << parameter1 << "\n";
//std::cout << "floatV: " << floatV << "\n";
//std::cout << "parameter2: " << parameter2 << "\n";
//system("cls");
if (parameter1 == 'Q' && parameter2 == 'V') {
uint32_t Voltage = (uint32_t)(floatV * 1000);
char myString[30];
sprintf_s(myString, "%f", floatV);
//Set new voltage
//VSET:
TransmitCommChar(hComm, 'V');
TransmitCommChar(hComm, 'S');
TransmitCommChar(hComm, 'E');
TransmitCommChar(hComm, 'T');
TransmitCommChar(hComm, ':');
//Wert
TransmitCommChar(hComm, myString[0]);
TransmitCommChar(hComm, myString[1]);
TransmitCommChar(hComm, myString[2]);
TransmitCommChar(hComm, myString[3]);
TransmitCommChar(hComm, myString[4]);
TransmitCommChar(hComm, myString[5]);
//ENTER
TransmitCommChar(hComm, 0x0A);
//Get the voltage of the source
//Control V
//56 53 45 54 3F 0A
TransmitCommChar(hComm, 'V');
TransmitCommChar(hComm, 'S');
TransmitCommChar(hComm, 'E');
TransmitCommChar(hComm, 'T');
TransmitCommChar(hComm, '?');
TransmitCommChar(hComm, 0x0A);
//Sleep(100);
/*
LPVOID buffRead = 0;
DWORD dwBytesRead = 0;
if (!ReadFile(hComm, &buffRead, 6, &dwBytesRead, NULL))
{
printf("error reading from input buffer \n");
}
printf("Data read from read buffer is \n %s \n", (char*)buffRead);
*/
DWORD dwBytesRead = 0;
char bytes_to_receive[7];
if (!ReadFile(hComm, bytes_to_receive, 7, &dwBytesRead, NULL)) {
printf("SetCommState failed. Error: %d.\n", GetLastError());
//CloseHandle(hComm);
//return (4);
}
else {
printf("Bytes read %d -> %s\n", dwBytesRead, bytes_to_receive);
}
/*if (ReadFile(hComm, sBuffer, 7, NULL, NULL)) {
printf("%s \n", sBuffer);
}
else {
printf("Reading file fails! \n");
}*/
/*UINT numberBytesRead = _lread(
HFILE hFile,
LPVOID lpBuffer,
UINT uBytes
);*/
}
}
}
我得到的输出是:
Hallo, was möchten Sie tun?
Q12V
SetCommState failed. Error: 87.
Hallo, was möchten Sie tun?
电压源跳到12V,所以她得到了命令。
编辑:
我将 FILE_FLAG_OVERLAPPED 更改为 FILE_ATTRIBUTE_NORMAL,现在我得到:
Hallo, was möchten Sie tun?
Q12V
Bytes read 7 -> 12.000
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠G┤°V
Hallo, was möchten Sie tun?
所以它基本上似乎有效,但我得到了很多奇怪的迹象。
编辑 2:
我仍然面临的另一个问题是,在重新启动计算机后,一切都不再起作用,我需要启动 HTerm,按连接和断开连接,这显然是我在程序中错过的一些初始化。之后它一直工作到下一次重新启动计算机。你知道我的程序中可能没有什么吗?
你会得到奇怪的迹象,因为 bytes_to_receive
不是一个以 null 结尾的字符串。 printf
一直读取字节,直到它看到一个空 (0) 字节。您没有在 bytes_to_receive
中放置一个空字节,因此它会一直打印,直到它结束并在其他地方找到一个。
ReadFile
告诉您在 dwBytesRead
中读取了多少字节,因此您可以为 printf
添加一个空字节:bytes_to_receive[dwBytesRead] = '[=16=]';
.
确保将 bytes_to_receive
的大小增加到 8 因为现在您要多写一个字节。仍将 7 传递给 ReadFile,因为您不想读取 8 个字节 - 您在读取数据后添加了空字节 yourself。
好的,我暂时解决了这个问题。需要一些额外的代码,我希望我能帮助下一个有同样问题的人,否则我愿意接受改进建议。感谢大家的支持,所有帮助过我的人我都点赞了
DCB Dcb;
COMMTIMEOUTS Cto;
HANDLE hComm;
//Create file Handle
hComm = CreateFile(L"\\.\COM5",
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (hComm == INVALID_HANDLE_VALUE) {
printf("CreateFile handle failed ERROR: %d.\n", GetLastError());
}
//Data Center Bridging
Dcb.DCBlength = sizeof(Dcb);
GetCommState(hComm, &Dcb);
Dcb.BaudRate = CBR_115200;
Dcb.fParity = false;
Dcb.fNull = false;
Dcb.StopBits = ONESTOPBIT;
Dcb.Parity = NOPARITY;
Dcb.ByteSize = 8;
SetCommState(hComm, &Dcb);
//Timeouts
Cto.ReadIntervalTimeout = 0;
Cto.ReadTotalTimeoutMultiplier = 0;
Cto.ReadTotalTimeoutConstant = 0;
Cto.WriteTotalTimeoutMultiplier = 0;
Cto.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(hComm, &Cto);
我尝试通过 RS485(通过 USB 到 RS485 转换器)控制电压源。我在 Visual Studio 中使用标准 C++。 我写了下面的代码。写入工作正常,电压源响应所有输入,但读回字节对我来说很困难。 例如,答案可能是以下字符串:“12.000”(31 32 2E 30 30 30 0A)
#include <iostream>
#include <string.h>
#include <windows.h>
#include <msports.h>
#include <stdlib.h>
const unsigned char oe = static_cast<unsigned char>(148);
int main()
{
//create new handle
HANDLE hComm;
hComm = CreateFile(L"\\.\COM5",
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
printf("CreateFile handle failed ERROR: %d.\n", GetLastError());
/*
//Timwouts
COMMTIMEOUTS CTO;
CTO.ReadIntervalTimeout = 500;
CTO.ReadTotalTimeoutConstant = 500;
CTO.ReadTotalTimeoutMultiplier = 500;
CTO.WriteTotalTimeoutConstant = 500;
CTO.WriteTotalTimeoutMultiplier = 500;
//build DCB strukture
DCB dcb;
if (!BuildCommDCB(L"COM5 baud=115200 parity=N data=8 stop=1", &dcb))
{
MessageBox(0, L"Error BuildCommDCB", L"Test", MB_OK);
}
if (!SetCommTimeouts(hComm, &CTO))
{
MessageBox(0, L"Error CommTimeouts", L"Test", MB_OK);
}
*/
//Variables for read RS485
char sBuffer[1024];
//Variables for user input values
char parameter1;
float floatV;
char parameter2;
while (true) {
std::cout << "Hallo, was m" << oe << "chten Sie tun?\n";
std::cin >> parameter1 >> floatV >> parameter2;
//std::cout << "parameter1: " << parameter1 << "\n";
//std::cout << "floatV: " << floatV << "\n";
//std::cout << "parameter2: " << parameter2 << "\n";
//system("cls");
if (parameter1 == 'Q' && parameter2 == 'V') {
uint32_t Voltage = (uint32_t)(floatV * 1000);
char myString[30];
sprintf_s(myString, "%f", floatV);
//Set new voltage
//VSET:
TransmitCommChar(hComm, 'V');
TransmitCommChar(hComm, 'S');
TransmitCommChar(hComm, 'E');
TransmitCommChar(hComm, 'T');
TransmitCommChar(hComm, ':');
//Wert
TransmitCommChar(hComm, myString[0]);
TransmitCommChar(hComm, myString[1]);
TransmitCommChar(hComm, myString[2]);
TransmitCommChar(hComm, myString[3]);
TransmitCommChar(hComm, myString[4]);
TransmitCommChar(hComm, myString[5]);
//ENTER
TransmitCommChar(hComm, 0x0A);
//Get the voltage of the source
//Control V
//56 53 45 54 3F 0A
TransmitCommChar(hComm, 'V');
TransmitCommChar(hComm, 'S');
TransmitCommChar(hComm, 'E');
TransmitCommChar(hComm, 'T');
TransmitCommChar(hComm, '?');
TransmitCommChar(hComm, 0x0A);
//Sleep(100);
/*
LPVOID buffRead = 0;
DWORD dwBytesRead = 0;
if (!ReadFile(hComm, &buffRead, 6, &dwBytesRead, NULL))
{
printf("error reading from input buffer \n");
}
printf("Data read from read buffer is \n %s \n", (char*)buffRead);
*/
DWORD dwBytesRead = 0;
char bytes_to_receive[7];
if (!ReadFile(hComm, bytes_to_receive, 7, &dwBytesRead, NULL)) {
printf("SetCommState failed. Error: %d.\n", GetLastError());
//CloseHandle(hComm);
//return (4);
}
else {
printf("Bytes read %d -> %s\n", dwBytesRead, bytes_to_receive);
}
/*if (ReadFile(hComm, sBuffer, 7, NULL, NULL)) {
printf("%s \n", sBuffer);
}
else {
printf("Reading file fails! \n");
}*/
/*UINT numberBytesRead = _lread(
HFILE hFile,
LPVOID lpBuffer,
UINT uBytes
);*/
}
}
}
我得到的输出是:
Hallo, was möchten Sie tun?
Q12V
SetCommState failed. Error: 87.
Hallo, was möchten Sie tun?
电压源跳到12V,所以她得到了命令。
编辑: 我将 FILE_FLAG_OVERLAPPED 更改为 FILE_ATTRIBUTE_NORMAL,现在我得到:
Hallo, was möchten Sie tun?
Q12V
Bytes read 7 -> 12.000
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠G┤°V
Hallo, was möchten Sie tun?
所以它基本上似乎有效,但我得到了很多奇怪的迹象。
编辑 2: 我仍然面临的另一个问题是,在重新启动计算机后,一切都不再起作用,我需要启动 HTerm,按连接和断开连接,这显然是我在程序中错过的一些初始化。之后它一直工作到下一次重新启动计算机。你知道我的程序中可能没有什么吗?
你会得到奇怪的迹象,因为 bytes_to_receive
不是一个以 null 结尾的字符串。 printf
一直读取字节,直到它看到一个空 (0) 字节。您没有在 bytes_to_receive
中放置一个空字节,因此它会一直打印,直到它结束并在其他地方找到一个。
ReadFile
告诉您在 dwBytesRead
中读取了多少字节,因此您可以为 printf
添加一个空字节:bytes_to_receive[dwBytesRead] = '[=16=]';
.
确保将 bytes_to_receive
的大小增加到 8 因为现在您要多写一个字节。仍将 7 传递给 ReadFile,因为您不想读取 8 个字节 - 您在读取数据后添加了空字节 yourself。
好的,我暂时解决了这个问题。需要一些额外的代码,我希望我能帮助下一个有同样问题的人,否则我愿意接受改进建议。感谢大家的支持,所有帮助过我的人我都点赞了
DCB Dcb;
COMMTIMEOUTS Cto;
HANDLE hComm;
//Create file Handle
hComm = CreateFile(L"\\.\COM5",
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (hComm == INVALID_HANDLE_VALUE) {
printf("CreateFile handle failed ERROR: %d.\n", GetLastError());
}
//Data Center Bridging
Dcb.DCBlength = sizeof(Dcb);
GetCommState(hComm, &Dcb);
Dcb.BaudRate = CBR_115200;
Dcb.fParity = false;
Dcb.fNull = false;
Dcb.StopBits = ONESTOPBIT;
Dcb.Parity = NOPARITY;
Dcb.ByteSize = 8;
SetCommState(hComm, &Dcb);
//Timeouts
Cto.ReadIntervalTimeout = 0;
Cto.ReadTotalTimeoutMultiplier = 0;
Cto.ReadTotalTimeoutConstant = 0;
Cto.WriteTotalTimeoutMultiplier = 0;
Cto.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(hComm, &Cto);