winapigccusbserial-communicationraspberry-pi-pico

Serial Communication Issue with WinApi and Raspberry pi Pico


I am experiencing a weird problem while trying to make a serial communication with RPi-Pico -> PC.

From Pico, I am sending a packet of 9 Bytes (8 Byte Data from ADC + \n) once a second through Serial communication using the USB BUS.

While reading it from Windows, my program reads nothing, only stays at the if (!WaitCommEvent(hComm, &dwEventMask, NULL)) stage.

But, if I run Putty with any configuration, then data is shown in Putty. After closing Putty, if I run my program, surprisingly it also reads data without any fail! But after restarting the Pico, the same situation comes back.

That's so far very much an unknown feature for me. Could any of you help me to solve that situation?

I am sending the code snippet for analysis:

hComm = CreateFileA(commPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hComm == INVALID_HANDLE_VALUE)
    cout << "\nError Port " << commPortName << " can't be opened!!!\n";
else
    cout << "\nPort " << commPortName << " is opened!!\n";
dcbParams.DCBlength = sizeof(dcbParams);
if (!GetCommState(hComm, &dcbParams))
    cout << "\nError in GetCommState()\n";
dcbParams.BaudRate = CBR_115200; dcbParams.ByteSize = 8; 
dcbParams.StopBits = ONESTOPBIT; dcbParams.Parity = NOPARITY;
if (!SetCommState(hComm, &dcbParams))
    cout << "\nError in setting Device-Control Block(DCB)\n";
else
{
    cout << "\n\n    Setting DCB Structure Successfull" 
        << "\n       Baudrate --> " << dcbParams.BaudRate 
        << "\n       ByteSize --> " << (unsigned int)dcbParams.ByteSize 
        << "\n       StopBits --> " << (unsigned int)dcbParams.StopBits 
        << "\n       Parity   --> " << (unsigned int)dcbParams.Parity;
}
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
if (!SetCommTimeouts(hComm, &timeouts))
    cout << "\n\n    Error! in Setting Time Outs\n";
else
    cout << "\n\n    Setting Serial Port Timeouts Successfull\n";
if (!SetCommMask(hComm, EV_RXCHAR))
    cout << "\n\n    Error! in Setting Communication Mask\n";
else
    cout << "\n\n    Setting Communication Mask successfull\n";
cout << "\n\n    Waiting for Data Reception....\n";
for (int i = 0; i <= 99; i+=1)
{
    if (!WaitCommEvent(hComm, &dwEventMask, NULL))
        cout << "\n    Error! in Setting Wait for Communication Event...!\n";
    else
    {
        ReadFile(hComm, &readBuffer, sizeof(readBuffer), &noBytesRead, NULL);
        cout << "           " << readBuffer;
    }
}
CloseHandle(hComm);

Solution

  • As @Luzian said in the question, it is a device configuration issue(SetCommState). After checking the putty source, The DTR (data-terminal-ready) flow control is not enabled in @Luzian 's code. And RPi-Pico proved to be strictly DTR controlled.

    The following code is excerpted from putty.

        /*
         * Set up the serial port parameters. If we can't even
         * GetCommState, we ignore the problem on the grounds that the
         * user might have pointed us at some other type of two-way
         * device instead of a serial port.
         */
        if (GetCommState(serport, &dcb)) {
            const char *str;
    
            /*
             * Boilerplate.
             */
            dcb.fBinary = true;
            dcb.fDtrControl = DTR_CONTROL_ENABLE;
            dcb.fDsrSensitivity = false;
            dcb.fTXContinueOnXoff = false;
            dcb.fOutX = false;
            dcb.fInX = false;
            dcb.fErrorChar = false;
            dcb.fNull = false;
            dcb.fRtsControl = RTS_CONTROL_ENABLE;
            dcb.fAbortOnError = false;
            dcb.fOutxCtsFlow = false;
            dcb.fOutxDsrFlow = false;
            ...
        }