STM32同步定时器并触发ADC_DMA多路采样

STM32同步定时器并触发ADC_DMA多路采样

ctime:2019-05-05 16:53:06 +0800|1557046386

标签(空格分隔): 技术 硬件


需求是这样的:

做电机驱动,需要采集电压和电流的时候,由于H桥驱动管以16K的频率再开关,如果随意进行ADC采样的话,会采到MOS关断时候的电压值和电流值,对整个电压和电流的估计造成影响。最好的情况就是在PWM为高电平,也就是MOS导通的时候,采集相应的电压和电流。

那么实现方式就是用定时器来触发ADC进行采样,而这个定时器又必须与发出PWM波的定时器计数是同步的,假设驱动电机的定时器为TIM2,那么用TIM4作为从定时器,TIM4另外发出一路PWM波来触发ADC采样。

假设此时驱动电机的占空比为50%,那么TIM4发出的PWM波占空比应该是25%(在高电平的中间采样),同时由于ADC是上升沿触发,因此需要将TIM4的PWM波极性反一下,直接设置为PWM_MODE_2即可。

思路就是这样,接下来开始配置:

ADC配置:

void MX_ADC1_Init(void)
{
  ADC_ChannelConfTypeDef sConfig;

    /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
    */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = ENABLE;           //有多路需要采集的话,这里要enable
  hadc1.Init.ContinuousConvMode = DISABLE;    //必须设置为disable,否则只有第一次是TIM4 触发,接下来都是自动触发
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;      // 上升沿采集
  hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T4_CC4;              // 设置为TIM4-CH4触发
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 2;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  if (HA
  • 2
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是基于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); } } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值