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

1 篇文章 0 订阅

一、关于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传输

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
以下是基于HAL库的stm32f407定时器触发adc dma多通道采样代码: 首先,需要初始化定时器和ADC: ``` TIM_HandleTypeDef htim; ADC_HandleTypeDef hadc; void MX_TIM_Init(void) { TIM_MasterConfigTypeDef sMasterConfig = {0}; htim.Instance = TIMx; htim.Init.Prescaler = TIMx_PRESCALER; htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = TIMx_PERIOD; htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim.Init.RepetitionCounter = 0; HAL_TIM_Base_Init(&htim); sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(&htim, &sMasterConfig); } void MX_ADC_Init(void) { ADC_ChannelConfTypeDef sConfig = {0}; hadc.Instance = ADCx; hadc.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2; hadc.Init.Resolution = ADC_RESOLUTION_12B; hadc.Init.ScanConvMode = ENABLE; hadc.Init.ContinuousConvMode = DISABLE; hadc.Init.DiscontinuousConvMode = DISABLE; hadc.Init.NbrOfDiscConversion = 0; hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_Tx_TRGO; hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc.Init.NbrOfConversion = ADC_CHANNEL_NUM; hadc.Init.DMAContinuousRequests = ENABLE; hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV; HAL_ADC_Init(&hadc); for (int i = 0; i < ADC_CHANNEL_NUM; ++i) { sConfig.Channel = ADC_CHANNEL_x[i]; sConfig.Rank = i + 1; sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; HAL_ADC_ConfigChannel(&hadc, &sConfig); } } ``` 然后,需要初始化DMA和中断: ``` DMA_HandleTypeDef hdma_adc; void MX_DMA_Init(void) { hdma_adc.Instance = DMAx_STREAMx; hdma_adc.Init.Channel = DMA_CHANNELx; hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE; hdma_adc.Init.MemInc = DMA_MINC_ENABLE; hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; hdma_adc.Init.Mode = DMA_CIRCULAR; hdma_adc.Init.Priority = DMA_PRIORITY_HIGH; hdma_adc.Init.FIFOMode = DMA_FIFOMODE_DISABLE; HAL_DMA_Init(&hdma_adc); __HAL_LINKDMA(&hadc, DMA_Handle, hdma_adc); } void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { if (hadc->Instance == ADCx) { HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); } } ``` 最后,在main函数中启动定时器DMA: ``` int main(void) { HAL_Init(); MX_TIM_Init(); MX_ADC_Init(); MX_DMA_Init(); HAL_TIM_Base_Start(&htim); HAL_ADC_Start_DMA(&hadc, (uint32_t*)adc_buf, ADC_CHANNEL_NUM); while (1) { HAL_Delay(1000); } } ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值