Linux嵌入式UART可发送无法接收、select返回0问题求助
select返回0不代表串口繁忙,仅表示在你设定的5秒超时窗口内,串口没有产生可读事件,不是硬件被占用的问题。你遇到的接收失败是代码实现存在多个错误导致的,具体问题如下:
1. 流控配置逻辑完全写反
你实现的buildFlowControl函数三个分支的配置全部匹配错误:
- 无流控(NO_FLOW_CTRL)场景下你反而开启了硬件流控
CRTSCTS,如果你的RS232接线没有接RTS/CTS引脚,串口内核驱动会一直等待硬件流控信号就绪,直接导致无法接收数据 - FC_RTSCTS(硬件流控)场景你反而关了
CRTSCTS开了软件流控,FC_XONXOFF(软件流控)场景你反而关了软件流控,逻辑完全颠倒
修正后的流控配置参考:
static int buildFlowControl(Enum_FlowCtrl fc, struct termios* term) { if (NO_FLOW_CTRL == fc) { term->c_cflag &= ~CRTSCTS; // 无流控关闭硬件流控 term->c_iflag &= ~(IXON | IXOFF | IXANY); // 关闭软件流控 } else if (FC_RTSCTS == fc) { term->c_cflag |= CRTSCTS; // 硬件流控开启CRTSCTS term->c_iflag &= ~(IXON | IXOFF | IXANY); } else if (FC_XONXOFF == fc) { term->c_cflag &= ~CRTSCTS; term->c_iflag |= (IXON | IXOFF | IXANY); // 软件流控开启相关标志位 }else{ return -1; } return 0; }
2. 串口配置顺序错误,前面的配置全部被覆盖
你在UART_Open里先初始化了term结构体、调用cfmakeraw、设置CREAD之后才调用tcgetattr读当前串口配置,这会导致你前面所有对term的修改全部被tcgetattr读出的默认值覆盖,完全不生效。
修正后的配置顺序参考:
fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY); // 建议加O_NOCTTY防止串口控制进程,O_NDELAY设置非阻塞 if (fd < 0) { // 必须补充open失败的错误处理 } tcgetattr(fd, &term); // 先读取现有配置,再基于该配置修改参数 cfmakeraw(&term); term->c_cflag |= CREAD | CLOCAL; // 建议加CLOCAL忽略调制解调器状态线,避免被外部信号影响 // 后续再调用各个buildxxx函数修改参数
3. select的fd_set未在每次循环前重新初始化
select调用结束后会修改传入的fd_set,仅保留有事件触发的文件描述符。你当前只在循环外初始化了一次fd_set,第一次超时后fd_set里的串口描述符就被清空了,后续所有循环调用select的时候传入的都是空的fd_set,必然永远返回0超时。
修正方式是把FD_ZERO和FD_SET操作放到while循环内部,每次调用select前重新设置fd_set:
while(true) { FD_ZERO(&fdset); FD_SET(socketFileDescriptor, &fdset); ret = select(socketFileDescriptor + 1, &fdset, NULL, NULL, &timeout); timeout.tv_sec = 5; // 后续逻辑不变 }
4. 接收逻辑存在死循环缺陷
你在可读事件触发后进入了do{}while(true)的死循环,第一次读到数据后就永远卡在这个循环里,而且完全没有判断read的返回值,即使读失败也不会退出,同时加了sleep(3)会导致大量数据丢包。建议去掉该死循环,单次read后回到外层select循环等待下一次事件,同时处理read的返回值:
if (FD_ISSET(socketFileDescriptor, &fdset)) { memset(buffer, 0x0, sizeof(buffer)); ret = read(socketFileDescriptor, buffer, 100); if (ret > 0) { // 处理收到的ret个字节 } else if (ret == 0) { // 串口断开相关处理 } else { // 读错误处理 } }
补充验证建议
你可以先不用自己的程序,直接在设备侧执行cat /dev/ttyHSL0命令,然后在minicom侧发送数据,看能不能收到数据:如果能收到就确认是代码问题,否则检查硬件接线、串口驱动权限和设备树配置。
内容的提问来源于stack exchange,提问作者Jazzy
相关产品推荐
相关产品推荐

