正确读取或编写串口Windows API

时间:2014-05-01 21:09:33

标签: c++ winapi serial-port

我已经阅读了很多串口读写问题。到目前为止,没有人帮我弄清楚我的代码缺失了什么。 c ++的msdn示例有未定义的变量和缺少括号,所以虽然我可以添加括号但它仍然不起作用。这就是我现在所拥有的。看来我可以打开端口并进行配置,但我无法读取数据的字节/字符。我真的只想要一个简单的异步串行读/写,以便从Arduino中读取aprogram。

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

};

所以我删除了读取功能。我现在得到一个char,它报告读取1个字节,但char的值不正确。我得到一系列48,13,10,偶尔为该字节的50值。然而,Arduino正在发送一个系列0和#128,然后通过TerraTerm验证128。我还需要什么?

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

}

所以现在我可以读取一个字节的数据但是我不能写一个字节或更多的字节到端口。我刚收到ERROR_IO_PENDING。也有人可以帮忙解决这个问题。写下我班级的功能。

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

我从main调用这两个函数,如下所示

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

目前,arduino设置为读入字节并重复它们返回到pc。它在arduino IDE串口监视器上做得很好,所以现在我只需要让这个pc程序写出来。

1 个答案:

答案 0 :(得分:3)

您的bytesRead变量是未初始化的指针。您将无效地址传递给ReadFile()以写入。

LPDWORD bytesRead替换为DWORD bytesRead,然后使用ReadFile()将其传递给&bytesRead

修改 同时消除FILE_FLAG_OVERLAPPED。您没有正确处理它,如果您在阅读之前WaitForSingleObject()使用它是没有意义的。