使用周期法测量
利用外部中断来确定两个下降沿之间的时间。之间的时间T用定时器来实现
#include <Arduino.h>
hw_timer_t *timer = NULL;
volatile uint32_t timerCount = 0;
volatile int interruptFlag = 0; //(中断回调函数与主程序共享的变量要加上 volatile 关键字)
volatile int interruptFlag_clear = 0; //(中断回调函数与主程序共享的变量要加上 volatile 关键字)
const int interruptPin = 5; // 外部中断引脚
void IRAM_ATTR interruptHandler() {
interruptFlag_clear =1;
}
void setup() {
Serial.begin(115200);
// 配置定时器
timer = timerBegin(10000000);//10M
timerAttachInterrupt(timer, []() {
timerCount++;
});
timerAlarm(timer, 100, true, 0); // 设置定时器中断时间间隔(这里是 1 秒)
timerStart(timer);
// 配置外部中断
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), interruptHandler, FALLING);
}
void loop() {
// Serial.print("Timer count: ");
// Serial.println(timerCount);
// timerCount = 0;
// delay(1000);
if (interruptFlag_clear == 1) {
timerStop(timer); //停止计数器
interruptFlag++;
if (interruptFlag == 1) {
timerCount = 0; //第一个脉冲,计数清零
} else if (interruptFlag == 2) {
//第二次进入,统计计数个数,并计算频率
// timerStop(timer); //停止计数器
float dre_time = timerCount; //单位为微秒
float fre = 1000000.0 / (timerCount * 10);
Serial.println("dre_time: " + String(dre_time));
Serial.println("fre: " + String(fre));
timerCount = 0; //清零
interruptFlag = 0;
// timerAlarm(timer, 100, true, 0); // 设置定时器中断时间间隔(这里是 1 秒)
// timerStart(timer); // 重启定时器
}
timerStart(timer); // 重启定时器
interruptFlag_clear = 0;
}
}
输入500Hz,1000H的频率,能够测到频率,但是比如我这里时钟是10M,每隔100次计数一次,可以计算出一次定时器中断为100*1/10M ,时钟为十分之一微秒,100次就是10微秒。
如果频率为1KHz,1个周期是1000微秒,也就是一个周期内可以数100次。
如果测量10个周期,可以提高精度。
这里调整到测量100个周期,那么精度得到较大提高
测试输入1001.4Hz ,会有0.1Hz的误差
100Hz,这个就非常准了。
3KHz
这种方式可以看到频率越高,误差越大。