C++开发GTP-180小票打印机时SetCommState创建DCB报错如何解决
代码错误点及修复方案
- 未校验
CreateFile返回值:串口打开失败(如端口不存在、被其他程序占用)时,后续所有串口API都会调用失败,需在打开后判断返回值是否为INVALID_HANDLE_VALUE,可配合GetLastError查看具体错误码 - DCB结构初始化不完整:DCB结构的
DCBlength字段必须显式赋值为sizeof(DCB),否则SetCommState无法识别结构大小,会返回参数错误;同时建议先调用GetCommState获取当前端口默认配置再修改指定参数,避免遗漏配置项 - 硬编码串口端口:函数形参
PortSpecifier未被使用,CreateFile固定写死COM5,传入参数不生效 WriteFile参数错误:直接传入CString对象作为缓冲区是错误的,需要传入字符串指针;同时你要发送2字节的指令0x1b 0x69,硬编码写入长度1只会发送第一个字节,而且字符串中使用双反斜杠\\x会把转义符当作普通字符处理,实际发送的不是十六进制字节- 未校验所有API调用返回值:
SetCommState、WriteFile调用后都要判断返回值,便于定位出错环节 - 缺少串口超时配置:未配置超时的情况下,
WriteFile可能会出现无限阻塞的情况
修复后完整代码
#include <atlstr.h> #include <windows.h> #include <iostream> using namespace std; BOOL WriteComPort(CString PortSpecifier, CString data) { HANDLE hSerial = CreateFile(PortSpecifier, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // 校验串口打开结果 if (hSerial == INVALID_HANDLE_VALUE) { cout << "打开串口失败,错误码:" << GetLastError() << endl; return FALSE; } DCB dcbSerialParams = { 0 }; // 必须设置DCB结构长度 dcbSerialParams.DCBlength = sizeof(DCB); // 先获取当前串口默认配置 if (!GetCommState(hSerial, &dcbSerialParams)) { cout << "获取串口配置失败,错误码:" << GetLastError() << endl; CloseHandle(hSerial); return FALSE; } // 修改需要的配置项 dcbSerialParams.BaudRate = CBR_110; // 注意确认你的打印机实际波特率,小票机常用9600/115200,可按需修改 dcbSerialParams.fDtrControl = DTR_CONTROL_ENABLE; dcbSerialParams.ByteSize = 8; dcbSerialParams.StopBits = ONESTOPBIT; dcbSerialParams.Parity = NOPARITY; // 设置串口配置 if (!SetCommState(hSerial, &dcbSerialParams)) { cout << "设置串口配置失败,错误码:" << GetLastError() << endl; CloseHandle(hSerial); return FALSE; } // 配置串口超时,避免WriteFile阻塞 COMMTIMEOUTS timeouts = { 0 }; timeouts.WriteTotalTimeoutConstant = 1000; timeouts.WriteTotalTimeoutMultiplier = 10; if (!SetCommTimeouts(hSerial, &timeouts)) { cout << "设置超时失败,错误码:" << GetLastError() << endl; CloseHandle(hSerial); return FALSE; } DWORD byteswritten; // 正确传入字符串指针,长度取实际字符串字节数 if (!WriteFile(hSerial, (LPCTSTR)data, data.GetLength(), &byteswritten, NULL)) { cout << "写入数据失败,错误码:" << GetLastError() << endl; CloseHandle(hSerial); return FALSE; } CloseHandle(hSerial); return TRUE; } int main() { // 注意这里不要加双反斜杠,直接用\x转义输出十六进制字节 WriteComPort(_T("COM5"), _T("\x1b\x69")); return 0; }
内容的提问来源于stack exchange,提问作者Baurzhan
相关产品推荐
相关产品推荐

