×
单片机 > 单片机程序设计 > 详情

STM32F4 HAL库DMA学习

发布时间:2020-09-02 发布时间:
|

用了一段时间HAL库,不知道是不是用外设固件库时间长一点的原因,个人感觉没有固件库来的直接。看DMA部分看的有点乱,捋一下。


DMA的使用方法及细节直接看官方的手册就可以了,注意的是如果原地址和目的地址的数据长度不一样的话只能使用FIFO模式,直接模式下原地址和目的地址的数据长度必须一致。


主要是简单整理一下使用DMA的初始化过程,以串口发送使用DMA为例:


 (1)  定义一个外设的句柄,对外设的基本参数、IO、时钟、中断等进行初始化。


UART_HandleTypeDef UART1_Handler; 


               ....

 HAL_UART_Init(&UART1_Handler);

调用外设的初始化函数完成对外设的初始化


 (2)  定义一个 DMA的句柄,对DMA的数据流、通道、传输方向、数据长度等基本参数进行初始化


DMA_HandleTypeDef     UART1TxDMA_Handler; 


                      ....

HAL_DMA_Init(&UART1TxDMA_Handler);


调用初始化函数完成对句柄的填充。


 (3)  使用HAL库中对DMA的一个宏定义完成外设发送DMAT或者接收DMAR和第二步的DMA句柄进行关联


__HAL_LINKDMA(&UART1_Handler,hdmatx,UART1TxDMA_Handler);           

  每个外设的句柄结构体中都一个该外设关于DMA相关的设置:


 DMA_HandleTypeDef      *hdmatx;          UART TX 的DMA句柄参数

 DMA_HandleTypeDef      *hdmarx;          UART RX 的DMA句柄参数


 使用__HAL_LINKDMA 宏定义的作用就是将第二步初始化的DMA句柄赋值给外设的发送或者接收DMA句柄,并且外设的句柄(第一步定义的)赋给DMA结构体中的.parent 参数,调用DMA的函数都会间接调用 

             

 UART1TxDMA_Handler.parent->hdmatx  

            

 对DMA的个别寄存器的参数进行填充,比如调用 HAL_DMA_Start()函数就会调用DMA_SetConfig()函数配置数据个数、源地址、目的地址等。而hdmatx 和第二步的DMA句柄是一模一样的,感觉最后转了一圈又转回会来了。。。

  (4)  外设初始化、DMA初始化、外设和DMA进行关联、外设使能DMA发送或者接收、DMA调用函数开始发送或者接收。


 个人感觉有时候HAL库的确有些冗余了,这时候可能就需要部分进行寄存器操作了。


二、使用过程总结


1、传输数据数目设置


 注意传输数据的个数的设置:如果源的数据宽度和目标数据宽度不一样,即PSIZE、MSIZE不相等时,DMA_SXNDTR寄存器配置要传输的数据项数目的宽度等于外设总线的宽度(和传输方向无关)。例如外设的宽度设置为字,存储器的宽度设置为半字,假如要传输100个字节的数据,NDTR寄存器配置要传输的数据数目 100/4.外设宽度是字=4个字节。


2、DMA初始化


 HAL_DMA_Init() ;   初始化函数中会使能所有的中断,如果不想用中断,可以在初始化之后关闭。初始化完成后会自动使能流的DMA。 




三、调试过程问题解决


直接模式中出现FIFO溢出错误,可能是DMA的源地址或者目的地址设置有问题。


关键字:STM32F4  HAL库  DMA 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32单片机的复用端口初始化的步骤及方法