定时器
介绍
定时器是单片机内部的一种外设,主要用来实现定时执行代码的功能,通过计数器和时钟周期来计时。定时器的类型多样,包括PWM定时器、系统定时器、看门狗定时器等,各有不同的特点和用途
ESP32 内置 4 个 64-bit 通用定时器。每个定时器包含一个 16-bit 预分频器和一个 64-bit 可自动重新加载向上/向下计数器。
4个定时器分为 2 组,每组 2 个。TIMGn_Tx
的 n 代表组别,x 代表定时器编号。共4个硬件通用定时器,分别对应序号0,1,2,3
ESP32的计数基频为80MHZ,预分频系数为80可以得到1MHz的计数信号,每个计数信号的周期为1us,即每个计数单位1us
定时器API
1.定时器硬件初始化
hw_timer_t* timerBegin(timer_num_t timer_num, uint32_t divider, bool count_up)
timer_num
:定时器编号,可选值为 0-3 等。divide
r:定时器的分频系数,用于设置定时器的时钟频率。较大的分频系数将降低定时器的时钟频率。可以根据需要选择合适的值,一般设置为 80 即可count_up
:指定定时器是否为向上计数模式。设置为 true 表示向上计数,设置为 false 表示向下计数。
2.将中断处理函数与特定的定时器关联起来
timerAttachInterrupt(hw_timer_t *timer, void (*isr)(void *), int intr_type)
timer
:定时器指针isr
: 中断处理函数intr_type
: 中断类型,可选值为 ture(边沿触发)或 false(电平触发)
3.设置定时器的计数值
timerAlarmWrite(hw_timer_t *timer, uint64_t alarm_value, bool autoreload)
timer
:定时器指针alarm_value
: 定时器的计数值,向上计数到达该数值溢出,触发中断。当预分频系数为80时,alarm_value设置为1000000,即间隔时间为1秒溢出,执行中断服务函数。autoreload
: 是否自动重载计数值,可选值为 true(自动重载)或 false(单次触发)
其他API
timerAlarmEnable(hw_timer_t *timer)
:用于启动定时器,使其开始计数timerAlarmEnabled(hw_timer_t *timer)
: 检查定时器是否启动timerAlarmDisable(hw_timer_t *timer)
:用于禁用定时器,停止计数timerGetAutoReload(hw_timer_t *timer)
:获取定时器是否自动重新加载timerAlarmRead(hw_timer_t *timer)
:获取定时器计数器报警值timerStart(hw_timer_t *timer)
:计数器开始计数timerStop(hw_timer_t *timer)
:计数器停止计数timerRestart(hw_timer_t *timer)
:计数器重新开始计数,从 0 开始timerStarted(hw_timer_t *timer)
:计数器是否开始计数。
使用硬件定时器的基本步骤如下:
10. 初始化定时器:使用 timerBegin()
函数初始化所需的硬件定时器。
11. 注册中断处理函数:使用 timerAttachInterrupt()
函数将中断处理函数与定时器关联起来。
12. 设置定时器模式:使用 timerAlarmWrite()
,设置触发一次,还是周期性触发。
13. 启动定时器:使用 timerAlarmEnable()
函数启动定时器,使其开始计数。
实训案例
定时器间隔定时
#include <Arduino.h>
// 定义引脚d2为数字输出引脚
#define d2 2
// 定时器服务函数,用于切换引脚d2的状态
void service_timer0() {
digitalWrite(d2, !digitalRead(d2)); // 读取引脚d2的当前状态,并取反后写入引脚d2
}
// 声明一个全局变量,用于存储定时器句柄
hw_timer_t *tim0 = NULL;
// 初始化定时器函数
void Init_timer() {
// 使用timerBegin函数初始化定时器,参数分别为定时器编号、时钟频率和是否启用自动重装载模式
tim0 = timerBegin(0, 80, true);
// 使用timerAttachInterrupt函数将定时器中断与服务函数service_timer0关联,并设置为在定时器溢出时触发中断
timerAttachInterrupt(tim0, service_timer0, true);
// 使用timerAlarmWrite函数设置定时器的闹钟值,参数分别为定时器句柄、闹钟值和是否启用闹钟功能
timerAlarmWrite(tim0, 2000000, true);
// 使用timerAlarmEnable函数启用定时器的闹钟功能
timerAlarmEnable(tim0);
}
void setup() {
// 设置引脚d2为数字输出模式
pinMode(d2, OUTPUT);
// 调用初始化定时器的函数
Init_timer();
}
void loop() {
// 主循环函数,空实现
}