[应用相关] STM32H750VBTx 多通道ADC用DMA 连续模式和TIM触发 HAL

[复制链接]
1851|8
 楼主| keaibukelian 发表于 2021-7-3 11:28 | 显示全部楼层 |阅读模式
简述:运用dma搬运adc减少cpu消耗时间。
IDE: KEILv5.27
Firmware Package:STM32Cube FW_H7 V1.8.0
芯片:STM32H750VBT6
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMjQxODQ3,size_16,color_FFFFFF,t_70#pic_center.jpg

 楼主| keaibukelian 发表于 2021-7-3 11:28 | 显示全部楼层
主要配置Data Management Mode为DMA Circular Mode。对于STM32H7的DMA可以自主选择通道。
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMjQxODQ3,size_16,color_FFFFFF,t_70#pic_center.jpg

 楼主| keaibukelian 发表于 2021-7-3 11:28 | 显示全部楼层
DMA配置循环模式 内存地址增加 数据长度半字(只开起ADC1)
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMjQxODQ3,size_16,color_FFFFFF,t_70#pic_center.jpg

 楼主| keaibukelian 发表于 2021-7-3 11:29 | 显示全部楼层
中断配置可以不用改变

        //在主函数内加入如下语句打开ADC 开始DMA传送
        HAL_ADCEx_Calibration_Start(&hadc1,ADC_CALIB_OFFSET,ADC_SINGLE_ENDED);
        HAL_ADCEx_Calibration_Start(&hadc1,ADC_CALIB_OFFSET_LINEARITY,ADC_SINGLE_ENDED);
        HAL_ADC_Start_DMA(&hadc1,(uint32_t *)adcbuffer,ADC_CHANNEL_NUM*ADC_TIMES);

        __HAL_DMA_ENABLE_IT(&hdma_adc1,DMA_IT_TC);       
        __HAL_DMA_DISABLE_IT(&hdma_adc1,DMA_IT_TE);       
        __HAL_DMA_DISABLE_IT(&hdma_adc1,DMA_IT_HT);
        __HAL_DMA_DISABLE_IT(&hdma_adc1,DMA_IT_DME);



在开启adc之前一定要进行校准,否则测量出来的值会有很大偏差。在在这里我用到了传输完成中断,所以关闭了另外的中断。

处理结果可以用HAL_ADC_ConvCpltCallback()进行调用。也可以直接查询标志位。HAL_ADC_ConvCpltCallback()这个函数不仅adc中断可以用 DMA传输也可以用。这个是在HAL_ADC_Start_DMA中配置已经配置好了。

HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef *hadc, uint32_t *pData, uint32_t Length)
{
//...此处省略
hadc->DMA_Handle->XferCpltCallback = ADC_DMAConvCplt;
//...此处省略
}
//在ADC_DMAConvCplt()中调用了HAL_ADC_ConvCpltCallback()
void ADC_DMAConvCplt(DMA_HandleTypeDef *hdma)
{
//...此处省略
#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
    hadc->ConvCpltCallback(hadc);
#else
    HAL_ADC_ConvCpltCallback(hadc);
#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */;
//...此处省略
}


 楼主| keaibukelian 发表于 2021-7-3 11:29 | 显示全部楼层
运行结果:
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMjQxODQ3,size_16,color_FFFFFF,t_70#pic_center.jpg
8个通道结果都正确。
 楼主| keaibukelian 发表于 2021-7-3 11:29 | 显示全部楼层
上述方式是没有触发的使用的连续工作模式。也可以使用TIM触发。
20210509104029590.png
20210509104042822.png
 楼主| keaibukelian 发表于 2021-7-3 11:29 | 显示全部楼层
将连续工作模式去掉,外部触发源选择TIM1_CC2。
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMjQxODQ3,size_16,color_FFFFFF,t_70.jpg
 楼主| keaibukelian 发表于 2021-7-3 11:29 | 显示全部楼层
TIM1配置如上图所示。我在程序里设置了占空比,也可以在这里修改Pulse的值。

        HAL_ADCEx_Calibration_Start(&hadc1,ADC_CALIB_OFFSET,ADC_SINGLE_ENDED);
        HAL_ADCEx_Calibration_Start(&hadc1,ADC_CALIB_OFFSET_LINEARITY,ADC_SINGLE_ENDED);

        HAL_ADC_Start_DMA(&hadc1,(uint32_t *)adcbuffer,ADC_CHANNEL_NUM);
        __HAL_DMA_ENABLE_IT(&hdma_adc1,DMA_IT_TC);       
        __HAL_DMA_DISABLE_IT(&hdma_adc1,DMA_IT_TE);       
        __HAL_DMA_DISABLE_IT(&hdma_adc1,DMA_IT_HT);
        __HAL_DMA_DISABLE_IT(&hdma_adc1,DMA_IT_DME);
       
        HAL_TIM_Base_Start_IT(&htim1);
        HAL_TIM_Base_Start_IT(&htim6);
//        HAL_TIM_Base_Start(&htim2);
  TIM1->CCR1 = 4499;
        TIM1->CCR2 = 4499;       
        TIM1->CCR3 = 4499;       
       
        HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2);


 楼主| keaibukelian 发表于 2021-7-3 11:30 | 显示全部楼层
初始化如上图所示。处理adc的结果与连续工作模式一致。在HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
中处理。下面代码是我处理adc值的代码。

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
       
  if(hadc->Instance == ADC1)
        {
        vout_sum += adcbuffer[0];
  adc_time ++;
  if(adc_time >= ADC_TIMES)
        {
                vout_aver = vout_sum/ADC_TIMES;
               
        }       
               
        }
}


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

本版积分规则

105

主题

4372

帖子

5

粉丝
快速回复 在线客服 返回列表 返回顶部