串口和LCD使用同一队列传递status,多消费者竞争导致 LCD 延迟丢包

现象

  • LCD 显示明显滞后于串口输出
  • LCD 偶尔丢失 M1 的 PWM 更新,RPM 刷新不稳定

根因

status_queue(1 个队列)被 USARTLCD 两个任务同时消费:

MotorCtrlTask --→ status_queue --+--→ UartCommTask(printf,微秒级)
                                 +--→ LcdDisplayTask(SPI 绘制,毫秒级)
  • UartCommTask 仅做 printf(),微秒级完成,立刻回到等待队列
  • LcdDisplayTask 需 lcd_fill() + lcd_show_string() 等 SPI 逐像素绘制,毫秒级耗时
  • 结果:USART 几乎每次都能抢到消息,LCD 只能拿到 USART 处理间隙的少数消息

本质问题:多消费者单队列 + 消费者处理速度差异 → 竞争消费,慢消费者丢包。

修复

拆分为两路独立队列,各消费者持有专属队列:

MotorCtrlTask --+--→ usart_status_queue (16) --→ UartCommTask(独立消费)
                +--→ lcd_status_queue   (16) --→ LcdDisplayTask(独立消费)
文件 改动
freertos.c 用户区新增 usart_status_queue / lcd_status_queuexQueueCreate(16, sizeof(motor_status_t))
motor_app.c 每条状态 xQueueSend 到两个队列各一份
usart_app.c 改为 xQueueReceive(usart_status_queue, ...)osStatus_t/osOKBaseType_t/pdPASS
lcd_app.c 改为 xQueueReceive(lcd_status_queue, ...)osStatus_t/osOKBaseType_t/pdPASS

经验

  • FreeRTOS 队列是点对点通信机制,一条消息只能被一个消费者取走
  • 需要广播数据给多个消费者时,必须用多队列分发或 Event Group + 共享内存
  • CubeMX 生成的 status_queueHandle 保留在非用户区无法删除,但可弃用
posted @ 2026-05-05 23:38  alanala  阅读(5)  评论(0)    收藏  举报