> 技术文档 > 【STM32+HAL库】串口空闲中断+DMA接收不定长数据_stm32 不定长接收空闲中断回调函数

【STM32+HAL库】串口空闲中断+DMA接收不定长数据_stm32 不定长接收空闲中断回调函数

目录

前言

1.开发环境

2.Cubemx配置

2.1 开启UART4

2.2 开启DMA通道

2.3 开启NVIC中断

3.编写代码

3.1 核心函数解析

3.1.1 接收启动函数:HAL_UARTEx_ReceiveToIdle_DMA()

3.1.2 事件回调函数:HAL_UARTEx_RxEventCallback()

3.2 定义接收数组

3.3 使能接收中断

3.4 回传代码编写

4.优化改进


摘要:本文介绍了基于STM32F103的串口不定长数据接收实现方案,通过CubeMX配置UART4和DMA通道,利用HAL库的HAL_UARTEx_ReceiveToIdle_DMA()函数实现空闲中断接收。详细解析了接收启动函数和回调函数的使用方法,并针对DMA过半中断导致的数据截断问题提出了关闭该中断的优化方案。文章还包含接收数组定义、中断使能和数据回传等关键代码实现,为开发者提供了完整的串口通信解决方案。

前言

我在实现串口不定长接收数据的过程中,看见了很多方法,其中魔改了不少,良莠不齐,这里参考keysking大佬的方法。

对于串口中断原理的讲解,参考【STM32】串口不定长接收 保姆级教程。。为了便于大家阅读,这里直接摘录。

串口空闲中断是指当串口接收缓冲区中没有数据时,串口控制器产生的一种中断信号。在串口通信中,当接收到一个完整的数据帧后,通常会有一个停止位,表示数据的传输结束。当接收缓冲区中没有数据时,串口控制器会检测到停止位的连续空闲状态,并产生空闲中断信号。使用串口空闲中断可以消除轮训接收缓冲区的需要,提高系统的性能和效率。
空闲中断(Idle Interrupt) 是STM32串口的重要特性,其触发机制如下图所示:

1.开发环境

硬件:正点原子精英 V2 STM32F103开发板

单片机:STM32F103ZET6

Keil版本:5.32

串口:UART4、TTL-USB、PC11(RX)、PC10(TX)

2.Cubemx配置

2.1 开启UART4

2.2 开启DMA通道

点击add即可添加,默认配置就可以了。DMA的循环模式在一些较为复杂的项目中才会涉及到,这里暂且设置为正常模式

2.3 开启NVIC中断

之后生成代码即可。

3.编写代码

3.1 核心函数解析
3.1.1 接收启动函数:HAL_UARTEx_ReceiveToIdle_DMA()
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA( UART_HandleTypeDef *huart, // 串口句柄 uint8_t *pData, // 接收缓冲区 uint16_t Size  // 缓冲区大小);
参数 类型 作用说明 huart UART_HandleTypeDef* 串口实例指针(如&huart4) pData uint8_t* 接收数据缓冲区起始地址 Size uint16_t 最大接收数据长度(防溢出)
3.1.2 事件回调函数:HAL_UARTEx_RxEventCallback()
void HAL_UARTEx_RxEventCallback( UART_HandleTypeDef *huart, // 触发中断的串口 uint16_t Size  // 实际接收数据长度);

3.2 定义接收数组

3.3 使能接收中断

3.4 回传代码编写

这里写一个小学二年级就会的回传函数,我发什么过去,它就发送什么给我。

注意:在中断里面记得再次使能空闲中断函数,否则中断只会出现一次。

4.优化改进

由于DMA的特性,当使用DMA发送一半数据时,也会触发这个空闲中断,导致发送的数据不宜过大。如下图,我定义的数组是50个,它只能回传给我25个数据。

难道我们只能忍耐小数据的传输,亦或是更大的数组吗?其实解决方法也很简单,本质上是由于DMA的过半中断导致的,那么我直接关闭这个过半中断不就可以了吗
 

如果你遇到hdma_uart4_rx的报错,那么只需要在uart.h里面声明一下即可。