目录
写在前面
一般的做法(定时器单通道输入捕获)
以外部时钟的方式(高低频都适用)
测试效果
写在前面
STM32的定时器本身有输入捕获的功能。可选择双端捕获,上升沿捕获或者是下降沿捕获。对应捕获频率来说,连续捕获上升沿或下降沿的时间间隔就是其脉冲的周期.
一般的做法(定时器单通道输入捕获)
定时器设置频率为1M.
每次进入输入捕获的中断回调函数 HAL_TIM_IC_CaptureCallback 就让其计数值CNT为0. 那么连续两次采样的计数值也就是 (TIMx->CCRx - 0) ,频率 =定时器频率/(TIMx->CCRx - 0).
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
freq=htim->Instance->CCR2;
freq = 1e6/freq;
htim->Instance->CNT =0;
}
}
}
如果是单个定时器对多个通道进行采样呢?这时候就必须重新考虑如何测量频率了。通用做法:
(以上升沿为例,定时器的计数值TIMx->CNT设置为65535后溢出)
测量第一次上升沿的捕获值CCRx,即为first,并设置标记表示开始测量,若存在溢出则在定时器的溢出回调函数 HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)中记录溢出次数,直到第二个上升沿到来,计为 second,计算频率。
频率= 定时器的频率 / (second - first +溢出次数*溢出值)
由上面的等式得出,若两个上升沿之间的计数值 > 定时器的频率 ,则脉冲的频率<1hz 属于低频。
低频是非常好测量的,难的是高频。若还想以直接的方式去测量高频,则不太现实,因为高频两个脉冲之间的间隔更短,而定时器的频率总不可能超过其系统频率,更不可能达到高频脉冲的频率。
直接不行变间接,将一段时间内的脉冲的个数进行计数统计,并记录所统计的这一段时间
频率 = 个数 /时间, 若设置时间为1s(特殊情况) 频率= 1s内的脉冲个数. 计时需要用到别的定时器。
以外部时钟的方式(高低频适用)
typedef struct mypwm{
u32 ts; //记录的脉冲值
u8 flag; //开始信号/结束信号
u16 time; //记录的时间
} mypwm;
mypwm m1 ={0};
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM6)
{
if(m1.flag == 0) m1.flag = 1; //第一次进来
else if(m1.flag == 1){
if( ++m1.time == 1000){//增加1ms
//已经测了1s
m1.time = 0;
m1.flag = 0;
freq = m1.ts;
m1.ts = 0;
}
}
}
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
if(m1.flag == 1) m1.ts++;
}
}
}
测试效果
通过定位器去控制脉冲发生器的输出频率以此测量: