关于ESP32硬件定时器报错问题
·
目录
前言
不知怎么今天突然想记录下学习记录,我问腾讯元宝我说今天突然想写一篇博客,但是已经大三了这几天还期末考试,是不是太浪费时间,这个想法出现太晚了,大一还可以,元宝说了一大堆意思就是有意义,不管了,随心,记录一下挺好的,以下是今天碰到的一个小问题。2025.6.23
一、一些ESP32教程的范例代码
代码如下
#include <Arduino.h>
hw_timer_t *tim1 = NULL;
int tim1_IRQ_count = 0;
void tim1Interrupt()//中断操作函数
{
Serial.println("haha");
tim1_IRQ_count++;
Serial.println(timerAlarmEnabled(tim1));
}
void setup()//初始化函数
{
Serial.begin(115200);
tim1 = timerBegin(0, 80, true);
timerAttachInterrupt(tim1, tim1Interrupt, true);
timerAlarmWrite(tim1, 100000, true);
timerAlarmEnable(tim1);
}
void loop()//正常的循环函数
{
if (tim1_IRQ_count > 10)
{
Serial.println("count trigger");
tim1_IRQ_count = 0;
}
}
二、为什么你报错?
不管是在Arduino平台还是VScode,不妨ctrl+左键点住一个函数进头文件里看下,比如说ctrl+左键点住以上的timerbegin 这个函数,进到esp32-hal-timer.c文件里,再再最上面找到#include "esp32-hal-timer.h"同样的方法ctrl+鼠标左键点进去,然后你会看到里面有如下内容
hw_timer_t *timerBegin(uint32_t frequency);
void timerEnd(hw_timer_t *timer);
void timerStart(hw_timer_t *timer);
void timerStop(hw_timer_t *timer);
void timerRestart(hw_timer_t *timer);
void timerWrite(hw_timer_t *timer, uint64_t val);
uint64_t timerRead(hw_timer_t *timer);
uint64_t timerReadMicros(hw_timer_t *timer);
uint64_t timerReadMillis(hw_timer_t *timer);
double timerReadSeconds(hw_timer_t *timer);
uint32_t timerGetFrequency(hw_timer_t *timer);
void timerAttachInterrupt(hw_timer_t *timer, void (*userFunc)(void));
void timerAttachInterruptArg(hw_timer_t *timer, void (*userFunc)(void *), void *arg);
void timerDetachInterrupt(hw_timer_t *timer);
void timerAlarm(hw_timer_t *timer, uint64_t alarm_value, bool autoreload, uint64_t reload_count);
发现范例程序setup里用的定时器函数和这里的不大一样,(和上面一样说明你是新版Ardunio),范例的都是老版本函数已经弃用了,包括但不限于timerBegin函数只需要一个参数,不用开启定时器使能等等,对照着看即可。
三、新版程序
新版的定时器计数器程序可参考以下,pin2每隔1s闪烁,pin4单次中断亮一下。
#define LED 2
#define LED_ONCE 4
void timer_interrupt()
{
digitalWrite(LED, !digitalRead(LED));
}
void timeronce_interrupt()
{
digitalWrite(LED_ONCE, !digitalRead(LED_ONCE));
}
hw_timer_t* timer = NULL;
hw_timer_t* once_timer = NULL;
void setup() {
Serial.begin(115200);
pinMode(LED, OUTPUT);
pinMode(LED_ONCE, OUTPUT);
timer = timerBegin(10000);//定时频率 秒分之一,可以理解为频率为几就是一秒几次,此处定时时间为0.1ms
once_timer = timerBegin(10000);
timerAttachInterrupt(timer,timer_interrupt );//此处中断函数不需要加&,函数名本身就是函数指针
timerAttachInterrupt(once_timer,timeronce_interrupt);
timerAlarm(timer, 10000, true, 0);//第二个参数为触发定时中断的计数周期,10000*0.1ms=1s
timerAlarm(once_timer, 10000, false, 0);//第三个参数为是否自动重装载,否的话就是单次触发定时中断
}
void loop() {
}
四、注意事项
上面代码中已经注释出一些注意事项,还有几点要注意
1.timerBegin()函数参数不要小于10000,因为老版函数此处为分频系数,我一开始此处写80,打印出来定时器定时一直为0,后来看了函数内部有如下片段
divider = counter_src_hz / frequency;
if ((divider >= 2) && (divider <= 65536)) {
break;
} else {
divider = 0;
}
- 假设
counter_src_hz (时钟源频率)= 80MHz:frequency = 10,000Hz→divider = 8,000(合法)frequency = 1,000Hz→divider = 80,000(非法,>65536)
2.新版定时器不需要指定定时器。
3.不必理会时钟频率,不用设分频系数,内部自动处理,蛮好使的。
五、写在最后
记得刚学c语言时候翁恺说过,这些东西都是人做出来的,没有什么是不可知道的,所以只有暂时不知道,搞懂所有只有态度和时间问题。
更多推荐


所有评论(0)