【问题标题】:Serial port ReadFile reads 0 bytes and returns true串口ReadFile读取0字节返回true
【发布时间】:2016-11-09 22:10:53
【问题描述】:

我正在尝试使用 Windows API 从 Windows 7 中的串行端口读取数据。当我尝试读入数据时,WaitCommEvent() 触发得很好,ReadFile() 调用返回 1 作为状态,但没有读入数据。在ReadFile documentation 中它说:

当同步读取操作到达文件末尾时,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.

【问题讨论】:

  • 你确定msg_size 不是 0 吗?
  • 注意:port_num > 99 导致覆盖port_name[10]。应该更宽。 port_num 应检查 0。有效端口号为 1-256。
  • 不清楚“我确定没有 EOF 字符” 什么是 EOF 字符?
  • @chux 没有意识到超过 100 个端口是有效的。感谢您的输入
  • 显示的代码在未初始化的句柄上调用 GetCommState():... = GetCommState(uart->handle, &uart_params); 引发 UB 这样做。它的返回状态未经测试。由于这个uart_params 可能包含BS。

标签: c windows winapi serial-port initialization


【解决方案1】:

显示的代码在未初始化句柄上调用GetCommState():

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

激怒 UB 这样做。其返回状态未经测试。

由于这个uart_params可能包含BS没有有用的数据。


帮自己一个忙: 始终检查所有相关函数调用的返回值(并让代码采取相应措施)!将所有返回或更改之后使用的数据的函数视为“相关”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-16
    • 1970-01-01
    • 1970-01-01
    • 2019-06-03
    • 1970-01-01
    相关资源
    最近更新 更多