Frage

I have read alot of issues with serial port reading and writing. None so far have helped me figure out what my code is missing. The msdn example for c++ has undefined variables and missing brackets so although i can add brackets it still does not function. Here's what I've got at this point. It appears I can open the port and do the configuration but I cannot read a byte/char of data. I really just want a simple asyncronous serial read/write for aprogram to read from an Arduino.

class MY_SERIAL
{

HANDLE serialinstance;

DWORD      dwStoredFlags;
DWORD      dwRes;
DWORD      dwCommEvent;
OVERLAPPED osStatus = {0};
BOOL       fWaitingOnStat;
//dwStoredFlags = EV_BREAK | EV_CTS   | EV_DSR | EV_ERR | EV_RING | EV_RLSD | EV_RXCHAR |      EV_RXFLAG | EV_TXEMPTY ;


DCB dcb;
COMMTIMEOUTS timeouts;

COMMCONFIG serialconfig;



public:
char inBuffer[1000];
char outBuffer[100];

PDWORD noBytes;

void close_serial()
{
    CloseHandle(serialinstance);
}
//----------------------------------------------------
bool open_serial(LPCSTR portNumber)   // serial port name use this format  "\\\\.\\COM10"
{

    serialinstance = CreateFile(portNumber, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    if(serialinstance == INVALID_HANDLE_VALUE)
    {
        int error = GetLastError();
        printf("ERROR opening serial port  %s\r\n", portNumber);
        if(error == 0x2){printf("ERROR_FILE_NOT_FOUND\r\n");}
        if(error == 0x5){printf("ERROR_ACCESS_DENIED\r\n");}
        if(error == 0xC){printf("ERROR_INVALID_ACCESS\r\n");}
        if(error == 0x6){printf("ERROR_INVALID_HANDLE\r\n");}
        printf("error code %d\r\n", error);
        return false;
    }
    if(GetCommState(serialinstance, &dcb)!= true)
    {
        printf("ERROR getting current state of COM   %d \r\n", GetLastError());
        return false;
    }
    else{printf("debug   read current comstate\r\n");}


    FillMemory(&dcb, sizeof(dcb), 0); //zero initialize the structure
    dcb.DCBlength = sizeof(dcb);      //fill in length

    dcb.BaudRate = CBR_115200;     //  baud rate
    dcb.ByteSize = 8;             //  data size, xmit and rcv
    dcb.Parity   = NOPARITY;      //  parity bit
    dcb.StopBits = ONESTOPBIT;

    if(SetCommState(serialinstance, &dcb) != true)
    {
        printf("ERROR setting new state of COM   %d \r\n", GetLastError());
        return false;
    }
    else{printf("debug   set new comstate\r\n");}
    /*
    if (!BuildCommDCB("115200,n,8,1", &dcb)) //fills in basic async details
    {
        printf("ERROR getting port comstate\r\n");
        return FALSE;
    }
    */
    if (!SetCommMask(serialinstance, EV_RXCHAR))
    {
        printf("ERROR setting new COM MASK   %d \r\n", GetLastError());
        return false;
    }
    else{printf("debug   commmask set\r\n");}
    timeouts.ReadIntervalTimeout = MAXDWORD;
    timeouts.ReadTotalTimeoutMultiplier = 20;
    timeouts.ReadTotalTimeoutConstant = 0;
    timeouts.WriteTotalTimeoutMultiplier = 0;
    timeouts.WriteTotalTimeoutConstant = 0;

    if (!SetCommTimeouts(serialinstance, &timeouts))
    {
        printf("ERROR setting timeout parameters\r\n");
        return false;
    }
    else{printf("debug   timeouts set\r\n");}
    osStatus.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (osStatus.hEvent == NULL)
    {// error creating event; abort
        printf("ERROR creating Serial EVENT\r\n");
        return false;
    }
    else{printf("debug   event created set\r\n");}
    osStatus.Internal = 0;
    osStatus.InternalHigh = 0;
    osStatus.Offset = 0;
    osStatus.OffsetHigh = 0;
    assert(osStatus.hEvent);
    printf("debug   com port setting complete\r\n");






    return true;
}
//---------------------------------------------------------

bool read_serial_simple()
{
    char m[1000];
    LPDWORD bytesRead;



    if (WaitCommEvent(serialinstance, &dwCommEvent, &osStatus))
    {
        if(dwCommEvent & EV_RXCHAR)
        {
            ReadFile(serialinstance, &m, 1, bytesRead, &osStatus);
            printf("data read =   %d,       number bytes read =     %d  \r\n", m, bytesRead);
            return true;
        }
        else
        {
            int error = GetLastError();
            if(error == ERROR_IO_PENDING){printf(" waiting on incomplete IO\r\n");}
            else{printf("ERROR %d\r\n", error);}
            return false;
        }
    }
    return false;
}

};

So I stripped the read function down. I now get a char and it reports reading 1 byte but the value of the char is incorrect. I get a series of 48, 13, 10, and occasionally a 50 value for the byte. However the Arduino is sending a series a 0's then a 128 as verified with TerraTerm. What else do I need here?

bool read_serial_simple()
{
    unsigned char m = 0;
    DWORD bytesRead;
    if(ReadFile(serialinstance, &m, 1, &bytesRead, &osStatus) == true)
    {
        printf("data read =   %d,       number bytes read =     %d  \r\n", m, bytesRead);
        return true;
    }
    else{
        int error = GetLastError();
        if(error == ERROR_IO_PENDING){printf(" waiting on incomplete IO\r\n");}
        else{printf("ERROR %d\r\n", error);}
        return false;
    }

}

So now I can read a byte of data but I cannot write a byte or more to the port. I just get ERROR_IO_PENDING. Can someone help out with this as well. Write function of my class below.

bool write(DWORD noBytesToWrite)
{
    if(WriteFile(serialinstance, outBuffer, noBytesToWrite, NULL, &osStatus) == true)
    {
        printf("message sent\r\n");
        return true;
    }
    else
    {
        int error = GetLastError();
        if(error != ERROR_IO_PENDING){LastError();}
        return false;
    }
}

I'm calling both functions from main as follows

myserial.open_serial(COM12);
myserial.outBuffer[0] = 'H';
myserial.outBuffer[1] = 'e';
myserial.outBuffer[2] = 'L';
myserial.outBuffer[3] = 'l';
myserial.outBuffer[4] = 'O';
for(int n=0; n<5; n++){printf("%c", myserial.outBuffer[n]);}
printf("\r\n");

while(1)
{
    myserial.read();
    myserial.write(5);
    //system("PAUSE");
}

Currently the arduino is set up to read bytes in and repeat them back to the pc. It is doing this fine on the arduino IDE serial monitor so now I just need to get this pc program to write out.

War es hilfreich?

Lösung

Your bytesRead variable is an uninitialized pointer. You are passing an invalid address to ReadFile() to write to.

Replace LPDWORD bytesRead with DWORD bytesRead, then pass it to ReadFile() using &bytesRead.

Edit: Also eliminate the FILE_FLAG_OVERLAPPED. You are not handling it properly, and there is no point in using it if you WaitForSingleObject() before reading.

Andere Tipps

Sorry my answer is a bit late, but as I was checking up on another serial port detail I found this.

There is a bit flaw in the original code. You are calling CreateFile with the FILE_FLAG_OVERLAPPED flag. This means you want to use non-blocking calls. You either need to remove this flag, or change your ReadFile and WriteFile calls so that they include a pointer to an OVERLAPPED structure WriteFile.

Your code works with ReadFile as it will complete syncrhronously as there is a character already waiting. The WriteFile will return IO_PENDING result to indicate that the write has been queued.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top