读取文件在多次串行端口读取后ERROR_INVALID_HANDLE

ReadFile ERROR_INVALID_HANDLE after several Serial Port reads

本文关键字:读取 ERROR INVALID HANDLE 串行端口 文件      更新时间:2023-10-16

我是Windows上的串行库的新手,因此非常感谢任何指导。我有一个插入USB端口的微控制器,它不断地通过UART发送数据。应该接收的内容的一个例子是:

ADC 值 1:848 ADC 值 2:972 ADC 中断计数:2300

(暂停)

ADC 值 1:849 ADC 值 2:971 ADC 中断数:2301

程序本身在GUI上有一个线程,一旦用户选择了COM端口,就会创建一个句柄名称为hCom的文件。创建一个新线程并将hCom传递给它。我尝试在新线程上使用无限 while 循环来不断读取端口(稍后我将实现适当的检查条件)。ReadFile 函数一次读取一个字节并将它们打印到屏幕上。这种连续的循环。但是,在发送第一组(val 1、val 2、int count)后,不会再收到任何数据。

文件和线程生成的创建在这里:

HANDLE hCom = CreateFile(szComPort,
GENERIC_READ |
GENERIC_WRITE, // desired access should be read&write
0,                          // COM port must be opened in non-sharing mode
NULL,                       // don't care about the security
OPEN_EXISTING,              // IMPORTANT: must use OPEN_EXISTING for a COM port
0,                          // usually overlapped but non-overlapped for existance test
NULL);
if (INVALID_HANDLE_VALUE == hCom) {
MessageBox(hwnd, "This port is not available or is in use.", "Error", MB_OK | MB_ICONERROR);
return WndProc(hwnd, WM_CREATE, wParam, lParam);
}
AppendText(hOut, "CONNECTED TO " + std::string(szComPort) + "rn");
DWORD myThreadID;
CreateThread(NULL, 0, serialHandler, &hCom, 0, &myThreadID);
return WndProc(hwnd, WM_CREATE, wParam, lParam);

这是我的线程处理程序:

DWORD WINAPI serialHandler(LPVOID lpParameter) {
HANDLE &hCom = *((HANDLE *) lpParameter);
SetCommState(hCom, &dcbSerialParams);
COMMTIMEOUTS tMyTimeOuts =  {
MAXDWORD, //  DWORD ReadIntervalTimeout;
0, //  DWORD ReadTotalTimeoutMultiplier;
10000,    //  DWORD ReadTotalTimeoutConstant;
1000,     //  DWORD WriteTotalTimeoutMultiplier;
1000,     //  DWORD WriteTotalTimeoutConstant;
};
if (!SetCommTimeouts(hCom, &tMyTimeOuts))
printf("setting port time-outs.");
std::string sb = "";
DWORD dwEventMask, dwSize = 0;

while (1) {
char szBuf;
DWORD dwIncommingReadSize;
do {
int error = ReadFile(hCom, &szBuf, 1, &dwIncommingReadSize, NULL);
if (error !=0) {
if (dwIncommingReadSize > 0) {
dwSize += dwIncommingReadSize;
sb += szBuf;
printf("%c", szBuf);
sb = "";
}
} else {
printf("No Data Received - ");
DWORD lasterror = GetLastError();
lasterror = GetLastError();
}
} while (dwIncommingReadSize > 0);
}
return 0;
}

编辑:这是导致我出现问题的WM_CREATE的一部分

hCom = CreateFile(szComPort,
GENERIC_READ | GENERIC_WRITE, // desired access should be read&write
0,                          // COM port must be opened in non-sharing mode
NULL,                       // don't care about the security
OPEN_EXISTING,              // IMPORTANT: must use OPEN_EXISTING for a COM port
0,                          // usually overlapped but non-overlapped for existance test
NULL);                      // always NULL for a general purpose COM port
if (INVALID_HANDLE_VALUE == hCom) {
if ((ERROR_ACCESS_DENIED) == GetLastError()) {   // then it exists and currently opened
wsprintf(szComPort, _T("&COM%d (in use)"), i);
AppendMenu(hSubMenu, MF_STRING, COM_PORT_MESSAGE_BASE + i, szComPort);
}
} else {   // COM port exists
wsprintf(szComPort, _T("COM%d"), i);
AppendMenu(hSubMenu, MF_STRING, COM_PORT_MESSAGE_BASE + i, szComPort);
CloseHandle(hCom);
}

实际输出为:

ADC 值 1: 848 ADC 值 2:972 ADC 中断数:2879 A收到的数据

- 未收到数据 - 未收到数据 -等等。串行处理程序中的变量 lasterror 返回 6,即ERROR_INVALID_HANDLE。我不确定为什么句柄在一次"设置"读取后从有效变为无效。

我在代码的另一部分打开了文件句柄,但忘记关闭它。当我尝试打开端口时,这导致了问题,它不再存在,并且我的 readfile 功能不起作用。确保检查所有创建文件的实例。

具体来说,我的代码不起作用的原因有两个。首先,我将 hCom 的本地副本传递到另一个线程的堆栈上。

CreateThread(NULL, 0, serialHandler, &hCom, 0, &myThreadID);

然后我返回到相同的功能以重新绘制 GUI(我想更新我的菜单栏以显示已建立连接)。

return WndProc(hwnd, WM_CREATE, wParam, lParam);

WM_CREATE内部是端口扫描,它会重新打开所有端口以检查它们是否打开。

hCom = CreateFile(szComPort,
GENERIC_READ | GENERIC_WRITE, // desired access should be read&write
0,                          // COM port must be opened in non-sharing mode
NULL,                       // don't care about the security
OPEN_EXISTING,              // IMPORTANT: must use OPEN_EXISTING for a COM port
0,                          // usually overlapped but non-overlapped for existance test
NULL);                      // always NULL for a general purpose COM port

这会干扰早期的线程,因为它使用相同的句柄来收集数据。这就是为什么它会工作一段时间,直到另一个线程运行并重用 COM 端口。我通过删除 return 函数、将整数传递给新线程并在新线程中打开 COM 端口来解决此问题。