ESP32-arduino,超好玩的定时器!
前言
嵌入式系统的主程序基本上是个大循环,如果在循环里要处理各个任务的请求的话,最粗暴的方式就是轮流查询,简称轮询, 轮询可以解决简单系统的问题,但当请求数量和处理复杂度提升的时候,难免捉襟见肘,中断就是为了解决“按需分配”的资源配置问题。
当然,中断有很几种,外部中断、定时中断等,今天我们要介绍的就是中断里的定时中断!
定时中断——定时执行的中断
直奔主题,编写一个定时中断的程序需要几步呢?我们来编写一个简单的定时器程序,每秒打印一次,如下:
- 首先声明一个定时器
/* timerBegin:初始化定时器指针
第一个参数:设置定时器0(一共有四个定时器0、1、2、3)
第二个参数:80分频(设置APB时钟,ESP32主频80MHz),80则时间单位为1Mhz即1us,1000000us即1s。
第三个参数:计数方式,true向上计数 false向下计数
*/
timer = timerBegin(0, 80, true);
- 编写中断函数并绑定定时器
/*
中断服务函数,为使编译器将代码分配到IRAM内,中断处理程序应该具有 IRAM_ATTR 属性
*/
void IRAM_ATTR onTimer() {
Serial.println('1');
}
/* timerAttachInterrupt:绑定定时器
第一个参数:指向已初始化定时器的指针
第二个参数:中断服务器函数
第三个参数:true边沿触发,false电平触发
*/
timerAttachInterrupt(timer, &onTimer, true);
- 初始化定时器,指定定时器、分频、计数方式
/* timerAlarmWrite:配置报警计数器保护值(就是设置时间)
第一个参数:指向已初始化定时器的指针
第二个参数:定时时间,这里为1000000us 意思为1s进入一次中断
第三个参数:是否重载,false定时器中断触发一次 true:死循环
*/
timerAlarmWrite(timer, 1000000, true);
- 启用定时器
/* timerAlarmEnable:启用定时器
第一个参数:指向已初始化定时器的指针
*/
timerAlarmEnable(timer);
- 关闭定时器
/*timerDetachInterrupt:关闭定时器
第一个参数:指向已初始化定时器的指针
*/
timerDetachInterrupt(timer);
hw_timer_t * timer = NULL; // 声明一个定时器
void IRAM_ATTR onTimer() { // 中断函数
Serial.println('1');
}
void setup() {
Serial.begin(115200);
timer = timerBegin(0, 80, true); // 初始化定时器指针
timerAttachInterrupt(timer, &onTimer, true); // 绑定定时器
timerAlarmWrite(timer, 1000000, true); // 配置报警计数器保护值(就是设置时间)
timerAlarmEnable(timer); // 启用定时器
// timerDetachInterrupt(timer); // 关闭定时器
}
void loop() {
}
需要注意的是:
- 中断服务程序必须是一个返回void(空)且没有输入参数的函数。
相关参考
[ESP32系列教程]ESP32 Arduino教程:定时器中断
ESP-Arduino玩转外设(五)中断基本概念及Timer中断
ESP32 Timer实现