Teltonika TRB246串口通信方案故障排查求助
解决方案建议
一、修复microcom Shell脚本问题
你的推测(microcom启动不及时)大概率成立,默认microcom启动时可能未提前完成串口初始化,导致错过首批数据。可按以下步骤优化脚本:
- 提前初始化串口参数:用
stty在启动microcom前强制配置串口(参数根据实际设备调整,示例为9600波特率、8N1格式),避免microcom自动初始化的延迟:
# 先配置目标串口,比如/dev/ttyUSB0 stty -F /dev/ttyUSB0 raw speed 9600 cs8 -cstopb -parenb -echo # 启动microcom,-w参数可指定等待设备就绪的时长(部分BusyBox版本支持) microcom -w 1000 /dev/ttyUSB0
- 改用持续监听逻辑:如果microcom仍偶尔丢包,可换用BusyBox自带的
cat+xxd实现无间隙监听,跳过microcom的启动间隙:
stty -F /dev/ttyUSB0 raw speed 9600 cs8 -cstopb -parenb # 持续读取串口数据并转为十六进制输出 cat /dev/ttyUSB0 | xxd -p
- 调整启动时机:将脚本加入
/etc/rc.local设为开机自启,确保系统启动时就抢占串口资源,避免后续启动延迟。
二、修复C程序read()与终端配置问题
核心问题是终端配置未生效,导致串口处于错误的读取模式,按以下步骤排查修复:
- 确保终端配置代码正确生效:打开串口后立即配置参数,并用
TCSANOW强制生效,示例代码片段:
#include <stdio.h> #include <fcntl.h> #include <termios.h> #include <unistd.h> #include <errno.h> int main() { // 打开串口,可去掉O_NONBLOCK改为阻塞模式 int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd == -1) { perror("open"); return 1; } struct termios tty; // 先获取当前配置,避免覆盖必要参数 if (tcgetattr(fd, &tty) != 0) { perror("tcgetattr"); close(fd); return 1; } // 配置为raw模式,禁用规范模式、回显等干扰项 cfmakeraw(&tty); // 设置波特率,根据实际设备调整 cfsetispeed(&tty, B9600); cfsetospeed(&tty, B9600); // 配置8N1格式 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; // 调整VMIN和VTIME适配每秒一次的数据包: // 若数据包长度固定,设VMIN为包长度,VTIME=0(等待满字节再返回) // 若长度不固定,设VMIN=0,VTIME=10(1秒超时,有数据就返回) tty.c_cc[VMIN] = 0; tty.c_cc[VTIME] = 10; // 强制生效配置 if (tcsetattr(fd, TCSANOW, &tty) != 0) { perror("tcsetattr"); close(fd); return 1; } // 读取循环 unsigned char buf[256]; ssize_t n; while (1) { n = read(fd, buf, sizeof(buf)); if (n > 0) { printf("Read %zd bytes: ", n); for (int i=0; i<n; i++) printf("%02X ", buf[i]); printf("\n"); } else if (n == -1 && errno != EAGAIN) { // 忽略EAGAIN(无数据可读),处理其他错误 perror("read"); break; } usleep(10000); // 避免CPU空转 } close(fd); return 0; }
- 处理EAGAIN问题:
read()返回EAGAIN是非阻塞模式下无数据的正常提示,若不需要非阻塞,可去掉O_NONBLOCK打开标志;若保留非阻塞,需在循环中忽略该错误,等待数据到来。 - 检查串口权限:确保程序运行时拥有串口读写权限,可临时用
chmod 666 /dev/ttyUSB0测试,或把运行用户加入dialout组。
三、定制BusyBox microcom的方法
BusyBox的microcom源码位于miscutils/microcom.c,可修改以下部分解决启动延迟:
- 在
main()函数打开串口后,立即调用tcsetattr配置串口参数(参考上述C程序的配置逻辑),不再依赖系统默认配置; - 在启动读取循环前增加短暂延迟,比如
usleep(50000),等待串口设备就绪; - 修改
read()循环对应的VMIN/VTIME参数,适配每秒一次的数据包频率。
编译时需在BusyBox的.config中开启CONFIG_MICROCOM=y,交叉编译生成新的busybox二进制后,替换设备上的/bin/busybox即可。
内容的提问来源于stack exchange,提问作者SFrancis
相关产品推荐
相关产品推荐

