单片机学习小组
直播中

卢表镜

7年用户 1040经验值
私信 关注

介绍几种频率计的测频方法

输入捕获测频率的原理是什么?有何优缺点呢?
外部时钟输入测频率的原理是什么?有何优缺点呢?


回帖(1)

赵天湖

2022-1-17 13:52:22
多种测频方式比较


  频率计在高频方面运用十分广泛,需要掌握各种测频的方法来满足对多种场景的需求。本文是基于正点原子的stmf103rct6 Mini单片机的测频,并且因本人能力有限,数据测试比较粗糙。但是测频的方法还是可以来讨论一二。此次会分析四种测频的方法,每种方法各有优劣,适合的场景也各不相同。最后在说一下,本人能力有限,望能指出错误或改进之处。

1.输入捕获测频率

简介:

玩过32单片机的盆友应该都清楚输入捕获是stm32单片机自带的一个功能。其会在输入信号的上升沿或者下降沿(由程序员自行设定)到来之时,触发特定信号给定时器。基于此特性,我们可以结合定时器的定时或计数功能来做到采频。
原理:

基于输入捕获的特性,测方波是最合适的(正弦波与三角波应该能行,但我没试)。假设我们设定下降沿进行捕获(给定时器一个特定信号)。这时我们将在中断中清0定时器的值并进行一个标记。当第二次信号来临时,我们读取定时器的值并进行另外的标记。这时候我们有了定时器的计时数,并且这是在一个周期内的计时数。我们知道一个数是代表的时间为多少就能算出方波的周期为多少,进而算出频率是多少。例如,我们读到的数的1000,定时器走一个数的时间为1us,则周期为1ms,频率为1khz。

  注:当周期过大时要注意定时器溢出多次,实际读到的值与方波的周期不相符,可以设另外一个变量来记录定时器的溢出次数。此方法还有一个固定误差,我猜测是由于进中断的代码造成的,当频率过高,此误差将会极大的影响结果的正确性。
数据分析:



  注:只能采方波是我之前的认知,现在不确定能不能采其他的波
改进:

上面的方法是根据正点原子的思路来的,且功能有所删减。但是,在一次和学长的探讨下,受其启发,发现了将固定误差消除的方法。当我们第一次进入的时候不清0定时器的值,而是直接读取输入捕获寄存器的值,在第二次进入时,用此时的值来减第一次值得到的将会是正确的周期数。因为第一次有固定误差,第二次也有固定误差,两次相减就将固定误差消除了(一个好的程序员不应该是码农,不应该只沉迷于码代码中)。还有个问题,出现负数怎么办?很简单,如果出现负数,肯定是因为定时器溢出了,然后我们有溢出标志,将溢出的时间加进去后,数就会是正的。
数据分析:


2.外部时钟输入

简介:

玩过单片机的盆友都知道,单片机的定时器都是有个信号源的,就是那个几兆的晶振。晶振就是给定时器做为定时的基准。当晶振发出一个周期的正弦波,定时器就会计一个时。晶振的信号周期就是定时器的计数周期。但是32给了我们使用外部信号源而不用晶振的方法。我们就利用一个周期定时器计一个数的特性来进行采频。
原理:

我们将要采集的信号(继续以方波为例),作为定时器的信号源输入,这在程序上得做特殊配置,我也是在网上找到的他人的代码,在此特别感谢。除此之外,我们还要另外使用一个定时器来计时。因为我们得在一个时间内进行采频才能算出频率。要不然那就只是单纯的计数。而我就是用的1s来计时,因为采频周期正好是1s,所以所得的数正好就是频率。

  注:此发方法测频简单暴力,但是如果定时出错则会直接影响到频率的计算。
数据分析:


3.ADC捕获各种波形的频率

简介:

首先申明,这只是我异想天开的想法,实际效果很差。stm32也是自带采ad功能的,也就是采集电压的功能。32的采ad速度很快,f103的最快速度能做的到采集一次1us。我们可以了利用采ad和定时器来采集波形一个周期的时间。
原理:

我们的信号实质上也是周期变化的电压。首先我们让ADC进入连续工作模式且开启中断,速度不用最快,我的就是5.625us。因为采ad的速即可,可以认为采集到的是某点的电压。在电压连续变化的时候(规定电压范围在0-3.3v),假设我们采集到2v电压的时候,获取现在定时器的计算值并记录标志量,表明在上升。当采集到1v的电压时再记录标志量,表明在下降。当采集再到2v的时候表明已经过完一个周期,这时就读取当前定时器的值,溢出量该加就加。(这里有很大的bug,下面再分析)
数据分析:



  注:此方法我只在测心电频率的时候用过,在0.2-2hz的频率下,感觉还是很稳的。但是就像上面说的BUG。我第一次采到的2v是一定是上升沿的2v吗?采到下降沿的2v不就出错了嘛!而且不是每个电压的信号都只是0-3.3v。这范围的限制影响很大。最重要的是,后面还有更好的方法,所以我果断放弃这个想法。
4.FFT!!!

简介:

这个方法是我目前接触到的最需要数学的编程。正如我之前所说,好的程序员不能是码农!学过高数的童鞋应该了解过傅里叶变换。其理论证明任何周期信号都能分解成无限多个有公共周期的正弦波信号(幅值不一定相等)。我们可以利用这个定理来将我们采集到的信号进行分解,然后进行数据处理得到我们想要的信息。但是还有个问题,在单片机上计算傅里叶变换速度很慢且程序很复杂。于是人们发明了快速傅里叶变换(FFT)。舍去一些东西来得到速度的提升与程序的简化。
原理:

还是得用到ADC采集。但是这次必须得固定采集频率,不能让他自己一直在那采。我使用定时器触发ADC采集,采样频率为10000hz。并且将值储存在一个256大小的数组里。然后使用stm32官方自带的FFT库,调用一个函数,将256个数据传进去,然后将出来的数据再进行一些简单的分析得到频率与幅值的信息。有关FFT的具体原理与数据意义这里不细讲。
数据分析:


上面的数据分为三列,只列举了一部分。我输入的信号为1Khz,3.3vpp,1.6v偏置的正弦波信号。由上面的的数据可以看出,0hz(直流也就是偏置),1014hz的后面的数字明显大于其他的频率。其实这里不是最好的数据,我测的最好的数据其余频率的数字应该在个位数。这个数字也与峰峰值有关系。
总结:

接下来我们分析一下这四种方法的优劣


  • 输入捕获测频率
    优点:32自带功能,程序简单,使用方便,网上信息丰富。在原来的代码上稍加修改就能获得占空比,可以参考正点原子的输入捕获教程(B站),我也放了一个双通道采两路pwm波的程序。
    缺点:对峰峰值的要求必须要满足能让IO口检测到。而且误差和32的主频有关。中断里的代码越多误差可能越大。有一次尝试中,我换了两个if的位置,都让误差变小了。还不确定能不能测正弦波与三角波
  • 外部时钟输入
    优点:简单粗暴,轻轻松松上兆,而且误差极小。正弦波,三角波,方波都行
    缺点:峰峰值也有要求。只能采频,得不到其他信息。另外用来计时的定时器的设定也极大的影响了频率的误差。
  • ADC捕获各种波形的频率
    优点:能采任意波形,程序简单,思路简单。(我编不出来了,不过我程序还是有锅)
    缺点:能用的场合极少。误差与不确定性极大。不推荐使用
  • FFT
    优点:能采任意波形,得到所有的谐波的频率与幅度信息。因为有官方库,所以FFT很难的缺点也没了。
    缺点:不能得到占空比信息。官方库使用范围的限制很大。要想自己写,FFT很难的缺点又来了(所以我现在还是码农)。FFT得到的数据与自己的采样频率和采样点数有关。采样点数越多,能测的频率范围越大,精度越好。但是官方库限制了只有64,256,1024三种采样点数。而且点数越多,用到的单片机资源也越多。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分