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

STM32使用DMA+环形缓冲区解析MAVLink 2时丢包问题排查

STM32 UART读取Pixhawk4遥测丢包问题修复方案

问题根源

你用大小为1的缓冲区是丢包的核心原因:单字节缓冲区会导致UART/DMA中断触发过于频繁,CPU来不及处理后续 incoming 数据,要么DMA传输时覆盖未处理的字节,要么中断响应不及时直接丢帧。

具体修复步骤

1. 替换单字节缓冲区为环形缓冲区

改用环形缓冲区可以批量缓存数据,减少中断触发频率,避免数据丢失。建议缓冲区大小至少覆盖Mavlink单包最大长度(Mavlink2最大包长255字节,选256字节足够):

#define UART_RX_BUF_SIZE 256
uint8_t uart_rx_buf[UART_RX_BUF_SIZE];
// 环形缓冲区读写指针(volatile确保编译器不优化)
volatile uint16_t rx_read_ptr = 0;
volatile uint16_t rx_write_ptr = 0;

2. 调整DMA配置为循环模式+半满/全满中断

将DMA设为循环模式,让它持续填充缓冲区,同时开启半满和全满中断,批量处理数据:

// 启动DMA循环接收,缓冲区长度设为UART_RX_BUF_SIZE
HAL_UART_Receive_DMA(&huart1, uart_rx_buf, UART_RX_BUF_SIZE);
// 开启DMA半满(HT)和全满(TC)中断
__HAL_DMA_ENABLE_IT(&hdma_usart1_rx, DMA_IT_HT | DMA_IT_TC);

3. 优化中断回调函数

在半满/全满中断回调里更新环形缓冲区的写指针,确保数据被正确缓存:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if (huart->Instance == USART1) {
        // 缓冲区全满,更新写指针到下一个起始位置
        rx_write_ptr = (rx_write_ptr + UART_RX_BUF_SIZE) % UART_RX_BUF_SIZE;
    }
}

void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) {
    if (huart->Instance == USART1) {
        // 缓冲区半满,更新写指针到半满位置
        rx_write_ptr = (rx_write_ptr + UART_RX_BUF_SIZE/2) % UART_RX_BUF_SIZE;
    }
}

4. 适配环形缓冲区的Mavlink解析逻辑

从环形缓冲区中逐个读取字节解析,完成一包就转发,避免数据堆积:

void parse_and_forward_mavlink(void) {
    mavlink_message_t msg;
    mavlink_status_t status;

    // 只要缓冲区有未处理数据,就持续解析
    while (rx_read_ptr != rx_write_ptr) {
        uint8_t curr_byte = uart_rx_buf[rx_read_ptr];
        // 更新读指针(环形取模)
        rx_read_ptr = (rx_read_ptr + 1) % UART_RX_BUF_SIZE;

        // 解析Mavlink数据包,成功解析后转发
        if (mavlink_parse_char(MAVLINK_COMM_0, curr_byte, &msg, &status)) {
            // 转发到目标设备,这里用huart2示例
            HAL_UART_Transmit(&huart2, (uint8_t*)&msg, msg.len + MAVLINK_NUM_NON_PAYLOAD_BYTES, HAL_MAX_DELAY);
        }
    }
}

5. 主循环处理解析任务

把主循环的continue替换成解析函数调用,确保数据被及时处理:

while (1) {
    parse_and_forward_mavlink();
    // 如果有其他低优先级任务,可以放在这里执行
}

额外注意事项

  • 确保UART波特率和Pixhawk配置一致,波特率不匹配也会导致丢包
  • 如果用HAL库,注意DMA中断优先级要高于其他低优先级任务,避免中断被抢占
  • 环形缓冲区的读写指针操作要保证原子性,必要时关中断(如果在多任务环境下)

内容的提问来源于stack exchange,提问作者João Ferreira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 10:22:34