#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "esp_log.h"
#include "driver/timer.h"
#define TIMER_DIVIDER 16
#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER/ 1000) //分频
#define TIMER_INTERVAL0_SEC (1) //计数值,如果为1,则1ms进入中断;如果为10,则10ms进入中断
#define TEST_WITH_RELOAD 1
typedef struct {
uint64_t timer_minute_count;
uint64_t timer_second_count;
} timer_event_t;
timer_event_t g_timer_event;
xQueueHandle timer_queue;
unsigned int timer_counter = 0;
void IRAM_ATTR timer_group0_isr(void *para) //中断函数
{
timer_spinlock_take(TIMER_GROUP_0);
int timer_idx = (int) para;
// /* Prepare basic event data
// that will be then sent back to the main program task */
timer_counter++;
timer_event_t evt;
xQueueSendFromISR(timer_queue, &evt, NULL); //每次进入中断都会向设置好的队列发送消息
timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);
/* After the alarm has been triggered
we need enable it again, so it is triggered the next time */
timer_group_enable_alarm_in_isr(TIMER_GROUP_0, timer_idx);
/* Now just send the event data back to the main program task */
timer_spinlock_give(TIMER_GROUP_0);
}
static void example_tg0_timer_init(int timer_idx,
bool auto_reload, double timer_interval_sec)
{
/* Select and initialize basic parameters of the timer */
timer_config_t config = {
.divider = TIMER_DIVIDER,
.counter_dir = TIMER_COUNT_UP,
.counter_en = TIMER_PAUSE,
.alarm_en = TIMER_ALARM_EN,
.auto_reload = auto_reload,
}; // default clock source is APB
timer_init(TIMER_GROUP_0, timer_idx, &config);
/* Timer's counter will initially start from value below.
Also, if auto_reload is set, this value will be automatically reload on alarm */
timer_set_counter_value(TIMER_GROUP_0, timer_idx, 0x00000000ULL);
/* Configure the alarm value and the interrupt on alarm. */
timer_set_alarm_value(TIMER_GROUP_0, timer_idx, timer_interval_sec * TIMER_SCALE);
timer_enable_intr(TIMER_GROUP_0, timer_idx);
timer_isr_register(TIMER_GROUP_0, timer_idx, timer_group0_isr,
(void *) timer_idx, ESP_INTR_FLAG_IRAM, NULL);
timer_start(TIMER_GROUP_0, timer_idx);
}
static void timer_example_evt_task(void *arg)
{
while (1) {
timer_event_t evt;
xQueueReceive(timer_queue, &evt, portMAX_DELAY);
g_timer_event.timer_minute_count ++;
//60s 计算一次 刷新时间
if(g_timer_event.timer_minute_count >= 60000){
g_timer_event.timer_minute_count = 0;
printf("One minute receive ...\n");
}
g_timer_event.timer_second_count ++;
//1s计算一次
if(g_timer_event.timer_second_count >= 1000){
g_timer_event.timer_second_count = 0;
printf("One second receive ...\n");
}
}
}
void ds_timer_init(void)
{
g_timer_event.timer_minute_count = 0;
g_timer_event.timer_second_count = 0;
timer_queue = xQueueCreate(10, sizeof(timer_event_t));
example_tg0_timer_init(TIMER_0, TEST_WITH_RELOAD, TIMER_INTERVAL0_SEC);
xTaskCreate(timer_example_evt_task, "timer_evt_task", 2048, NULL, 5, NULL);
}
void app_main(void)
{
ds_timer_init();
while(1){
printf("system run ...\n");
vTaskDelay(1000 / portTICK_PERIOD_MS);
if(timer_counter >= 1000)
{
timer_counter = 0;
printf("ESP32 Demo Timer Task run ...\n");
}
}
}
主要是验证了ESP32中的消息队列机制,配置好定时器后,在每次定时中断中向消息队列发送消息,在消息队列接收端接收消息并打印触发信息。作为一个小demo方便后续开发查阅。
运行结果: