树莓派与Pico USB CDC串口通信延迟及丢包问题排查
树莓派与Raspberry Pi Pico USB CDC串口通信丢包及缓冲问题
原本树莓派与Raspberry Pi Pico通过UART引脚通信正常,因环境存在噪声干扰,切换为USB CDC(采用差分对的USB串口方案)。
Pico端添加以下代码后恢复正常:
stdio_set_translate_crlf(&stdio_usb, false);
注:协议为二进制格式,换行转换会造成通信干扰
但树莓派端出现两处异常:
- 原UART引脚读取为无缓冲/即时模式,切换至USB后,需积累大量数据才会传输到程序中
- 存在大量丢包情况
测试验证情况
- Pico运行测试程序,持续输出0x00至0xFF的字节,连接Windows主机用Putty记录会话可完整接收所有字节,无异常
- 树莓派上自研软件丢失大量字节
- 执行以下命令测试:
多数场景下丢失0x0A至0x16之间的字节,0x7E和0x7F也经常丢失;偶尔能完整捕获256字节;在Pico的循环中添加10ms延迟后,该命令可正常捕获所有数据(原UART设计速率为9600-115200bps,当前循环输出速率>200kbps,满足需求)(stty raw; cat > received.log) < /dev/ttyACM0
树莓派端初始化代码
uart0_fd = ::open("/dev/ttyACM0", O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); //以非阻塞读写模式打开 struct termios options; tcgetattr(uart0_fd, &options); cfmakeraw(&options); options.c_cflag = B115200 | CS8 | CLOCAL | CSTOPB | CREAD; //设置波特率 options.c_iflag = IGNPAR | IGNBRK; options.c_oflag = 0; options.c_lflag = ICANON | NOFLSH; options.c_cc[VTIME] = 10; tcflush(uart0_fd, TCIFLUSH); tcsetattr(uart0_fd, TCSANOW, &options); struct termios tty; memset (&tty, 0, sizeof tty); if (tcgetattr (uart0_fd, &tty) != 0) { printf ("error %d from tggetattr\r\n", errno); return; } tty.c_cc[VMIN] = 0; tty.c_cc[VTIME] = 5; // 0.5秒读取超时 if (tcsetattr (uart0_fd, TCSANOW, &tty) != 0) { ... }
树莓派端读取代码
void printHex(const uint8_t *data, const size_t size) { for (uint32_t index = 0; index < size; ++index) { printf("%.2X",data[index]); } } void execute() { printf("UART thread started\r\n"); sendOverUart(COMMAND_RESEND_ALL, 0xFFFF); int local_uart0_fd = uart0_fd; unsigned char buffer[100]; memset(buffer, 0, sizeof(buffer)); while (!shouldFinish) { int bytesRead = read(local_uart0_fd, &buffer, sizeof(buffer) - 1); buffer[bytesRead + 1] = '\0'; if (-1 == bytesRead) { if (errno != EAGAIN) { printf("UART... error reading %d\r\n", errno); } } else { printHex(buffer, bytesRead); fflush(stdout); continue; } if (EFAULT == errno) { } } ::close(local_uart0_fd); printf("UART thread finished\r\n"); }
使用UART引脚(树莓派的/dev/serial0)时一切正常,切换至USB后是否遗漏了某些配置?需要实现无缓冲的快速、可靠接收(不丢失字节)。当前树莓派程序的输出始终是00-0A,接着DE-FF,仅捕获了约88个字节。
内容的提问来源于stack exchange,提问作者user1532080
相关产品推荐
相关产品推荐

