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

树莓派与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记录会话可完整接收所有字节,无异常
  • 树莓派上自研软件丢失大量字节
  • 执行以下命令测试:
    (stty raw; cat > received.log) < /dev/ttyACM0
    
    多数场景下丢失0x0A至0x16之间的字节,0x7E和0x7F也经常丢失;偶尔能完整捕获256字节;在Pico的循环中添加10ms延迟后,该命令可正常捕获所有数据(原UART设计速率为9600-115200bps,当前循环输出速率>200kbps,满足需求)

树莓派端初始化代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 13:38:13