处理STM32 DMA方式下的HAL_UART_ERROR_ORE错误

在STM32微控制器中,使用DMA(直接存储器访问)方式进行UART通信时,可能会遇到 HAL_UART_ERROR_ORE(Overrun Error)错误。这种错误通常发生在接收缓冲区满时,新数据到来导致数据溢出。处理这种错误需要系统化的策略,包括正确配置DMA、适当的错误处理和数据管理。以下是详细的解决方法和步骤。

一、理解Overrun Error (ORE)

Overrun Error (ORE) :当USART接收器在缓冲区已满的情况下接收到新数据时,会产生溢出错误。此错误表示上一次接收的数据未及时处理,新数据已经到达,但无法存储。

二、配置DMA和UART

正确配置DMA和UART对于避免溢出错误至关重要。

1. 配置UART

在CubeMX中配置UART,确保启用DMA接收模式。

2. 配置DMA

配置DMA通道,确保DMA的优先级和缓冲区大小足够应对预期的数据速率。

三、编写代码处理ORE错误

1. 初始化UART和DMA

确保正确初始化UART和DMA。

复制代码
// UART句柄定义
UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_rx;

// UART和DMA初始化函数
void MX_USART1_UART_Init(void) {
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 115200;
    huart1.Init.WordLength = UART_WORDLENGTH_8B;
    huart1.Init.StopBits = UART_STOPBITS_1;
    huart1.Init.Parity = UART_PARITY_NONE;
    huart1.Init.Mode = UART_MODE_TX_RX;
    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    if (HAL_UART_Init(&huart1) != HAL_OK) {
        Error_Handler();
    }
}

void MX_DMA_Init(void) {
    // DMA控制器时钟启用
    __HAL_RCC_DMA1_CLK_ENABLE();

    // USART1 DMA RX初始化
    hdma_usart1_rx.Instance = DMA1_Channel5;
    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_HIGH;
    if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK) {
        Error_Handler();
    }

    __HAL_LINKDMA(&huart1, hdmarx, hdma_usart1_rx);
}
​

2. 启动DMA接收

在主程序中启动DMA接收:

复制代码
uint8_t RxBuffer[64]; // 接收缓冲区

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_USART1_UART_Init();

    if (HAL_UART_Receive_DMA(&huart1, RxBuffer, sizeof(RxBuffer)) != HAL_OK) {
        Error_Handler();
    }

    while (1) {
        // 主循环
    }
}
​

3. 错误处理回调函数

实现UART错误回调函数,处理 HAL_UART_ERROR_ORE错误。

复制代码
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
    if (huart->ErrorCode & HAL_UART_ERROR_ORE) {
        __HAL_UART_CLEAR_OREFLAG(huart); // 清除ORE错误标志

        // 重新启动DMA接收
        HAL_UART_Receive_DMA(huart, RxBuffer, sizeof(RxBuffer));
    }
}
​

四、优化数据处理和缓冲区管理

1. 提高数据处理速度

确保在接收数据后尽快处理,以避免缓冲区溢出。

2. 增加缓冲区大小

根据实际应用需求,增加DMA缓冲区大小。

3. 使用循环缓冲区

实现循环缓冲区,提高数据处理效率。

复制代码
#define BUFFER_SIZE 256
uint8_t CircularBuffer[BUFFER_SIZE];
volatile uint16_t WriteIndex = 0;
volatile uint16_t ReadIndex = 0;

void ProcessData(void) {
    while (ReadIndex != WriteIndex) {
        uint8_t data = CircularBuffer[ReadIndex++];
        ReadIndex %= BUFFER_SIZE;

        // 处理数据
    }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    // 将接收到的数据存入循环缓冲区
    CircularBuffer[WriteIndex++] = RxBuffer[0];
    WriteIndex %= BUFFER_SIZE;

    // 继续接收数据
    HAL_UART_Receive_DMA(huart, RxBuffer, 1);
}
相关推荐
No0d1es4 小时前
202506 电子学会青少年等级考试机器人五级器人理论真题
单片机·嵌入式硬件·青少年编程·机器人·电子学会·五级·理论综合
范纹杉想快点毕业7 小时前
C 语言主控开发与显控开发能力体系及技术栈详解,STM32、QT、嵌入式、边缘系统显示
stm32·单片机·tcp/ip·microsoft·fpga开发·51单片机·wpf
不会先思考7 小时前
C5.3:发射极偏置和LED驱动电路
嵌入式硬件·模拟电路·三极管·发射极偏置电路·bjt
LJWWD8 小时前
AI小智单片机esps32-s3烧录教程
单片机·嵌入式硬件
szxinmai主板定制专家12 小时前
基于FPGA的热电偶测温数据采集系统,替代NI的产品(二)总体设计方案
arm开发·人工智能·嵌入式硬件·fpga开发
herderl14 小时前
【无标题】命名管道(Named Pipe)是一种在操作系统中用于**进程间通信(IPC)** 的机制
java·linux·服务器·嵌入式硬件·php
智者知已应修善业16 小时前
【51单片机数码管循环显示3位数字】2022-10-26
c语言·经验分享·笔记·嵌入式硬件·算法·51单片机
何以问天涯17 小时前
K210人脸识别系统
人工智能·python·嵌入式硬件·ai编程
嵌入式小李17 小时前
stm32项目(25)——基于stm32的植物生长箱环境监测系统
stm32·单片机·嵌入式硬件
青草地溪水旁18 小时前
socket编程中系统调用send()详细讲解
嵌入式硬件·socket·内核空间·用户空间