一、关于429的DMA
关于STM429的DMA介绍可以先看看这篇博客https://blog.csdn.net/qq_38351824/article/details/101865426
其中有两个很重要的点:
1. 两路DMA对存储器和外设的支持,这一点我就走了很长的弯路,429的DMA1不支持内存到内存!虽然我这里没用到。如果使用的其它型号的片子,一定要先去看看支不支持你这样的操作。
2. DMA的请求映射,两路支持的外设并不是全部都支持。如果发现DMA在程序中无效,我认为首先要考虑这个问题
关于上面的问题,使用STMCubeMx去配置问题都不大,只要仔细的看看。
二、关于定时器触发DMA
关于定时器触发DMA 内存到内存可以查看这篇代码
http://www.efton.sk/STM32/bt.c
其中也有个重要的点:
1. 虽然我们的目的是让DMA从内存到内存,但由于是定时器是触发源,所以DMA的方向因该是外设到内存或者内存到外设,这样才能让定时器产生更新事件的时候触发DMA去搬运数据,但源地址和目的地址就是自己来定义了
2. 定时器配置好后,一定要使能定时器的DMA更新事件,主要就是配置定时器寄存器DIER 为 TIM_DIER_UDE,这点在cubeMx生成的代码中没有,需要自己添加。
三、cubeMx的配置和主要的代码
- 添加 TIM1的DMA
- 对DMA的方向进行更改
if (htim->Instance==TIM1) {
__HAL_RCC_TIM1_CLK_ENABLE();
/* TIM1 DMA Init */
/* TIM1_UP Init */
hdma_tim1_up.Instance = DMA2_Stream5;
hdma_tim1_up.Init.Channel = DMA_CHANNEL_6;
hdma_tim1_up.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_tim1_up.Init.PeriphInc = DMA_PINC_ENABLE;
hdma_tim1_up.Init.MemInc = DMA_MINC_DISABLE;
hdma_tim1_up.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_tim1_up.Init.MemDataAlignment = DMA_PDATAALIGN_WORD;
hdma_tim1_up.Init.Mode = DMA_NORMAL;
hdma_tim1_up.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_tim1_up.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
// hdma_tim2_up_ch3.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_tim1_up);
/* Several peripheral DMA handle pointers point to the same DMA handle.
Be aware that there is only one stream to perform all the requested DMAs. */
__HAL_LINKDMA(htim,hdma[TIM_DMA_ID_UPDATE],hdma_tim1_up);
__HAL_LINKDMA(htim,hdma[TIM_DMA_ID_CC3],hdma_tim1_up);
}
- 在DMA初始化函数的最后添加:
__HAL_TIM_ENABLE_DMA(&TIM1_Handler, TIM_DMA_UPDATE);
- 测试
HAL_TIM_Base_Start(&TIM1_Handler);
HAL_DMA_Start_IT(TIM1_Handler.hdma[TIM_DMA_ID_UPDATE], (uint32_t)buf1, (uint32_t)buf2,20);//开启DMA传输