1.实验原理

ESP32可以通过定时器完成各种预设好的任务,ESP32定时器在达到指定的时间后会产生中断,然后再回调函数中执行所需的功能。

在Arduino中定时器的有两种:

"硬件定时器"是ESP32芯片上的内置定时器,专门用于计时和定时的硬件模块。硬件定时器可以通过设置特定的寄存器来配置和控制,具有更高的精确性和稳定性。不受代码干扰,适用于高精度和实时性的任务,例如PWM输出或输入捕获的脉冲等。

"软件定时器"是通过编写代码在Arduino中模拟实现的定时器,他不依赖硬件模块,使用计数器变量实现定时功能。时间精度要求不高或只需要基本定时功能时可以使用。

软硬件定时器各有优劣,取决于应用需求。

2.硬件定时器

2.1 硬件定时器库函数

在ESP32 Arduino开发环境中,可以使用以下几个库函数(esp32-hal-timer.h)来配置和操作硬件定时器(timer):  

2.1.1 初始化硬件定时器

hw_timer_t * timerBegin(uint8_t num, uint16_t divider, bool countUp)
  • num    定时器变化,可选值0-3。
  • divider    定时器分频系数,用于设置定时器的始终频率。通常为80分频(设置APB时钟,ESP32主频80MHz),80则时间单位为1Mhz即1us,1000000us即1s。
  • countUp    指定定时器是否为向上计数模式。设置为ture为向上计数,false为向下计数。

2.1.2 关联中断处理函数

void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge)
  • timer    指向已初始化的定时器指针。
  • fn    中断服务函数。
  • edge    中断类型,true边沿触发,false电平触发。

2.1.3 设置定时器计数值

void timerAlarmWrite(hw_timer_t *timer, uint64_t alarm_value, bool autoreload)
  • timer    指向已初始化的定时器指针。
  • alarm_value    计数值,例如分频系数为80,500000us 意思为0.5s进入一次中断。
  • autoreload    是否重载,false定时器中断触发一次,true自动重载。

2.1.4 使能/失能定时器事件

void timerAlarmEnable(hw_timer_t *timer)
void timerAlarmDisable(hw_timer_t *timer)

2.1.5 获取定时器是否自动重载

bool timerGetAutoReload(hw_timer_t *timer)

2.1.6 使能/失能/重启定时器

void timerStart(hw_timer_t *timer)
void timerStop(hw_timer_t *timer)
void timerRestart(hw_timer_t *timer)
//定时器状态,是否开始计数
bool timerStarted(hw_timer_t *timer)

2.1.7 获取定时器报警值

uint64_t timerAlarmRead(hw_timer_t *timer)

2.2 硬件定时器使用步骤

  • 1.初始化定时器:使用 'timerBegin()' 初始化硬件定时器。
  • 2.注册中断函数:使用 'timerAttachInterrupt()' 函数将中断处理函数与定时器关联起来。
  • 3.设置定时器模式:使用 'timerAlarmWrite()' 函数设置计数值及是否重载。
  • 4.启动定时器:使用 'timerAlarmEnable()' 函数使能定时器,开始计数。

2.3 示例

//定时器中断初始化
hw_timer_t *timer = NULL;
void timer_init(void)
{
  timer = timerBegin(0, 80, true);
  timerAttachInterrupt(timer, timerIAR, true);
  timerAlarmWrite(timer, 500 * 1000, true);
  timerAlarmEnable(timer);
}
//中断处理函数
void timerIAR()
{
  digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}

3.软件定时器

使用软件定时器的时候,需要用到ESP32内置的库 Ticker,Ticker是ESP32 Arduino内置的一个定时器库,这个库用于规定时间后调用函数。

 3.1 Ticker库函数

3.1.1 停止Ticker

void Ticker::detach()

3.1.2 Ticker激活状态

bool Ticker::active()//true表示启用

3.1.3 once()

void once(float seconds, void (*callback)(TArg), TArg arg)
void once_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg)

n秒(毫秒)后只执行一次callback函数,arg表示回调函数的参数(不写表示没有)。

3.1.4 attach()

void attach(float seconds, void (*callback)(TArg), TArg arg)
void attach_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg)

每隔n秒(毫秒)后周期性执行callback,arg参数同once()。

3.2 示例

//软件定时器初始化
Ticker ticker;
void ticker_init(void)
{
  ticker.attach(0.5,timerIAR);
}
//每0.5秒转换一次led状态
void timerIAR()
{
  digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}