读取多个串行端口后,ReadFile ERROR_INVALID_HANDLE

时间:2019-06-13 23:25:47

标签: c++ multithreading winapi serial-port

我是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函数一次读取一个字节,然后将它们打印到屏幕上。这不断循环。但是,在发送第一组(值1,值2,整数计数)之后,不再接收任何数据。

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

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) + "\r\n");
                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。我不确定为什么一组“读取”后句柄会从有效变为无效。

1 个答案:

答案 0 :(得分:0)

我在代码的另一部分中打开了文件句柄,却忘记了将其关闭。当我尝试打开端口并且它不再存在时,这导致出现问题,并且我的readfile函数不起作用。确保检查所有createfile实例。

具体来说,我的代码无法正常工作的原因是双重的。首先,我将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端口。我通过删除返回函数,将整数传递给新线程并在新线程中打开COM端口来解决此问题。