0

I'm trying to configure my C++ application to communicate with a device using the COM port. I can currently do it using the HTerm software:

HTerm

However, when I try to do my C++ implementation, I can't read any byte from the port. This is my program, based in this answer:

#include "stdafx.h"
#include <stdio.h>
#include <conio.h>
#include <string>

#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

std::wstring s2ws(const std::string& s)
{
    int len;
    int slength = (int)s.length() + 1;
    len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
    wchar_t* buf = new wchar_t[len];
    MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
    std::wstring r(buf);
    delete[] buf;
    return r;
}

int main(int argc, char **argv) {

    int ch;
    char buffer[10] = {"\0"};
    HANDLE file;
    COMMTIMEOUTS timeouts;
    DWORD read, written;
    DCB port;
    HANDLE keyboard = GetStdHandle(STD_INPUT_HANDLE);
    DWORD mode;
    std::wstring port_name = s2ws("\\\\.\\COM4");
    char init[] = "5000000555";

    // open the comm port.
    file = CreateFile(port_name.c_str(),
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_EXISTING,
        0,
        NULL);

    if (INVALID_HANDLE_VALUE == file) {
        printf("opening file");
        return 1;
    }

    // get the current DCB, and adjust a few bits to our liking.
    memset(&port, 0, sizeof(port));
    port.DCBlength = sizeof(port);
    if (!GetCommState(file, &port))
        printf("getting comm state");

    if (!SetCommState(file, &port))
        printf("adjusting port settings");

    DCB dcbSerialParams = { 0 };                         // Initializing DCB structure
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);

    dcbSerialParams.BaudRate = CBR_115200;      // Setting BaudRate = 115200
    dcbSerialParams.ByteSize = 8;             // Setting ByteSize = 8
    dcbSerialParams.StopBits = ONESTOPBIT;    // Setting StopBits = 1
    dcbSerialParams.Parity = NOPARITY;

    if (!GetCommState(file, &dcbSerialParams))
        printf("getting serial params");

    if (!SetCommState(file, &dcbSerialParams))
        printf("adjusting serial params");// Setting Parity = None 

    SetCommState(file, &dcbSerialParams);  //Configuring the port according to settings in DCB

    PurgeComm(file, PURGE_TXABORT | PURGE_RXABORT); // Clear up the queue

    // set short timeouts on the comm port.
    timeouts.ReadIntervalTimeout = 1;
    timeouts.ReadTotalTimeoutMultiplier = 1;
    timeouts.ReadTotalTimeoutConstant = 1;
    timeouts.WriteTotalTimeoutMultiplier = 1;
    timeouts.WriteTotalTimeoutConstant = 1;
    if (!SetCommTimeouts(file, &timeouts))
        printf("setting port time-outs.");

    // basic terminal loop:
    do {
        if (!WriteFile(file, init, sizeof(init), &written, NULL)) {
            printf("writing data to port");
        }
        else {
            printf("written %lu bytes\n", written);
        }

        Sleep(1000);

        if (written != sizeof(init))
            printf("not all data written to port");

        // check for data on port and display it on screen.
        BOOL Status = ReadFile(file, buffer, sizeof(buffer), &read, NULL);
        if (Status) {
            printf("received %lu bytes\n", read);
        }

        // check for keypress, and write any out the port.
        if (_kbhit()) {
            ch = _getch();
            WriteFile(file, &ch, 1, &written, NULL);
            printf("closing...");
        }
        // until user hits ctrl-backspace.
    } while (ch != 127);

    // close up and go home.
    CloseHandle(keyboard);
    CloseHandle(file);
    return 0;
}

This is the output in the console:

written 11 bytes
received 0 bytes
written 11 bytes
received 0 bytes
....

Any ideas about what's going on?

EDIT 1

As @rveerd suggests, I tried disabling the handshake with these lines, same result:

dcbSerialParams.fRtsControl = RTS_CONTROL_DISABLE;
dcbSerialParams.fDtrControl = DTR_CONTROL_DISABLE;
dcbSerialParams.fOutxCtsFlow = 0;
dcbSerialParams.fOutxDsrFlow = 0;
dcbSerialParams.fNull = 0;
dcbSerialParams.fOutX = 0;
dcbSerialParams.fInX = 0;

2 Answers 2

0

Maybe you need to disable handshaking:

dcbSerialParamsfBinary = TRUE;
dcbSerialParamsfOutxCtsFlow = FALSE; // CTS output handshaking.
dcbSerialParamsfOutxDsrFlow = FALSE; // DSR output handshaking.
dcbSerialParamsfDtrControl = DTR_CONTROL_DISABLE; // DTR handshaking.
dcbSerialParamsfDsrSensitivity = FALSE; // DSR input control.
dcbSerialParamsfTXContinueOnXoff = TRUE;
dcbSerialParamsfOutX = FALSE; // XON/XOFF data flow control.
dcbSerialParamsfInX = FALSE; // XON/XOFF data flow control.
dcbSerialParamsfErrorChar = FALSE;
dcbSerialParamsfNull = FALSE;
dcbSerialParamsfRtsControl = RTS_CONTROL_DISABLE; // RTS handshaking.
dcbSerialParamsfAbortOnError = FALSE;
dcbSerialParamswReserved = 0;
dcbSerialParamsXonLim = 0;
dcbSerialParamsXoffLim = 0;
dcbSerialParamsXonChar = 0;
dcbSerialParamsXoffChar = 0;
dcbSerialParamsErrorChar = 0;
dcbSerialParamsEofChar = 0;
dcbSerialParamsEvtChar = 0;
Sign up to request clarification or add additional context in comments.

Comments

0

I had the hex values for the commands in the wrong format, this is how they should go:

unsigned char buffer[20] = { 0x00 };
unsigned char init[] = { 0x50, 0x00, 0x00, 0x05, 0x55};

Thanks to this answer in the MS forum!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.