硬汉嵌入式论坛

 找回密码
 立即注册
查看: 5166|回复: 5
收起左侧

[HAL学习笔记] HAL库源文件stm32h7xx_hal_dma.c学习笔记(2018-07-31 V1.0)

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106771
QQ
发表于 2018-7-31 11:55:59 | 显示全部楼层 |阅读模式
说明:
1、H7系列的DMA与F1,F4系列的不同,H7系列DMA前面多了一级DMAMUX,可以方便选择各种通道,没有之前F1,F1系列限制只能使用给定的通道。
     详情看此贴:F1系列,F4系列和H7系列的DMA框图对比,一目了然
     http://www.armbbs.cn/forum.php?mod=viewthread&tid=86257

2、此文件主要用于配置DMA1,DMA2和BDMA。而MDMA是另外的一个源文件。



==============================================================================
                                                                  ##### 如何使用此驱动  #####
==============================================================================  


1、使能和配置外设连接DMA Stream需要看参考手册进行学习(除了内部Flash和SRAM:无需初始化,这个有待考证)

2、对于一个给定的Stream,用户使用函数HAL_DMA_Init配置各项参数。

3、DMA查询方式
(1)配置了源地址,目的地址和数据长度后,调用函数HAL_DMA_Start()启动传输
(2)使用函数HAL_DMA_PollForTransfer()查询当前传输结束,用户还可以给此函数配置超时等待时间

4、中断方式
(1)使用函数HAL_NVIC_SetPriority配置NVIC优先级
(2)使用函数HAL_NVIC_EnableIRQ使能NVIC中断
(3)配置了源地址,目的地址和数据长度后,调用函数HAL_DMA_Start_IT()可以启动传输(注,此函数会使能DMA中断)
(4)将函数HAL_DMA_IRQHandler()填到中断服务程序HAL_DMA_IRQHandler()里面
(5)传输结束后会调用函数HAL_DMA_IRQHandler(),此函数里面会执行回调函数,即用户需要为XferCpltCallback和XferErrorCallback指向的函数。


5、使用函数 HAL_DMA_GetState()可以获得DMA状态,函数HAL_DMA_GetError()获取哪方面错误

6、使用函数HAL_DMA_Abort()可以终止DMA传输
(1)存储器到存储器方式,不支持循环模式
(2)DMA FIFO的作用是降低对总线的需求和原地址,目的地址不同数据宽度的传输。
(3)当FIFO禁止后,不允许配置源数据和目的数据宽度不同,此时将统一使用外设数据宽度。

7、下面是几个常用的DMA宏定义
(+) __HAL_DMA_ENABLE:  使能指定的DMA Stream
(+) __HAL_DMA_DISABLE: 禁止指定的DMA Stream
(+) __HAL_DMA_GET_FS:  返回当前DMA Stream FIFO填充情况
(+) __HAL_DMA_ENABLE_IT: 使能指定的DMA Stream中断
(+) __HAL_DMA_DISABLE_IT: 禁止指定的DMA Stream中断
(+) __HAL_DMA_GET_IT_SOURCE: 检查指定的指定的DMA Stream中断是否发送



1、初始化函数HAL_DMA_Init
2018-08-01_144224.jpg

2、复位函数HAL_DMA_DeInit
2018-08-01_144709.jpg

3、函数HAL_DMA_Start
启动DMA传输,此函数没有开启中断,代码比较好理解:
  1. HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
  2. {
  3.   HAL_StatusTypeDef status = HAL_OK;

  4.   /* Check the parameters */
  5.   assert_param(IS_DMA_BUFFER_SIZE(DataLength));

  6.   /* Check the DMA peripheral handle */
  7.   if(hdma == NULL)
  8.   {
  9.     return HAL_ERROR;
  10.   }

  11.   /* Process locked */
  12.   __HAL_LOCK(hdma);

  13.   if(HAL_DMA_STATE_READY == hdma->State)
  14.   {
  15.     /* Change DMA peripheral state */
  16.     hdma->State = HAL_DMA_STATE_BUSY;

  17.     /* Initialize the error code */
  18.     hdma->ErrorCode = HAL_DMA_ERROR_NONE;

  19.     /* Disable the peripheral */
  20.     __HAL_DMA_DISABLE(hdma);

  21.     /* Configure the source, destination address and the data length */
  22.     DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);

  23.     /* Enable the Peripheral */
  24.     __HAL_DMA_ENABLE(hdma);
  25.   }
  26.   else
  27.   {
  28.     /* Process unlocked */
  29.     __HAL_UNLOCK(hdma);

  30.     /* Set the error code to busy */
  31.     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;

  32.     /* Return error status */
  33.     status = HAL_ERROR;
  34.   }
  35.   return status;
  36. }
复制代码


4、函数HAL_DMA_Start_IT
启动DMA传输,开启DMA中断
11.jpg

5、函数HAL_DMA_Abort
(1)用于终止使用函数HAL_DMA_Start开启的DMA传输
(2)禁止了DMA Stream,一定要等待,直到DMA Stream被有效禁止,程序里面对此已经做了处理。另外注意,如果当前传输正在进行中,会等到传输结束才会终止。


6、函数HAL_DMA_Abort_IT
(1)用于终止使用函数HAL_DMA_Start_IT开启的DMA传输

7、函数HAL_DMA_PollForTransfer
(1)此函数已经不推荐使用,仅仅作为兼容性函数存在,用于调试目的。推荐大家使用中断方式的。
(2)此函数不可用于DMA的循环传输模式和双缓冲模式

8、函数
HAL_DMA_IRQHandler  用于DMA中断服务程序里面调用
HAL_DMA_RegisterCallback  用于注册中断里面的回调函数
HAL_DMA_UnRegisterCallback 用于取消注册的回调函数


9、函数HAL_DMA_GetState
用于获取DMA状态

10、函数HAL_DMA_GetError
用于获取DMA的错误信息

11、函数DMA_SetConfig
此函数主要在DMA源码文件内部调用,供其它函数使用,用于设置原地址,目的地址和传输的数据长度

12、函数DMA_CalcBaseAndBitshift
根据stream number计算DMA Stream基地址。

13、函数DMA_CheckFifoParam
此函数用于检测配置的存储器突发大小和FIFO阀值是否兼容。

14、函数DMA_CalcDMAMUXChannelBaseAndMask
此函数用于计算使用的DMA通道和屏蔽状态

15、函数DMA_CalcDMAMUXRequestGenBaseAndMask
此函数用于配置DMA1,DMA2和BDMA使用的DMAMUX。







回复

使用道具 举报

4

主题

42

回帖

54

积分

初级会员

积分
54
发表于 2018-8-1 12:26:17 | 显示全部楼层
看到这个,又忍不住想多说一句,STM32的DMA寄存器规划真是很混乱,DMA1和DMA2的划分,更是匪夷所思。

依我看,DMA直接按streamX来为寄存器分组才是易于理解的逻辑。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106771
QQ
 楼主| 发表于 2018-8-1 14:34:54 | 显示全部楼层
jinggx 发表于 2018-8-1 12:26
看到这个,又忍不住想多说一句,STM32的DMA寄存器规划真是很混乱,DMA1和DMA2的划分,更是匪夷所思。

依 ...

你说是F1,F4系列吧,H7系列不是这样了,H7已经是新型的DMA控制器了,是有个DMAMUX,可以随意选择了。不用担心那个流通道能用,那个流通道不能用了。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106771
QQ
 楼主| 发表于 2018-8-1 17:24:40 | 显示全部楼层
已经更新完毕。
回复

使用道具 举报

2

主题

569

回帖

575

积分

金牌会员

积分
575
发表于 2018-8-2 06:13:30 | 显示全部楼层
这种要用户自己选没什么好处,还不如直接做成死的,一对一,没得选。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106771
QQ
 楼主| 发表于 2018-8-2 08:13:23 | 显示全部楼层
leiyitan 发表于 2018-8-2 06:13
这种要用户自己选没什么好处,还不如直接做成死的,一对一,没得选。

触发源少的的时候还行,H7的外设太多了,必须前面增加多路选择器来选择,像F4那种还需要我们看手册列表是否有冲突。改成这种方式真的是超方便,依次往下排就行。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-5 22:09 , Processed in 0.253398 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表