STM32之DMA讲解及配置过程,附带代码说明

DMA涉及概念讲解: 

①:DMA即Direct Memory Access(直接存储器存取),是STM32特有的外设。大容量STM32产品集成了两个DMA,分别是DMA1和DMA2,。其中DMA1有7个通道,DMA2有5个通道,具体每个通道连接的外设可以参考STM32芯片的数据手册。

②:通过DMA可以将数据在两个不同的地址之间进行传递,如存储器到外设寄存器,外设寄存器到存储器,也可以从存储器到存储器之间。

③:当两个数据在不同的地址之间传递时,需要在程序配置中确定每次传输的字节数,确定是字节、半字还是字。

④:DMA的每个通道优先级是可变的。以DMA1为例,它有7个通道,可以配置每个通道的优先级为很高、高、中,低四种中的一种。若两个通道的优先级一样,当两个通道同时有DMA请求时,通道号小的优先级则高。

⑤:DMA每次传输的数据量是可变的,DMA中有一个专门的寄存器用于存储这个数据量值。这个寄存器是32位的,但高16位全部保留为0,实际上起作用的是低16位,所以每次传输的最大数据量是65536。

⑥:⑤中所示,比如设置数据量值为100,若DMA传输设置为循环模式,则100个数据传输完成后,将自动进行下一轮传输。若设置成非循环模式,则需要先关闭DMA,再设置数据值,再开启DMA,才能进行下一轮传输。

⑦:DMA在传输过程中,常用的有3种标志位--传输完成一半、传输全部完成,传输过程发生错误。可以在程序中设置开启对应标志位的中断,当标志位到来时,会执行中断服务程序。也可不开启相应标志位的中断。

⑧:确定好要传输的外设和存储器地址之后,需要在程序中设置传输方向,即传输方向是从外设到寄存器,还是从寄存器到外设。

⑨:DMA一般用来在外设和存储器之间进行数据传输,所以还要设置外设地址及存储器地址是否递增。例如定义一个数组,char data[100],外设地址为&UART->TX,若将数组中的100个数据传输到UART->TX中,则存储器地址需要每次递增,而外设地址不需要递增。

DMA配置过程:

①:确定传输数据的外设和寄存器地址

②:确定传输方向

③:确定每次传输的数据量值

④:确定传输数据的字节数

⑤:配置通道优先级

⑥:确定传输是循环模式还是非循环模式

⑦:如若需要开启中断,则开启响应位中断


注意:DMA也可以从存储器到存储器,但存储器到存储器过程只能为非循环模式。


程序讲解:

例:程序实现功能是将存储器中的数据传输到串口的发送寄存器TX,每次传输的数据量是100,非循环模式传输。

void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx, u32 cpar, u32 cmar, u16 cndtr)

{

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //开启时钟

DMA_DeInit(DMA_CHx); //初始化通道,设置为默认配置

DMA1_MEM_LEN=cndtr;

DMA_InitStructure.DMA_PeripheralBaseAddr = cpar;//外设地址

DMA_InitStructure.DMA_MemoryBaseAddr = cmar;//存储器地址

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//传输方向,从内存到外设

DMA_InitStructure.DMA_BufferSize = cndtr;//每次循环传输的数据量值

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不变

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址每次加1

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;//设置优先级--中

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//不是内存到内存

DMA_Init(DMA_CHx, &DMA_InitStructure);//初始化DMA配置过程

}

//开启一次传输
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)

DMA_Cmd(DMA_CHx, DISABLE );  //关闭DMA     
  DMA_SetCurrDataCounter(DMA_CHx,DMA1_MEM_LEN);//重新确定每次循环要传输的数据量值
  DMA_Cmd(DMA_CHx, ENABLE);  //再次开启DMA
}

int main()

{

u8 SendBuff[100]; //存储器数据

MYDMA_Config(DMA1_Channel4, (u32)&USART1->DR, (u32)SendBuff, 100);//调用函数

MYDMA_Enable(DMA1_Channel4);  //开启一次传输

}
























  • 16
    点赞
  • 95
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值