STM32F103_LL库+寄存器学习笔记12.1 - 串口DMA高效收发实战:引入ringbuffer结构
导言
在STM32串口通信中,传统中断方式处理效率低、耦合度高,难以应对高频收发场景。为此,本章引入ringbuffer结构,配合USART1的DMA机制,实现接收数据的自动搬运与发送数据的非阻塞输出。ringbuffer作为中间缓冲区,有效解耦了硬件DMA与用户代码逻辑,不仅提升了数据处理效率,也增强了系统稳定性和可扩展性。
效果如下:
如上所示,从SSCOM串口助手与单片机的全局变量看来,单片机没有丢包。单片机一共发送356607bytes,接收344960bytes。
项目地址:
github:
- LL库: https://github.com/q164129345/MCU_Develop/tree/main/stm32f103_ll_library12_1_usart_dma_ringbuffer
- 寄存器方式:https://github.com/q164129345/MCU_Develop/tree/main/stm32f103_reg_library12_1_usart_dma_ringbuffer
gitee(国内):
- LL库: https://gitee.com/wallace89/MCU_Develop/tree/main/stm32f103_ll_library12_1_usart_dma_ringbuffer
- 寄存器方式: https://gitee.com/wallace89/MCU_Develop/tree/main/stm32f103_reg_library12_1_usart_dma_ringbuffer
一、代码
LL库与寄存器方式的代码类似的,这里只介绍LL库。
1.1、myUsartDrive.c
1.1.1、ringbuffer初始化
如上所示,完成发送ringbuffer与接收ringbuffer的初始化。
1.1.2、接收ringbuffer
如上所示:
- 函数
USART1_Put_Data_Into_Ringbuffer()
的作用是将从串口收到的数据放入ringbuffer。此外,它会有一些额外的处理。比如当ringbuffer的剩余空间不足以放入新的数据时,会将旧的数据丢弃,让后放入新的数据。 - 在DMA接收中断与串口空闲接收中断里分别调用函数
USART1_Put_Data_Into_Ringbuffer()
,将接收到的数据放入ringbuffer。
1.1.3、发送ringbuffer
如上所示,函数USART1_Put_TxData_To_Ringbuffer()
的目的是给其他模块调用,将需要发送的数据先放入ringbuffer,等待DMA一次性发送出去。
1.1.4、接收、发送ringbuffer的处理
1.2、main.c
二、细节补充
2.1、其他模块的代码,调用哪个函数将字符串从串口发送出去??
如上所示,外部的模块可以调用两个函数,将数据从串口发送出去:
- 函数
USART1_SendString_Blocking()
串行发送。 - 函数
USART1_Put_TxData_To_Ringbuffer()
非阻塞,异步发送。