DMA—直接存储区访问

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

这里主要记录一下stm32f407zg的dma-uart的接收

一、dma相关

1.简介
DMA:一种搬运数据的东西(在搬运过程中不占用cpu,但是会抢占总线,可能会导致cpu错过中断),一般用在adc的采集中,在我的开发板(stm32f407zg)中,两个dma,每个dma8个数据流,每个数据流有8个通道(即:对应8个外设请求),注意:每一个数据流虽然有8个通道,但是同一时刻只能相应一个通道。
2.模式
外设到存储器传输、存储器到外设传输和存储器到存储器传输三种传输模式
外设:外设的数据寄存器。
存储器:一般是指片内SRAM、外部存储器、片内Flash等等。
3.优先级
两种设置模式
1.软件设置(非常高、高、中和低)
2.硬件控制(数据流编号越小优先级别越高)
4.FIFO
每个数据流都独立拥有四级32位的FIFO,也就是16个字节,可以设置阈值(1/4、1/2、3/4和满),到达阈值才传—FIFO模式,有数就传—直接模式(默认直接模式)
5.配置参数说明
DMA2支持全部三种传输模式(dma1不支持内存到内存,因为没有挂载在ahb总线上),
位宽:可以设置外设和存储器数据宽度大小:字节(8位)、半字(16位)和字(32位),当时用直接模式的时候,只需要指定外设数据宽度既可。
源地址和目标地址:32位,两种寄存器(DMA_SxM0AR(x为0~7) ,DMA_SxM1AR(x为0~7) ,其中DMA_SxM1AR只用来双缓冲模式所以会看到在直接模式中的memory0)
流控制:即传输数据的个数,这里的个数单位是前面设置的位宽
循环模式/单次模式:字面意思。
传输类型:单次与突发(突发一般与FIFO一起使用,达到阈值即传输)

二、代码

//nvic配置中断源优先级,没什么好说的
static void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	
	NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream2_IRQn;		
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0 ;	
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;					
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;		
	
	NVIC_Init(&NVIC_InitStructure);	
}
//DMA配置
void USART_DMA_Config(void)
{
	DMA_InitTypeDef DMA_InitStructure;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);
	//复位初始化dma数据流
	DMA_DeInit(DMA2_Stream2);
	//确保复位完成
	while(DMA_GetCmdStatus(DMA2_Stream2) != DISABLE) 
	{
    }
	DMA_InitStructure.DMA_Channel = DMA_Channel_4;//通道4
	DMA_InitStructure.DMA_PeripheralBaseAddr=(u32)(USART1_BASE+0x04);//外设地址
	DMA_InitStructure.DMA_Memory0BaseAddr = (u32)u1rxbuf;//存储器地址
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//方向
	DMA_InitStructure.DMA_BufferSize = USART2_MAX_RX_LEN;//要传输数据大小
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//不自增
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//自增
	DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;//数据宽度
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//正常模式
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//优先级中
	//不用FIFO
	DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
	DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
	//注意:这两句要有的,我之前一直以为我使用直接模式,就不需要这两句了,后来一直调不通
	DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//单次模式
	DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
	
	DMA_Init(DMA2_Stream2, &DMA_InitStructure);
	
	NVIC_Configuration();
	DMA_ITConfig(DMA2_Stream2,DMA_IT_TC,ENABLE);//开启传输完成中断
	DMA_Cmd(DMA2_Stream2, ENABLE);
	USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
	while (DMA_GetCmdStatus(DMA2_Stream2) != ENABLE) 
	{
		
  }
	
}
//中断
void DMA2_Stream2_IRQHandler(void)
{	
	if(DMA_GetITStatus(DMA2_Stream2,DMA_IT_TCIF2)!=RESET)
	{
		DMA_ClearITPendingBit(DMA2_Stream2,DMA_IT_TCIF2);
		DMA_Cmd(DMA2_Stream2,DISABLE);
		//乒乓操作
		if(witchbuf)
		{
			memcpy(p,u2rxbuf,USART2_MAX_RX_LEN);
			DMA2_Stream2->M0AR = (u32)u1rxbuf;
			witchbuf=0;
		}
		else
		{
			memcpy(p,u1rxbuf,USART2_MAX_RX_LEN);
			DMA2_Stream2->M0AR = (u32)u2rxbuf;
			witchbuf=1;
		}
		
		DMA2_Stream2->NDTR = USART2_MAX_RX_LEN;
		/*因为是DMA正常模式,并非循环,所以传输完一次就停止了
			,要想开启需要这样做
			1:DMA_ClearITPendingBit(DMA2_Stream2,DMA_IT_TCIF2);
			2:DMA_Cmd(DMA2_Stream2,ENABLE);
		*/
		
		DMA_Cmd(DMA2_Stream2,ENABLE);
	}
}

总结

下把争取做到少些文字,更生动形象,不然文字太多自己都不想看;

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值