Visual Studio C++串口通信报错及自动识别串口需求
问题解决:VS C++串口通信编译错误与自动识别实现
一、编译错误(C2665、E0289)解决
错误核心原因
项目字符集设置与函数参数类型不匹配:
- Windows API的
CreateFile在Unicode字符集下对应CreateFileW,要求传入LPCWSTR(宽字符指针);在多字节字符集下对应CreateFileA,要求传入LPCSTR(窄字符指针)。 - 你传入的
L"//./com3"是宽字符常量,若项目字符集设置为多字节字符集,会直接触发类型不匹配的编译错误。
解决方案
方案1:切换到Unicode字符集(推荐)
- 右键项目 → 属性 → 配置属性 → 常规 → 字符集
- 选择「使用 Unicode 字符集」,点击确定后重新编译。
方案2:适配多字节字符集
若必须使用多字节字符集,修改代码如下:
- 将
SerialPort类中的LPCWSTR COMport改为LPCSTR COMport - 构造函数、
Connect函数的参数LPCWSTR COM改为LPCSTR COM - 调用构造函数时传入
"//./com3"(去掉L前缀)
额外代码问题修复
除字符集问题外,代码还有几处逻辑错误需修正:
字符串长度计算错误
sendCommand中dNoOFBytestoWrite = sizeof(commandBuffer);会获取指针的大小(4/8字节),而非实际命令字符串长度,改为:this->dNoOFBytestoWrite = strlen(commandBuffer) + 1; // +1包含字符串终止符串口参数未生效
当前代码仅定义了DCB和COMMTIMEOUTS结构体,但未将参数设置到串口,需在Connect函数的成功分支中添加:else { cout << "Opening serial port successful" << endl; // 设置串口参数 DCB dcbSerialParams = { 0 }; dcbSerialParams.DCBlength = sizeof(dcbSerialParams); if (!GetCommState(hComm, &dcbSerialParams)) { cout << "Failed to get comm state" << endl; } dcbSerialParams.BaudRate = setBaudRate; dcbSerialParams.ByteSize = setByteSize; dcbSerialParams.StopBits = ONESTOPBIT; dcbSerialParams.Parity = NOPARITY; if (!SetCommState(hComm, &dcbSerialParams)) { cout << "Failed to set comm state" << endl; } // 设置超时 COMMTIMEOUTS timeouts = { 0 }; timeouts.ReadIntervalTimeout = 10; timeouts.ReadTotalTimeoutConstant = 10; timeouts.ReadTotalTimeoutMultiplier = 10; timeouts.WriteTotalTimeoutConstant = 50; timeouts.WriteTotalTimeoutMultiplier = 10; if (!SetCommTimeouts(hComm, &timeouts)) { cout << "Failed to set comm timeouts" << endl; } sendCommand(setBaudRate, setByteSize, commandBuffer); }同时删除
sendCommand中重复的DCB和超时定义代码。缓冲区初始化与冗余代码
- 在
SerialPort构造函数中添加memset(this->SerialBuffer, 0, BufSize);初始化缓冲区,避免输出乱码。 getData中ReadFile的第二个参数改为this->SerialBuffer,&*属于冗余操作。
- 在
二、串口自动识别实现
通过Windows设备枚举API获取所有可用串口,再尝试连接验证是否为目标设备:
1. 配置依赖
在SerialPort.h或调用文件中添加头文件:
#include <vector> #include <string> #include <setupapi.h> #include <devguid.h>
同时在项目属性 → 链接器 → 输入 → 附加依赖项中添加setupapi.lib。
2. 编写串口枚举函数
std::vector<std::string> getAvailableSerialPorts() { std::vector<std::string> ports; // 获取当前存在的所有串口设备接口 HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_COMPORT, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (hDevInfo == INVALID_HANDLE_VALUE) { return ports; } SP_DEVICE_INTERFACE_DATA deviceInterfaceData = { 0 }; deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); for (DWORD i = 0; SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVINTERFACE_COMPORT, i, &deviceInterfaceData); i++) { DWORD requiredSize = 0; // 先获取所需缓冲区大小 SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, NULL, 0, &requiredSize, NULL); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { continue; } // 分配缓冲区获取设备详情 PSP_DEVICE_INTERFACE_DETAIL_DATA pDetailData = reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(malloc(requiredSize)); pDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); SP_DEVINFO_DATA devInfoData = { 0 }; devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, pDetailData, requiredSize, NULL, &devInfoData)) { // DevicePath格式为"\\\\.\\COMx",可直接用于CreateFile ports.emplace_back(pDetailData->DevicePath); } free(pDetailData); } SetupDiDestroyDeviceInfoList(hDevInfo); return ports; }
3. 自动识别并连接目标串口
遍历枚举到的串口,通过发送命令、读取响应验证是否为目标设备:
int main() { std::vector<std::string> ports = getAvailableSerialPorts(); SerialPort* targetPort = nullptr; for (const auto& port : ports) { // 转换为宽字符适配Unicode字符集 std::wstring wPort(port.begin(), port.end()); SerialPort tempPort(wPort.c_str(), CBR_115200, 8, "#or", 24); // 验证目标设备:示例为检查是否包含预期响应 tempPort.getData(); if (strstr(tempPort.SerialBuffer, "expected_response") != nullptr) { targetPort = new SerialPort(wPort.c_str(), CBR_115200, 8, "#or", 24); break; } } if (targetPort != nullptr) { cout << "Connected to target port successfully" << endl; targetPort->getData(); cout << targetPort->SerialBuffer << endl; delete targetPort; } else { cout << "Target serial port not found" << endl; } return 0; }
内容的提问来源于stack exchange,提问作者taek9105
相关产品推荐
相关产品推荐

