频率检测, 方案方法很多种, 其中最快最节省资源的方法. 分享给大家. 其它的方案都试过, 问题多多.
适合单片机在工业应用中, 1MHZ以下的频率检测. 1MHZ估计也行. 但是偏差估计是变大了.
我试过很多种方案, 可以看我前面的文章. 最后发现目前这种方案最为优秀. 主要特点为不占用过多的CPU资源, 纯硬件计算. 不需要中断函数. 简单配置即可. 而且可以测量频率和占空比都可以测量到.
废话不多说, 上过程. 主要也是为了方便以后再次遇到这种应用. 脑子总是会忘记的
使用定时器的混合通道模式, 这个模式下是通道1 CCR1中捕获的是上升沿来临时的定时器计数器CNT数值, 通道2的CCR2捕获的是下降沿来临时的定时器计数器CNT数值... Slave Model Controller 为Reset Mode时, 一个周期结束, CNT值会清零. 重新开始计数.
公式啥的就很简单了. 我这里不写了. 直接看后面的代码吧...

这个方案其实是占用了2个通道的输入捕获. 这里面Slave Model Controller 一定要为Reset Mode
Reset Mode的意思是,当一个周期结束后, 计数器清零. 重新开始计数.
如上配置完成后, 生成代码, 然后在main.c函数中添加如下代码:
c
/**
* 函 数:获取输入捕获的频率
* 参 数:无
* 返 回 值:捕获得到的频率
*/
uint32_t Haller_GetFreq(void)
{
//`频率 = 1 / (时间差 * 时钟源频率 / 预分频因子)`
return 1000000 / TIM5->CCR1 ; //测周法得到频率fx = fc / N , 1000000 是时钟的频率1Mhz
}
/**
* 函 数:获取输入捕获的占空比
* 参 数:无
* 返 回 值:捕获得到的占空比
*/
uint32_t Haller_GetDuty(void)
{
return (TIM5->CCR2 ) * 100 / (TIM5->CCR1 ) ; //占空比Duty = CCR2 / CCR1 * 100
}
c
volatile uint32_t freq =0;
volatile uint32_t duty =0;
int main(void)
{
HAL_Init();
//启动定时器5和输入捕获(不使用中断)
HAL_TIM_Base_Start(&htim5);
HAL_TIM_IC_Start(&htim5, TIM_CHANNEL_1); // 启动通道1输入捕获(上升沿)
HAL_TIM_IC_Start(&htim5, TIM_CHANNEL_2); // 启动通道2输入捕获(下降沿)
while (1)
{
freq = Haller_GetFreq(); //获取占频率 这个函数可以在需要的时候调用, 一般不需要循环中去计算.
duty = Haller_GetDuty(); //获取占空比.
//....其它代码.
}
}
最后贴一下硬件电路,方便参考, 这个电路实际上就是一个简单的比较器. 运放当作比较器用. 把正弦波转成方波, 这个电路要求传感器与运放之间的布线长度要尽可能的短. 不要太长.

注意VCC的电压不要超过mcu的允许电压哦. . 输出的电压大小等于VCC的电压值.
这种方案下, 测量3000hz, 的偏差在3hz左右. 估计提高定时器的时钟频率可以提高一点精度. 具体没测试, 欢迎测试过的给个反馈.