5

At the time we are trying to create an interface for serial communication, to be able to communicate with a microprocessor.

Actually - everything works fine. Almost! To be able to communicate with our controller, we need to sync up with it. To do this, we write a string: "?0{SY}13!", and the controller should then reply with "!0{SY}F5?" to accept the request for sync. To do this, we use a writeData function (that works - we know that by using echo), and after that we use a readData to read the answer. The problem is that, for some reason, it will not read anything. Though it returns 1 for success, the chars it reads is constanly " " (nothing).

Now comes the weird part - if we use an external terminal program to initialize the port (like putty), and then close the program, then everything works fine. It accepts the sync request, answers (and we can read it), and then we can do all that we want. But unless we use an external program to initialize the port, it doesn't work.

The constructor for the initializing the interface looks like this:

SerialIF::SerialIF(int baud, int byteSize, int stopBits, char* parity, int debug)
{
    string coutport = getPort();    
    wstring wideport;               
    debug_ = debug;                 //Debuglevel

    sync = false;                   //sync starts with false

    error = false;                  //Error false as beginnging

    //this is just for converting to the right type
    for (int i = 0; i < coutport.length(); i++)
    {
        wideport += wchar_t(coutport[i]);  
    }
    const wchar_t* port = wideport.c_str();

    SerialIF::hserial = CreateFile(port,
        GENERIC_READ | GENERIC_WRITE,       
        0,
        0,
        OPEN_EXISTING,                      
        FILE_ATTRIBUTE_NORMAL,              
        0);
    if (hserial == INVALID_HANDLE_VALUE)
    {
        if (GetLastError() == ERROR_FILE_NOT_FOUND)
        {
            if (debug_ != LOW)
            {
                cout << "[-] Port " << coutport << "doesn't exist." << endl;  
            }
        }

        if (debug_ != LOW)
        {
            cout << "[-] Handle error - is there another terminal active?" << endl;
        }
        error = true;
    }

    DCB dcbParms = { 0 };
    dcbParms.DCBlength = sizeof(dcbParms);

    if (!GetCommState(hserial, &dcbParms))
    {
        if (debug_ != LOW)
        {
            cout << "[-] Couldn't get status from port " << coutport << endl;
        }
        error = true;  
    }

    if (!error)
    {
        setBaud(dcbParms, baud);
        setParity(dcbParms, parity);
        setByteSize(dcbParms, byteSize);
        setStopbits(dcbParms, stopBits);

        if (debug_ == HIGH)
        {
            cout << "[+] Serial port " << coutport << " has been activated. \nBaud-rate: " << baud << "\nParity: "
                << parity << "\nStop bits: " << stopBits << endl;
        }
    }
    else if (debug_ != LOW)
    {
        cout << "[-] Port not initialized" << endl;
    }
}

This should work - I really don't know why it shouldn't. It returns no errors, I've tried A LOT of error searching the last couple of days, I tried timeouts, I tried other ways of building it, but it all boils down to the same problem.

Why wont this initialize the port?

EDIT:

The output when trying to sync: Can't post pictures due to lack of reputation. though it outputs as follows:

[+] Serial port COM1 has been activated. Baud-rate: 9600 Parity: NONE Stop bits: 1

[+] -> ?0{SY}13! is written to the port. ((And this is where it goes in to the infinite loop reading " "))

EDIT: code for read:

const int bytesToRead = 1;              //I byte pr læsning
char buffer[bytesToRead + 1] = { 0 };   //Bufferen til data
DWORD dwBytesRead = 0;                  //Antal bytes læst
string store;                           //Store - den vi gemmer den samlede streng i
bool end = false;                       //Kontrolvariabel til whileloop.

while (end == false)                    
{
    if (ReadFile(hserial, buffer, bytesToRead, &dwBytesRead, NULL)) 
    /*Readfile læser fra interfacet vha. hserial som vi oprettede i constructoren*/
    {
        if (buffer[0] == '?')           //Da protokollen slutter en modtaget streng med "?", sætter vi end til true 
        {                               //Hvis denne læses.     
            end = true;     
        }
        store += buffer[0];
    }
    else
    {
        if (debug_ != LOW)
        {
            cout << "[-] Read fail" << endl;    //Hvis readfile returnerer false, så er der sket en fejl. 
        }
        end = true;
    }
}

if (debug_ == HIGH)
{
    cout << "[+] Recieved: " << store << endl;  //I forbindelse med debug, er det muligt at få udsrkevet det man fik ind.
}

recentIn = store;                               //RecentIN brugES i andre funktioner                
if (verify())                                   //Som f.eks. her, hvor vi verificerer dataen
{
    if (debug_ == HIGH)
    {
        cout << "[+] Verification success!" << endl;
    }
    return convertRecData(store);
}
else
{
    if (debug_ != LOW)
    {
        cout << "[-] Verification failed." << endl;
    }

    vector <string> null;   //Returnerer en string uden data i, hvis der er sket en fejl.
    return null;
}
Roddy
  • 66,617
  • 42
  • 165
  • 277
Benjamin Larsen
  • 560
  • 1
  • 7
  • 21
  • What gets outputted when the port is initialised? As in , by the line "[+] Serial Port ...." – Greycon Dec 11 '14 at 16:28
  • can you provide readData() code? – alexm Dec 11 '14 at 16:54
  • @Greycon - I've edited the original post to include the output. – Benjamin Larsen Dec 11 '14 at 17:29
  • You are relying on the kindness of strangers to initialize DCB for you. The handshaking setup is never a minor detail. Easy to debug by simply look at the DCB returned by GetCommState() btw. – Hans Passant Dec 11 '14 at 17:40
  • @HansPassant I see what you meen. Thank you for noticing. – Benjamin Larsen Dec 11 '14 at 17:57
  • Well, the setHandshake() method is starkly missing. It fits the complaint. – Hans Passant Dec 11 '14 at 18:00
  • @HansPassant I tried editing the code ` dcbParms.BaudRate = 9600; dcbParms.Parity = NOPARITY; dcbParms.StopBits = 1; SetCommState(hserial, &dcbParms);` though it had no effect on the program. The standardvalues for the rest should be fine. ' – Benjamin Larsen Dec 11 '14 at 18:12
  • 1
    Read [this post](http://stackoverflow.com/a/8910167/17034) for some background on what handshaking means. – Hans Passant Dec 11 '14 at 18:27
  • I had the same problem, although I was calling SetCommState. The link posted by Hans Passant helped my see the problem. In my case it was DtrControl. Thanks a lot !!! – BaldDude Nov 14 '18 at 18:20

3 Answers3

1

You never call SetCommState.

I'm not sure where your functions setBaud,setParity etc. come from, but I can't see how they can actually modify the serial port, as they don't have access to the comm device's handle.

Roddy
  • 66,617
  • 42
  • 165
  • 277
  • I do see what you meen. The GetCommState function is the only one reciving these. The SetBaud and so on use: "dcbParms.BaudRate = CBR_110". I'll try using the SetCommState. – Benjamin Larsen Dec 11 '14 at 18:02
  • ..Though it had the same effect using SetCommState after passing in the data to the dcb-structure :-( – Benjamin Larsen Dec 11 '14 at 18:21
  • @BenjaminLarsen You should be able to check that the port is correctly configured by typing "MODE COMn:" into a command prompt. Or, just call GetCommState a second time (into a different DCB) and compare the two. Additionally, if your code works after PUTTY runs, the compare the DCB you receive after that with the one after your setup has run. – Roddy Dec 11 '14 at 22:16
  • Oh, and one other thing: The StopBits field in the DCB is very non-intuitive (0= 1 stop bit, 1=1.5 stop bits, 2=2). You should use `dcbParms.StopBits = ONESTOPBIT;` – Roddy Dec 11 '14 at 22:21
1

ReadFile() can return success even when zero bytes are read. Use dwBytesRead to find the actual number of received characters.

while (ReadFile(hserial, buffer, 1, &dwBytesRead, NULL)) 
{
    if (dwBytesRead != 0)
    {
       store += buffer[0];

       if (buffer[0] == '?')  
       {                               
           end = true;     
           break;
       }
    }
}
alexm
  • 6,854
  • 20
  • 24
1

Had a similar problem between a PC and an arduino nano clone including a CH340. This post was the only one which discribes my problem very good. I solved it by switching off DTR (data-terminal-ready) and RTS (request-to-send) flow control, which is normaly activated after (re)start the PC or plugging in the arduino. I found a descrition of this parameters in the documentation of DCB

I know that shis post is very old but maybe i can help somebody else with this idea/solution.

DGO
  • 11
  • 2
  • Ah!! This is probably my problem as well! Thank you! https://stackoverflow.com/questions/64929987/webusb-api-working-but-the-data-received-arent-decoded-properly – Jimmy Westberg Nov 27 '20 at 19:21