STM32 | 串口DMA很难?其实就是如此简单!(超详细、附代码)

串口DMA

DMA利用好无疑会让串口使用起来更加高效,同时CPU还能处理自己的事情,但是DMA的使用却让代码变得更加的复杂,也使串口配置变得更加麻烦!麻烦???也许只是学习的方式不对,代码是变长了,但是思路清晰的话,也就是在原来串口加了点东西而已。本文让你轻轻松松学会串口DMA!定长数据传输与不定长数据传输都教会你!通过此文,希望能让更多人了解和会使用串口DMA,希望大家多多支持,有无问题都可以参与评论,如果写得好,希望可以给个赞,谢谢! 读本文前,如果你对DMA不是很了解的可以看我的这篇博文《 STM32 | DMA配置和使用如此简单(超详细)》,里面详细介绍了DMA的一些基础知识。

测试平台:STM32F103C8T6
库版本:官方库3.5版本
关键词:串口DMA;定长数据传输;不定长数据传输;中断方式
代码下载地址: (超详细、附讲解)串口DMA.zip (点击链接跳转)
                        (https://download.csdn.net/download/weixin_44524484/12417316)

一、串口DMA的配置

本文针对串口2(USART2)如何进行DMA传输进行讲解,如果采用其他串口,注意要修改相应端口配置以及DMA通道

1、串口的DMA请求映像

通过我之前的博文《 STM32 | DMA配置和使用如此简单(超详细)》可以知道,串口2(USART2)的接收(USART2_RX)和发送(USART2_TX)分别在DMA1控制器的通道6通道7下图为DMA1控制器的请求映像图。
DMA1请求映像

2、资源说明

STM32F1中,USART2使用的是PA2(USART2_TX)和PA3(USART2_RX),为了方便阅读,使用到的资源列在下表。

外设 GPIO口 DMA请求映像通道 备注
USART2_TX PA2 DMA1通道7 RAM->USART2的数据传输
USART2_RX PA3 DMA1通道6 USART2->RAM的数据传输

3、DMA初始化配置

USART2的DMA配置在《 STM32 | DMA配置和使用如此简单(超详细)》中分别讲了库函数版和寄存器版两种配置,我这里直接搬用,不理解的可以看看《 STM32 | DMA配置和使用如此简单(超详细)》这篇文章。要注意的是库函数最大优势就是便于阅读,所以在DMA初始化配置中我们使用库函数。
首先,我们要先定义三个缓冲区(作全局定义),一个发送缓冲区,两个接收缓冲区,两个接收缓冲区是为了做双缓冲区,目的是为了防止后一次传输的数据覆盖前一次传输的数据,并且留出足够的时间让CPU处理缓冲区数据。双缓冲在串口DMA中有着很重要的意义并起着很大的作用!

//USART2_MAX_TX_LEN和USART2_MAX_RX_LEN在头文件进行了宏定义,分别指USART2最大发送长度和最大接收长度
u8 USART2_TX_BUF[USART2_MAX_TX_LEN]; 	//发送缓冲,最大USART2_MAX_TX_LEN字节
u8 u1rxbuf[USART2_MAX_RX_LEN];			//发送数据缓冲区1
u8 u2rxbuf[USART2_MAX_RX_LEN];			//发送数据缓冲区2
u8 witchbuf=0;                  		//标记当前使用的是哪个缓冲区,0:使用u1rxbuf;1:使用u2rxbuf
u8 USART2_TX_FLAG=0;					//USART2发送标志,启动发送时置1
u8 USART2_RX_FLAG=0;					//USART2接收标志,启动接收时置1

要说明的是,实际上发送缓冲区可能用不上,因为我们要发送的数据内容和大小都不一定每次都是固定的,可以是变化的,我们只需重新指派新的发送缓冲区地址即可,但是在初始化中我们还是要指定一个发送缓冲区地址。
下面是DMA1_USART2的初始化函数。

void DMA1_USART2_Init(void)
{
   
	DMA_InitTypeDef DMA1_Init;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);						//使能DMA1时钟

	//DMA_USART2_RX  USART2->RAM的数据传输
	DMA_DeInit(DMA1_Channel6);												//将DMA的通道6寄存器重设为缺省值 
	DMA1_Init.DMA_PeripheralBaseAddr = (u32)(&USART2->DR);					//启动传输前装入实际RAM地址
	DMA1_Init.DMA_MemoryBaseAddr = (u32)u1rxbuf;            				//设置接收缓冲区首地址
	DMA1_Init.DMA_DIR = DMA_DIR_PeripheralSRC;								//数据传输方向,从外设读取到内存
	DMA1_Init.DMA_BufferSize = USART2_MAX_RX_LEN;							//DMA通道的DMA缓存的大小
	DMA1_Init.DMA_PeripheralInc = DMA_PeripheralInc_Disable;				//外设地址寄存器不变
	DMA1_Init.DMA_MemoryInc = DMA_MemoryInc_Enable;							//内存地址寄存器递增
	DMA1_Init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;			//数据宽度为8位
	DMA1_Init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;					//数据宽度为8位
	DMA1_Init.DMA_Mode = DMA_Mode_Normal;									//工作在正常模式
	DMA1_Init.DMA_Priority = DMA_Priority_High; 							//DMA通道 x拥有高优先级 
	DMA1_Init.DMA_M2M = DMA_M2M_Disable;									//DMA通道x没有设置为内存到内存传输
	 
	DMA_Init(DMA1_Channel6,&DMA1_Init); 									//对DMA通道6进行初始化
	
	//DMA_USART2_TX  RAM->USART2的数据传输
	DMA_DeInit(DMA1_Channel7);												//将DMA的通道7寄存器重设为缺省值 
	DMA1_Init.DMA_PeripheralBaseAddr = (u32)(&USART2->DR);					//启动传输前装入实际RAM地址
	DMA1_Init.DMA_MemoryBaseAddr = (u32)USART2_TX_BUF;              		//设置发送缓冲区首地址
	DMA1_Init.DMA
评论 76
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值