单代码实现双设备数据传输及超声波传感器串口接收头异常问题
问题分析与解决方案
核心问题:双串口同时打开时,超声波传感器的数据包头部异常(读取到0x5f而非预期的0xff),但单串口场景下工作正常,读取长度ret=4符合预期。以下是针对性排查与解决步骤:
1. 排查串口配置冲突
- 必须确保两个串口的波特率、数据位、停止位、奇偶校验与传感器要求完全一致,双串口初始化时极易出现变量混淆导致其中一个串口配置被错误覆盖。示例标准化配置代码:
struct termios tty; memset(&tty, 0, sizeof(tty)); // 获取当前串口配置 if (tcgetattr(fd, &tty) != 0) { perror("tcgetattr"); return -1; } // 设置波特率(以9600为例,需匹配传感器参数) cfsetospeed(&tty, B9600); cfsetispeed(&tty, B9600); // 配置8N1(8数据位、无校验、1停止位) tty.c_cflag &= ~PARENB; tty.c_cflag &= ~CSTOPB; tty.c_cflag &= ~CSIZE; tty.c_cflag |= CS8; // 禁用硬件流控制,启用本地模式与数据接收 tty.c_cflag &= ~CRTSCTS; tty.c_cflag |= CREAD | CLOCAL; // 禁用规范模式与回显 tty.c_lflag &= ~ICANON; tty.c_lflag &= ~(ECHO | ECHOE | ECHONL); // 禁用软件流控制 tty.c_iflag &= ~(IXON | IXOFF | IXANY); tty.c_oflag &= ~OPOST; // 设置读取超时(至少4字节,超时5秒) tty.c_cc[VMIN] = 4; tty.c_cc[VTIME] = 5; // 生效配置 if (tcsetattr(fd, TCSANOW, &tty) != 0) { perror("tcsetattr"); return -1; } - 检查变量命名:确认打开
/dev/ttyUSB0(传感器串口)和/dev/ttyUSB1的文件描述符未被混用,避免误修改传感器串口的配置参数。
2. 清理串口缓存与优化读取时序
- 打开串口后、读取数据前,强制清空传感器对应串口的输入缓存,避免残留的垃圾数据干扰:
tcflush(fd_usb0, TCIFLUSH); // fd_usb0为传感器连接的串口文件描述符 - 双串口初始化完成后,给传感器预留1-2秒的初始化时间再开始读取,避免设备未就绪时输出异常数据。
3. 排查硬件干扰
- 若两个USB串口共用同一集线器,可能因供电不足或信号串扰导致数据位翻转(
0xff二进制为11111111,0x5f为01011111,属于最高位翻转),尝试将两个设备插在主板不同的原生USB接口上,避开共用集线器。 - 检查传感器供电稳定性,双设备同时工作可能导致电压波动,影响传感器的信号输出精度。
4. 验证读取逻辑准确性
- 确认读取操作指向正确的串口:打印
fd_usb0和fd_usb1的数值,排查是否误将另一串口的数据读到了packet_ultrasonic数组中。 - 改用逐字节读取的方式验证:先读取第一个字节确认是否为
0xff,再读取剩余3字节,排查是否存在缓存拼接或字节顺序错误:uint8_t header; int ret = read(fd_usb0, &header, 1); if (ret == 1 && header == 0xff) { // 读取剩余3字节 ret += read(fd_usb0, packet_ultrasonic + 1, 3); } else { // 丢弃错误数据,清空缓存 tcflush(fd_usb0, TCIFLUSH); }
内容的提问来源于stack exchange,提问作者chobo
相关产品推荐
相关产品推荐

