STM32F429 HAL 定时器触发DMA 内存到内存

一、关于429的DMA

关于STM429的DMA介绍可以先看看这篇博客

其中有两个很重要的点:

1. 两路DMA对存储器和外设的支持,这一点我就走了很长的弯路,429的DMA1不支持内存到内存!虽然我这里没用到。如果使用的其它型号的片子,一定要先去看看支不支持你这样的操作。

2. DMA的请求映射,两路支持的外设并不是全部都支持。如果发现DMA在程序中无效,我认为首先要考虑这个问题

关于上面的问题,使用STMCubeMx去配置问题都不大,只要仔细的看看。

二、关于定时器触发DMA

关于定时器触发DMA 内存到内存可以查看这篇代码

其中也有个重要的点:

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传输
经验分享 程序员 微信小程序 职场和发展