esp32学习笔记(2)——timer
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
ESP32 内置 4 个定时器分为两组,每组两个。每个定时器包含一个 16-bit 预分频器和一个 64-bit 可自动重新加载向上/向下计数器。
一、定时器配置步骤
要使用定时器首先要引用库
#include "driver/timer.h"
//1、定时器初始化
timer_init(TIMER_GROUP_x,TIMER_x,&timer_config_t;)
//参数1、定时器组0-1;2、定时器号0-1;3、定时器配置结构体
typedef struct {
timer_alarm_t alarm_en; /*!< 报警使能 */
timer_start_t counter_en; /*!< 计数使能,初始化时通常设置为PAUSE,在开启定时器的时候计数器就会开始计数 */
timer_intr_mode_t intr_type; /*!< 中断模式 *///计数器报警后是否产生中断
timer_count_dir_t counter_dir; /*!<计数方向 */ //向上或者向下计数
timer_autoreload_t auto_reload; /*!< 自动重装载*///计数器报警后是否自动重载指定的值
uint32_t divider; /*!< 预分频值. 2 to 65536. */
} timer_config_t;
//2、设置计数器的计数开始值 num:值
timer_set_counter_value(TIMER_GROUP_x, TIMER_x, num);
//3、设置报警值
timer_set_alarm_value(TIMER_GROUP_x, TIMER_x, num);
// num:计数多少次进入中断
// 1/(Base_clock/divider/num)=定时器时间
//4、使能定时器中断
timer_enable_intr(TIMER_GROUP_x, TIMER_x);
//5、添加中断回调函数
timer_isr_callback_add(timer_group_t group_num, timer_idx_t timer_num, timer_isr_t isr_handler, void *arg, int intr_alloc_flags);
//注意:这里第三个参数是中断处理函数的名字,第四个参数是中断处理函数的参数;第五个参数是用于分配中断的标志如果设置为ESP_INTR_FLAG_IRAM,那么handler函数必须用IRAM_ATTR属性声明,它只能调用IRAM或ROM中的函数,不能调用其他定时器api
//6、打开定时器
timer_start();
//7、中断处理函数
typedef bool (*timer_isr_t)(void *);
//这个中断处理函数的返回应是布尔型bool如果你在回调中调用FreeRTOS函数,你需要根据参数'pxHigherPriorityTaskwoken'的返回值返回true或false。例如,'xQueueSendFromISR'在回调中被调用,如果任何FreeRTos调用的返回值' pxhigherprioritytaskoken是pdTRUE,返回true;否则返回false。
二、参考部分代码
定时器初始化:
void my_timer_init(void)
{
timer_config_t timer_config_str;
timer_config_str.divider = timer_divider; //分频值,默认时钟是80mhz,80mhz/80=1mhz=1us
timer_config_str.counter_dir = TIMER_COUNT_UP;//向上计数模式
timer_config_str.counter_en = TIMER_PAUSE;//定时器计数失能
timer_config_str.alarm_en = TIMER_ALARM_EN;//使能定时器报警
timer_config_str.auto_reload = 1; //使能自动装载
timer_init(TIMER_GROUP_0,TIMER_0,&timer_config_str);//esp32定时器共有两组,每组两个
timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0);//设置定时器的计数值
timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 100000);//设置定时器的报警值(进入中断的值)
timer_enable_intr(TIMER_GROUP_0, TIMER_0);//使能定时器中断
timer_isr_callback_add(TIMER_GROUP_0, TIMER_0, timer_group_isr_callback, NULL, ESP_INTR_FLAG_IRAM);
// timer_isr_callback_add(TIMER_GROUP_0, TIMER_0, timer_group_isr_callback, NULL,0);//添加定时器中断回调
timer_start(TIMER_GROUP_0, TIMER_0);//打开定时器
printf("打开定时器成功");
}
2、定时器中断服务函数
static bool IRAM_ATTR timer_group_isr_callback(void *args)
{
BaseType_t pxHigherPriorityTaskWoken = pdFALSE;
// uint32_t timer_intr = timer_group_get_intr_status_in_isr(TIMER_GROUP_0); //获取中断状态
// if (timer_intr & TIMER_INTR_T0) {//定时器0分组的0号定时器产生中断
// /*清除中断状态*/
// timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);
// /*重新使能定时器中断*/
// timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_0);
// }
io_state = ! io_state;
gpio_set_level(led_gpio,io_state);
timer_count++;
return pxHigherPriorityTaskWoken;
}
对于中断函数来说,这个代码中只是在中断里面把led灯进行反转,还有每进一次中断就会记一次数
还有一点不太理解,就是根据官方手册给的数据,每进一次定时器中断就要清除一下标志位,然后就要重新使能报警中断,这个我也试验过,中断清与不清,定时器还都是会运行的。希望有了解的帮我解答一下
三.运行效果

总结
在控制台可以看到,打印的计数是一次加10,因为我i设置的分频是80,80mhz/80=1mhz,每计一次数就是1us,设置的是向上计数,并且是每计100000个数就会进入一次中断,那就是每0.1s就led灯就会翻转一次,count值就会加一次,因为在while循环里面打印数据之前设置了一个1000ms的延时,那就是说每次打印数据就会进入10次中断,count就会加10。
附上代码地址
代码