目录

前言

一、一些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语言时候翁恺说过,这些东西都是人做出来的,没有什么是不可知道的,所以只有暂时不知道,搞懂所有只有态度和时间问题。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐