ADC基础知识http://t.csdnimg.cn/x6PhU
一、(单通道)使用定时器触发的ADC单通道转换
我用的单片机是STM32F103CBTX
- 定时器:使用PWM输出的模式
- ADC:使用DMA的模式(在不使用DMA的情况下,定时器控制ADC进行数据采集只能是单通道!如果开启了多通道,读取到的ADC采集值只会是最后一个通道的值!所以,要想使用定时器控制ADC采集多通道,必须使用DMA!)
定时器中cubemx配置:
看STM32F103数据手册可以知道定时器TIM1是挂在APB1总线上。即定时器 1 的频率是 72MHZ。
我使用的是TIM1的通道2的上升沿(即PWM输出)触发ADC采样
PWM模式1和模式2区别:
以下是使用逻辑分析仪观察到的PWM输出情况
ADC中cubemx配置:
注意:此时不再需要ADC进行转换,把连续转换模式设为关闭!!!
(我自己踩的坑,我试过开启的时候程序死掉了)
DMA模式选择:
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;
}
}
结果:
二、(双通道)使用定时器触发的ADC双通道转换
注意:因为我们设置的是 2 个通道的采集,所以应该使能 ADC 的扫描模式,另一方面,我们采用的是 TIM 产生 pwm 触发 adc 进行采集,所以要禁止 ADC 的连续转换模式,这就是两个需要注意的地方。
ADC中cubemx配置:
三、关于PWM的频率或周期的计算
*注 :* ARR和PSC都是16位的寄存器, 数值一定要在0~65535这个范围。
当我们设置了当前机器设置的是 72MHZ和 72分频,定时器输入时钟频率是72MHz / 72 = 1MHz:
- 1MHZ ,即1秒计数 1M 次=1000000 次(1s产生1000000个脉冲方波)。
- 1MHZ ,也就是1us产生1个脉冲方波。
若重装载值 (Period 或 ARR)设置为 500。也就是0.1us*500=500us,对于当前 PWM 周期为 500us,也就是500us发生一次中断。
当重装载值(Period 或 ARR)设置为 500 时,意味着定时器需要计数 500 个时钟周期才会触发中断。因此,中断发生的周期是 500us(即500 * 1us)
若Pulse设为250,即占空比=Pulse/ARR=250/500=50%
四、寄存器TIMx_ARR、TIMx_CCRx 、TIMx_CNT
以向上计数为例,重载值为ARR,比较值为CRRx
上图可以看出:
- 0-t1段,定时器计数器TIMx_CNT值小于CCRx值,输出低电平。
- t1-t2段,定时器计数器TIMx_CNT值大于CCRx值,输出高电平。
当TIMx_CNT值达到ARR时,定时器溢出,重新向上计数...循环此过程至此一个PWM周期完成。
上图更加形象的说明了
信号频率由 TIMx_ARR 寄存器值决定。
占空比则由 TIMx_CCRx 寄存器值决定。
参考: