赞
踩
我用的单片机是STM32F103CBTX
看STM32F103数据手册可以知道定时器TIM1是挂在APB1总线上
我使用的是TIM1的通道2的上升沿(即PWM输出)触发ADC采样
以下是使用逻辑分析仪观察到的PWM输出情况
注意:此时不再需要ADC进行转换,把连续转换模式设为关闭!!!
(我自己踩的坑,我试过开启的时候程序死掉了)
Circular模式:
就是ADC连续采样的意思,也就是HAL_ADC_Start_DMA(&hadc1, (uint32_t *)ADC_Value, 4)这句代码在程序中开启一次即可,不需要每次都重新打开。
Normal模式:
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)ADC_Value, 4)执行完一次之后,如果想进行下一轮ADC采样,必须要重新开启,所以每一轮采样都要用一次这句代码,采样一次开启一次采样一次开启一次。
参考别人的试了用了Circular模式,完全没问题,可以成功测出电压值。
我自己也试了Normal模式,不行,只能测一次,后面没反应了。
- uint8_t AdcConvEnd=0;
-
- int main()
- {
- uint16_t ADC_Value[4]= 0;
-
- HAL_TIM_Base_Start(&htim1);
- HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
-
- HAL_ADCEx_Calibration_Start(&hadc1);//自动校准
- HAL_ADC_Start_DMA(&hadc1, (uint32_t *)ADC_Value, 4);
-
-
- while(1)
- {
- if(AdcConvEnd)
- {
- uint16_t averageValue = 0;
- for(int i = 0; i < 4; i++)
- {
- averageValue += ADC_Value[i];
- printf("ADC_Value[%d]:%.3f\r\n",i,(float)ADC_Value[i]*3.3f/4096);
- }
- AdcConvEnd=0;
-
- averageValue/=4;
- printf("averageValue:%d\r\n",averageValue);
- }
- }
-
- void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
- {
- if(hadc==&hadc1)
- {
- AdcConvEnd=1;
- }
- }

注意:因为我们设置的是 2 个通道的采集,所以应该使能 ADC 的扫描模式,另一方面,我们采用的是 TIM 产生 pwm 触发 adc 进行采集,所以要禁止 ADC 的连续转换模式,这就是两个需要注意的地方。
*注 :* ARR和PSC都是16位的寄存器, 数值一定要在0~65535这个范围。
当我们设置了当前机器设置的是 72MHZ和 72分频,定时器输入时钟频率是72MHz / 72 = 1MHz:
若重装载值 (Period 或 ARR)设置为 500。也就是0.1us*500=500us,对于当前 PWM 周期为 500us,也就是500us发生一次中断。
当重装载值(Period 或 ARR)设置为 500 时,意味着定时器需要计数 500 个时钟周期才会触发中断。因此,中断发生的周期是 500us(即500 * 1us)
若Pulse设为250,即占空比=Pulse/ARR=250/500=50%
以向上计数为例,重载值为ARR,比较值为CRRx
上图可以看出:
当TIMx_CNT值达到ARR时,定时器溢出,重新向上计数...循环此过程至此一个PWM周期完成。
上图更加形象的说明了
信号频率由 TIMx_ARR 寄存器值决定。
占空比则由 TIMx_CCRx 寄存器值决定。
参考:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。