STM32 DMA详解:数据宽度、BufferSize、DMA模式使用和注意事项

一、在看代码之前先认识几个寄存器:

CNDTR寄存器:标准库中这样写:DMAy_Channelx->CNDTR = DMA_InitStruct->DMA_BufferSize;即配置的BufferSize为CNDTR的值

CPAR寄存器:DMAy_Channelx->CPAR = DMA_InitStruct->DMA_PeripheralBaseAddr;即配置的源地址(数据的原始地址)

CMAR寄存器:DMAy_Channelx->CMAR = DMA_InitStruct->DMA_MemoryBaseAddr;即配置的目标地址(数据的目标地址)

二、上代码:

 每次的DMA传输是由两个部分组成的:(正点原子视频里面说的是三个,但我觉得大体上还是两个)

1.两个地址(CPAR和CMAR)之间数据传输

2.传输完成后(即从外设地址取了一次16位数据到内存后),BufferSize(CNDTR)自减

当CNDTR自减到0时,数据传输完成。

三、我在学习过程中的困惑解决(ADC采样且使用DMA中断):

1.一开始无法进入DMA中断:

        原因是在初始化时失能了DMA:DMA_Cmd(DMA1_Channel1,DISABLE);

        初始化时使能DMA就好了:DMA_Cmd(DMA1_Channel1,ENABLE);

2.两个数据宽度:

 如果源端地址宽度=目标地址宽度,如源端地址宽度=目标地址宽度=16,那么源端地址每次偏移为0x2,目标地址每次偏移为0x2。数据没有丢失,即源数据是什么,目标数据就是什么。

如果源端地址宽度>目标地址宽度,如源端地址宽度=16,目标地址宽度=8,那么源端地址每次偏移为0x2,目标地址每次偏移为0x1。且数据会丢失!具体丢失内容可以看上图。

如果源端地址宽度<目标地址宽度,如源端地址宽度=8,目标地址宽度=16,那么源端地址每次偏移为0x1,目标地址每次偏移为0x2。数据没有丢失,但会出现8位数据占16位数据的情况,可以看上图,而此时,配置的左对齐和右对齐就有了作用。

3.BufferSize和DMA模式:

像文章一开始所说,BufferSize的值是写进了CNDTR寄存器。当传输了一次数据后,CNDTR寄存器的值减1,减到0时,数据传输完成。

那么如果我需要一直传输数据怎么办呢?

两个方法:①开启DMA的循环模式,在BufferSize的值减到0时,会重新变为配置值。且此时不需要不断开启和关闭DMA

                  如:(在ADC采样时开启DMA中断)

                        

 

                  ②使用DMA普通模式时,需要在DMA中断中开启和关闭DMA,且需要重新设定BufferSize的值

                   如:

                         

文章到此结束,感觉对你有用的话,点赞收藏喔

 

物联沃分享整理
物联沃-IOTWORD物联网 » STM32 DMA详解:数据宽度、BufferSize、DMA模式使用和注意事项

发表评论