串行 COM 端口通信不工作

Serial COM port communications not working

我正在为我的团队正在进行的一些串行通信编写一个测试应用程序。它是在 VS2010 上用 Visual C++(非托管)编写的。我们正在 Windows 7x64 上对其进行测试。如果我们先 运行 Putty(并连接),我们的代码就可以工作。如果我们不先 运行 Putty(然后连接),则没有任何效果。

来自Read/Write文件的return代码如下:

w/o腻子

写入文件 = 1 读取文件 = 1

带腻子

写入文件 = 1 读取文件 = 1

SetCommState例程returns 1(通过):https://msdn.microsoft.com/en-us/library/windows/desktop/aa363436%28v=vs.85%29.aspx 只需仔细检查:在 SetCommState returns 0;

之后立即调用 GetLastError

我们运行正在使用 COM7,但在 GUI 中选择了 COM4(肮脏的 hack)。发生的事情是 readfile 例程没有 return 返回一个字符串(通过指针)。这表明 writefile 没有正常工作,但我对此不是 100% 确定。

有没有人知道为什么会发生这种情况?

代码如下:

注意:我试图显示所有内容,但代码格式化程序搞砸了。重要的都在这里。

OutputDebugStringW(L"Previous COM port = " + portString + "\n");
        comPort = 4;
        com4 = true;
        OutputDebugStringW(L"SETCOM - COM4\n");
        hComm = CreateFile(L"COM7", GENERIC_READ | GENERIC_WRITE,
            0,
            0,
            OPEN_EXISTING,
            0,
            NULL);
        if (hComm == INVALID_HANDLE_VALUE)
            OutputDebugStringW(L"Error!");
        else
            OutputDebugStringW(L"Success!");
        DCB comSettings;
        SecureZeroMemory(&comSettings, sizeof(DCB));
        comSettings.BaudRate = 9600;
        comSettings.ByteSize = 8;
        comSettings.Parity = NOPARITY;
        comSettings.StopBits = ONESTOPBIT;
        comSettings.fAbortOnError = TRUE;
        b = SetCommState(hComm, &comSettings);
        commSetupResult = GetLastError();
        /*OutputDebugStringW(L"SetCommState = " + (int)SetCommState(hComm, &comSettings));*/
        //s.Format("%d",4);//SetCommState(hComm, &comSettings));

            // instance an object of COMMTIMEOUTS.
            COMMTIMEOUTS comTimeOut;
            // Specify time-out between charactor for receiving.
            comTimeOut.ReadIntervalTimeout = 3;
            // Specify value that is multiplied 
            // by the requested number of bytes to be read. 
            comTimeOut.ReadTotalTimeoutMultiplier = 3;
            // Specify value is added to the product of the 
            // ReadTotalTimeoutMultiplier member
            comTimeOut.ReadTotalTimeoutConstant = 2;
            // Specify value that is multiplied 
            // by the requested number of bytes to be sent. 
            comTimeOut.WriteTotalTimeoutMultiplier = 3;
            // Specify value is added to the product of the 
            // WriteTotalTimeoutMultiplier member
            comTimeOut.WriteTotalTimeoutConstant = 2;
            // set the time-out parameter into device control.
            SetCommTimeouts(hComm, &comTimeOut);
            break;
        case ID_SETCOM_COM5:
            OutputDebugStringW(L"Previous COM port = " + portString + "\n");
            comPort = 5;
            OutputDebugStringW(L"SETCOM - COM5\n");
            hComm = CreateFile(L"COM5", GENERIC_READ | GENERIC_WRITE,
                0,
                0,
                OPEN_EXISTING,
                FILE_FLAG_OVERLAPPED,
                0);
            if (hComm == INVALID_HANDLE_VALUE)
                OutputDebugStringW(L"Error!");
            else
                OutputDebugStringW(L"Success!");
            break;
        case ID_SETCOM_COM6:
            OutputDebugStringW(L"Previous COM port = " + portString + "\n");
            comPort = 6;
            OutputDebugStringW(L"SETCOM - COM6\n");
            hComm = CreateFile(L"COM6", GENERIC_READ | GENERIC_WRITE,
                0,
                0,
                OPEN_EXISTING,
                FILE_FLAG_OVERLAPPED,
                0);
            if (hComm == INVALID_HANDLE_VALUE)
                OutputDebugStringW(L"Error!");
            else
                OutputDebugStringW(L"Success!");
            break;
        case ID_SETCOM_COM7:
            OutputDebugStringW(L"Previous COM port = " + portString + "\n");
            comPort = 7;
            OutputDebugStringW(L"SETCOM - COM7\n");
            hComm = CreateFile(L"COM7", GENERIC_READ | GENERIC_WRITE,
                0,
                0,
                OPEN_EXISTING,
                FILE_FLAG_OVERLAPPED,
                0);
            if (hComm == INVALID_HANDLE_VALUE)
                OutputDebugStringW(L"Error!");
            else
                OutputDebugStringW(L"Success!");
            break;
        case ID_SETCOM_COM8:
            OutputDebugStringW(L"Previous COM port = " + portString + "\n");
            comPort = 8;
            OutputDebugStringW(L"SETCOM - COM8\n");
            hComm = CreateFile(L"COM8", GENERIC_READ | GENERIC_WRITE,
                0,
                0,
                OPEN_EXISTING,
                FILE_FLAG_OVERLAPPED,
                0);
            if (hComm == INVALID_HANDLE_VALUE)
                OutputDebugStringW(L"Error!");
            else
                OutputDebugStringW(L"Success!");
            break;
        case ID_SETCOM_COM9:
            OutputDebugStringW(L"Previous COM port = " + portString + "\n");
            comPort = 9;
            OutputDebugStringW(L"SETCOM - COM9\n");
            hComm = CreateFile(L"COM9", GENERIC_READ | GENERIC_WRITE,
                0,
                0,
                OPEN_EXISTING,
                FILE_FLAG_OVERLAPPED,
                0);
            if (hComm == INVALID_HANDLE_VALUE)
                OutputDebugStringW(L"Error!");
            else
                OutputDebugStringW(L"Success!");
            break;
        case ID_SETCOM_COM10:
            OutputDebugStringW(L"Previous COM port = " + portString + "\n");
            comPort = 10;
            OutputDebugStringW(L"SETCOM - COM10\n");
            hComm = CreateFile(L"COM9", GENERIC_READ | GENERIC_WRITE,
                0,
                0,
                OPEN_EXISTING,
                FILE_FLAG_OVERLAPPED,
                0);
            if (hComm == INVALID_HANDLE_VALUE)
                OutputDebugStringW(L"Error!");
            else
                OutputDebugStringW(L"Success!");
            break;
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        // TODO: Add any drawing code here...
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }

    DWORD dwRead;
    BOOL fWaitingOnRead = FALSE;
    OVERLAPPED osReader = { 0 };

    // Create the overlapped event. Must be closed before exiting
    // to avoid a handle leak.
    osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    if (osReader.hEvent == NULL) {}
    // Error creating overlapped event; abort.
    char lpBuf[32];
    if (com4) {
        if (!fWaitingOnRead) 
        {
            // Issue read operation.
            OVERLAPPED osWrite = { 0 };
            DWORD dwWritten;
            BOOL result = GetLastError();
            result = WriteFile(hComm, "EO1\nJAX0\nDI\n", 12, &dwWritten, NULL);
            CStringA WFError;
            WFError.Format("\nSent %d result %d lasterror %d \n", dwWritten, result, GetLastError());
            OutputDebugStringA(WFError);
            Sleep(100);//min was 61, 100 to be safe
            bool Wait = true;
            DWORD start = GetTickCount() + 15000;

            while (Wait && start > GetTickCount())
            {
                Sleep(200);
                //              GetLastError();
                result = ReadFile(hComm, lpBuf, 32, &dwRead, NULL);
                WFError.Format("Read %d, result %d, lasterror %d \n", dwRead, result, GetLastError());
                OutputDebugStringA(WFError);
                //          WFError = "Read file error = " + WFError;
                if (result != 0)
                {
                    CString temp = lpBuf;
                    temp = temp.Left(dwRead);
                    if (temp.GetLength() > 0)
                    {
                        OutputDebugString(temp + "\n");
                        MessageBox(NULL, temp, L"Title", MB_OK);
//                      memset(&lpBuf[0], 0, sizeof(lpBuf));
                    }
                    //strcpy(lpBuf,"");
//                  goto start;
                }


            }
        }
    }

我有根据的猜测是,您的 SetCommState 调用失败了。您正在向它传递一个充满随机垃圾的 DCB 结构。它在 Putty 之后工作的原因是 Putty 为您配置端口,并且您的程序开始使用该配置(因为它无法建立自己的配置)。

DCB comSettings; 行更改为

DCB comSettings = {sizeof(DCB)};

这会正确初始化 DCBlength 成员,并将所有其他成员设置为 0。然后根据需要为您的设备设置其他成员。

并检查 SetCommState 的 return 值是否有错误(以及所有其他 API 调用的值)。