2016-07-07 118 views
3

我試圖從Windows API中使用Windows API從串行端口讀取數據。當我嘗試在數據讀取時,WaitCommEvent()火得很好,作爲狀態ReadFile()調用返回1,但沒有數據被讀取。在該ReadFile documentation它說:串行端口ReadFile讀取0字節並返回true

當同步讀操作到達文件結尾ReadFile返回TRUE並將*lpNumberOfBytesRead設置爲零。

但是,我確定通過串口發送的數據中沒有EOT字符。

我目前有兩根USB電纜插入我的電腦並相互連接。我知道他們可以發送和接收數據,因爲我使用Putty測試了它們。

爲什麼ReadFile()不會讀入任何數據?

我的代碼如下。

部首:

typedef struct uart_handle 
{ 
    uint8_t port_num; 
    char port_name[10]; 
    uint32_t baud_rate; 
    uint8_t byte_size; 
    uint8_t stop; 
    uint8_t parity; 
    int32_t error; 
    HANDLE handle; 
} uart_handle; 

主文件:

uart_handle* serial_comm_init(uint8_t port_num, uint32_t baud_rate, uint8_t byte_size, uint8_t stop, uint8_t parity) 
{ 
    uart_handle* uart; 
    DCB   uart_params = { 0 }; 
    COMMTIMEOUTS timeouts = { 0 }; 
    int   status; 

    uart   = (uart_handle*) malloc(1 * sizeof(uart_handle)); 
    status  = 0; 

    // Set port name 
    if (port_num > 9) 
    { 
     sprintf(uart->port_name, "\\\\.\\COM%d", port_num); 
    } 
    else 
    { 
     sprintf(uart->port_name, "COM%d", port_num); 
    } 

    // Set baud rate 
    uart->baud_rate = baud_rate; 

    // Set byte size 
    uart->byte_size = byte_size; 

    // Set stop bit 
    uart->stop = stop; 

    // Set parity 
    uart->parity = parity; 

    // Set up comm state 
    uart_params.DCBlength = sizeof(uart_params); 
    status = GetCommState(uart->handle, &uart_params); 
    uart_params.BaudRate = uart->baud_rate; 
    uart_params.ByteSize = uart->byte_size; 
    uart_params.StopBits = uart->stop; 
    uart_params.Parity = uart->parity; 
    SetCommState(uart->handle, &uart_params); 

    // Setup actual file handle 
    uart->handle = CreateFile(uart->port_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 
    if (uart->handle == INVALID_HANDLE_VALUE) { 
     printf("Error opening serial port %s.\n", uart->port_name); 
     free(uart); 
     return NULL; 
    } 
    else { 
     printf("Serial port %s opened successfully.\n", uart->port_name); 
    } 

    // Set timeouts 
    status = GetCommTimeouts(uart->handle, &timeouts); 
    timeouts.ReadIntervalTimeout   = 50; 
    timeouts.ReadTotalTimeoutConstant = 50; 
    timeouts.ReadTotalTimeoutMultiplier = 10; 
    timeouts.WriteTotalTimeoutConstant = 50; 
    timeouts.WriteTotalTimeoutMultiplier = 10; 
    status = SetCommTimeouts(uart->handle, &timeouts); 
    if (status == 0) { 
     printf("Error setting comm timeouts: %d", GetLastError()); 
    } 

    return uart; 
} 

int32_t serial_comm_read(void* handle, uint8_t* msg, uint32_t msg_size, uint32_t timeout_ms, uint32_t flag) 
{ 
    uart_handle* uart; 
    uint32_t  num_bytes_read; 
    uint32_t  event_mask; 
    int32_t  status; 

    uart   = (uart_handle*) handle; 
    num_bytes_read = 0; 
    event_mask  = 0; 
    status   = 0; 

    memset(msg, 0, msg_size); 

    // Register Event 
    status = SetCommMask(uart->handle, EV_RXCHAR); 

    // Wait for event 
    status = WaitCommEvent(uart->handle, &event_mask, NULL); 

    printf("Recieved characters.\n"); 

    do { 
     status = ReadFile(uart->handle, msg, msg_size, &num_bytes_read, NULL); 
     printf("Status: %d\n", status); 
     printf("Num bytes read: %d\n", num_bytes_read); 
     printf("Message: %s\n", msg); 

    } while (num_bytes_read > 0); 

    printf("Read finished.\n"); 

    return 0; 
} 

輸出:

Serial port COM9 opened successfully. 
Recieved characters. 
Status: 1 
Num bytes read: 0 
Message: 
Read finished. 
+0

你確定'msg_size'不是0嗎? – ElderBug

+0

注意:'port_num> 99'會覆蓋'port_name [10]'。應該更廣泛。 'port_num'應該被檢查爲0.有效的端口號是1-256。 – chux

+0

不清楚「我確定沒有EOF字符」什麼是EOF _character_? – chux

回答

3

所示的代碼調用GetCommState()上的未初始化手柄

status = GetCommState(uart->handle, &uart_params); 

挑釁UB這樣做。其返回狀態未經測試。

由於此uart_params可能包含 BS 沒有有用的數據。


幫自己一個忙:情逆三世緣檢查所有相關函數調用的返回值(並相應地讓代碼的行爲)!將所有那些函數返回或更改之後使用的數據視爲「相關」。