0
votes

I'm writing a test app for some serial communications that my team is working on. Its written in Visual C++ (unmanaged) on VS2010. We're testing it on Windows 7x64. If we run Putty first (and connect), our code works. If we don't run Putty first (and connect), nothing works.

The return codes from Read/Write file are as follows:

w/o putty

write file = 1 read file = 1

w/ putty

write file = 1 read file = 1

The SetCommState routine returns 1 (a pass): https://msdn.microsoft.com/en-us/library/windows/desktop/aa363436%28v=vs.85%29.aspx Just double checking: Calling GetLastError immediately after SetCommState returns 0;

We're running on COM7, but COM4 is selected in the GUI (dirty hack). What happens is that the readfile routine doesn't return back a string (via pointer). This indicates that writefile isn't working properly, but I'm not 100% sure about this.

Does anyone out there know why this might happen?

Here is the code:

Note: I tried to show everything, but the code formatter screwed up. Everything that is important is here.

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;
                }


            }
        }
    }
1
Don't blame the code formatter. Instead, familiarize yourself with it by reading the Markdown Editing Help. It's also completely unclear, where the code fails, what error codes it returns, etc.IInspectable
Check whether SetCommState call succeeds. My guess is that it fails, and the reason your program works after Putty is that Putty configures the COM port for you. Off the top, you are not setting DCBlength. Try this: replace DCB comSettings; with DCB comSettings = {sizeof(DCB)}; (this does two things: initializes DCBlength member, and zeros out all others).Igor Tandetnik

1 Answers

2
votes

My educated guess would be, your SetCommState call fails. You are passing it a DCB structure filled with random garbage. The reason it works after Putty is that Putty configures the port for you, and your program gets to use that configuration (since it fails to establish its own).

Change DCB comSettings; line to

DCB comSettings = {sizeof(DCB)};

This initializes DCBlength member correctly, and sets all other members to 0. Then set up other members as necessary for your device.

And check the return value of SetCommState for errors (as well as that of all other API calls).