当我们身边没有示波器就无法测量频率与占空比了?这篇文件小编就教大家如何使用定时器输入捕获功能测量频率与占空比。
原理解析
定时器输入捕获一般应用在两个方面,一个方面是脉冲跳变沿时间测量,另一方面是 PWM输入测量。下面将要使用就是测量脉冲跳变沿时间。
测量频率
当捕获通道TIx上出现上升沿时,发生第一次捕获,计数器CNT的值会被锁存到捕获寄存器CCR中,而且还会进入捕获中断,在中断服务程序中记录一次捕获(可以用一个标志变量来记录),并把捕获寄存器中的值读取到 value1中。当出现第二次上升沿时,发生第二次捕获,计数器CNT的值会再次被锁存到捕获寄存器CCR 中,并再次进入捕获中断在捕获中断中,把捕获寄存器的值读取到value3中,并清除捕获记录标志。利用value3和value1的差值我们就可以算出信号的周期。也就是说:
频率
=
总频
v
a
l
u
e
3
−
v
a
l
u
e
1
频率= \frac {总频}{value3-value1}
频率=value3−value1总频
占空比测量
当捕获通道TIx上出现上升沿时,发生第一次捕获,计数器CNT的值会被锁存到捕获寄存器CCR中,而且还会进入捕获中断,在中断服务程序中记录一次捕获(可以用一个标志变量来记录),并把捕获寄存器中的值读取到 valuel中。然后把捕获边沿改变为下降沿捕获,目的是捕获后面的下降沿。当下降沿到来的时候,发生第二次捕获,计数器CNT的值会再次被锁存到捕获寄存器CCR中,并再次进入捕获中断,在捕获中断中,把捕获寄存器的值读取到value3中,并清除捕获记录标志。然后把捕获边沿设置为上升沿捕获。这时:
占空比
=
v
a
l
u
e
2
−
v
a
l
u
e
1
v
a
l
u
e
3
−
v
a
l
u
e
1
∗
100
%
占空比=\frac{value2-value1}{value3-value1} *100\%
占空比=value3−value1value2−value1∗100%
在测量脉宽过程中需要来回的切换捕获边沿的极性,如果测量的脉宽时间比较长,定时器就会发生溢出,溢出的时候会产生更新中断,我们可以在中断里面对溢出进行记录处理。
代码实现
由于近期在使用蓝桥杯嵌入式比赛的STM32G431开发板,此处就以其作为例子。
CubMX的配置
此处使用的是定时器3的通道1.
定时器中断采集频率
为了计算方便,可以从0开始计时直到第一次上升沿为止。
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM3)
{
//读取定时器的计数值
crrl_t = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
//将定时器的计数值设置成0
__HAL_TIM_SetCounter(htim,0);
//计算频率
frd = (80000000/80)/crrl_t;
//重新开启定时器
HAL_TIM_IC_Start_IT(htim,TIM_CHANNEL_1);
}
}
定时器中断采集占空比
//记录定时器上升沿 下降沿计数值
struct date
{
//记录计数值 偶数为上升沿 计数的下降沿
uint32_t count[3];
//用于记录当前应该是上升沿触发还是下将沿触发
char edge_flag;
//记录数据采集数量
int number;
};
struct date date;
//本次为上升沿触发
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM3)
{
//本次为上升沿触发
if(date.edge_flag%2==0)
{
//获取本次上升沿计数值
date.count[date.number++] = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
//采集一次下降沿、两次上升沿数据完成
if(date.number == 3)
{
dutyCicle = (((date.count[1]-date.count[0])*1.0)/(date.count[2]-date.count[0]))*100;
//将定时器的计数值设置成0
__HAL_TIM_SetCounter(htim,0);
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
//重新开启定时器
HAL_TIM_IC_Start_IT(htim,TIM_CHANNEL_1);
date.edge_flag = 0;
date.number = 0;
}
else
{
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);
//将下次触发方式设置为下降沿触发
date.edge_flag += 1;
}
}
//下降沿触发
else
{
//读取本轮的计数值
date.count[date.number++] = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
//修改触发方式为上升沿触发
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
date.edge_flag += 1;
}
}
}
结果
很不幸的是,按照上述原理,使用上述代码,小编测量出的占空比更是相差10倍呐。(原本应该是60,测量出结果为6)😢😢😢后续小编还将改进代码争取更加接近真实值。
小结
总的来说,当自己身边没有示波器时,采用这个方案得到一个大概的频率以及占空比还是挺不错的,毕竟也仅仅只是多了几行代码而已。😄😄😄