You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

vxWorks下串口UART调用select()始终返回0无法读取数据

问题分析与解决方案

针对vxWorks下串口读取使用select()始终返回0的问题,核心排查方向和解决步骤如下:

1. 检查select()调用参数正确性

这是最容易忽略的错误点:

  • select()的第一个参数必须是最大文件描述符+1,你的串口fd固定为4,所以该参数必须传入5,而非4。如果传入4,select()会忽略fd=4的监控,直接返回0。
  • 确认FD_SET正确将this->fd加入读描述符集合,FD_ZERO初始化集合无遗漏。
  • 超时时间赋值要准确:400us对应timeout.tv_sec = 0; timeout.tv_usec = 400;

正确调用示例:

fd_set readFds;
struct timeval timeout;

FD_ZERO(&readFds);
FD_SET(this->fd, &readFds);

timeout.tv_sec = 0;
timeout.tv_usec = 400;

// 第一个参数必须为5
int ret = select(5, &readFds, NULL, NULL, &timeout);

2. 适配vxWorks系统时钟精度限制

vxWorks的系统tick分辨率默认多为1ms(对应CONFIG_VXWORKS_SYS_TICK_RATE=1000),select()的超时时间会被对齐到系统tick的整数倍。400us小于1ms,会被系统视为立即超时,导致还未等到串口数据就返回0。

解决方法:

  • 临时调整超时时间到1ms(timeout.tv_usec = 1000),匹配IMU的1kHz数据发送周期,既能覆盖数据包传输耗时,又能适配系统tick精度。
  • 如果必须用更短超时,可通过sysClkRateGet()查看当前tick频率,若允许则修改系统tick为2000Hz(500us粒度),但该操作可能影响其他系统模块,需谨慎评估。

3. 修正串口终端属性配置

若串口处于规范模式,select()会等待换行符或缓冲区满才触发可读信号,而IMU的二进制数据包不含换行符,导致select()一直不触发。需配置为非规范模式:

struct termios termAttr;
tcgetattr(this->fd, &termAttr);

// 设置波特率
cfsetispeed(&termAttr, B921600);
cfsetospeed(&termAttr, B921600);

// 配置数据格式:8位数据、无校验、1位停止位
termAttr.c_cflag &= ~(PARENB | CSTOPB | CSIZE);
termAttr.c_cflag |= CS8;

// 禁用规范模式、回显、信号
termAttr.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
// 禁用流控制
termAttr.c_iflag &= ~(IXON | IXOFF | IXANY);
// 禁用输出处理
termAttr.c_oflag &= ~OPOST;

// 设置非阻塞读取:有数据就返回,无数据立即退出
termAttr.c_cc[VMIN] = 0;
termAttr.c_cc[VTIME] = 0;

tcsetattr(this->fd, TCSANOW, &termAttr);

4. 排查串口硬件与接收状态

  • 用ioctl(this->fd, FIONREAD, &bytesAvail)在select()前查询串口接收缓冲区字节数:
    • 若bytesAvail>0但select()返回0:说明select()参数配置错误。
    • 若bytesAvail=0:排查硬件连接、串口引脚配置(如RX/TX是否接反)、IMU是否正常发送数据。

内容的提问来源于stack exchange,提问作者Dark Sorrow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 19:23:15