很多低端MCU没有像STM32 那样拥有强大脉冲捕获测频率,那么MCU只能依靠自身有的资源来实现这个功能,比较通用的方法是使用了外部中断+定时器来实现,该方法经过我在实际项目中的使用来看,频率50/60Hz 完全没问题,最好加个滤波算法,效果会更好。
一、实现原理
思路:
- 定时器定时间隔周期512us,外部中断上升沿触发。
- 当第一个上升沿到来时,对计数器清理操作,此时定时器中断就会重新对这个计数器不断计数。
- 当第二个上升到来时,就可很快算出两个上升沿之间的间隔时间,间隔时间=cnt*512 us,从而获得周期,间而获取频率。
二、具体实现
2.1 封装结构
typedef struct GET_FRE
{
u32 cnt; /*计数*/
u32 cnt_value; /*脉冲计数值*/
u16 timeout; /*超时*/
u16 fre; /*频率*/
u8 flag;
};
2.2 瑞萨单片机定时中断函数
CS+ 中配置定时间隔时间
配置好后,点击生成代码即可
注意:定时器周期512us
__interrupt static void r_tau0_channel0_interrupt(void)
{
get_fre.cnt++;
/*******2s 内未检测到电平跳变则清零********/
get_fre.timeout++;
if(get_fre.timeout>=3906)
{
get_fre.timeout=0;
get_fre.fre=0;
get_fre.cnt=0;
}
}
2.3 瑞萨单片机外部中断函数
配置外中断,上升沿触发,最高优先级,最后点击生成代码即可
__interrupt static void r_intc0_interrupt(void)
{
get_fre.cnt_value=get_fre.cnt;
get_fre.cnt=0;
get_fre.timeout=0;
get_fre.flag=1;
}
2.4 例子
if(get_fre.flag)
{
get_fre.flag=0;
/*
频率f=1/t
get_fre.cnt_value<<9 =计数值*512us =周期 此时单位是 us,也就是MHz
f=1000000/t,1 MHz =1000 000 Hz
*/
get_fre.fre =(10000000/(get_fre.cnt_value<<9)); //hz 为提高精度比真数据扩大10
}
2.5 图片
注意:实际程序中加了滤波算法
单片机采集结果:74.9Hz
示波器采集结果:75.08Hz
单片机采集结果:108.3Hz
示波器采集结果:108.2Hz