定时器组
# Example: timer_group
This example uses the timer group driver to generate timer interrupts at two specified alarm intervals.
Two timers are configured
* Each timer is set with some sample alarm interval
* On reaching the interval value each timer will generate an alarm
* One of the timers is configured to automatically reload it's counter value on the alarm
* The other timer is configured to keep incrementing and is reloaded by the application each time the alarm happens
定时器组,这个例子用0组的0和1
其中0 不是reload 1是reload的
分步解析一下:
typedef volatile struct { struct{ union { struct { uint32_t reserved0: 10; uint32_t alarm_en: 1; /*When set alarm is enabled*/ uint32_t level_int_en: 1; /*When set level type interrupt will be generated during alarm*/ uint32_t edge_int_en: 1; /*When set edge type interrupt will be generated during alarm*/ uint32_t divider: 16; /*Timer clock (T0/1_clk) pre-scale value.*/ uint32_t autoreload: 1; /*When set timer 0/1 auto-reload at alarming is enabled*/ uint32_t increase: 1; /*When set timer 0/1 time-base counter increment. When cleared timer 0 time-base counter decrement.*/ uint32_t enable: 1; /*When set timer 0/1 time-base counter is enabled*/ }; uint32_t val; } config; uint32_t cnt_low; /*Register to store timer 0/1 time-base counter current value lower 32 bits.*/ uint32_t cnt_high; /*Register to store timer 0 time-base counter current value higher 32 bits.*/ uint32_t update; /*Write any value will trigger a timer 0 time-base counter value update (timer 0 current value will be stored in registers above)*/ uint32_t alarm_low; /*Timer 0 time-base counter value lower 32 bits that will trigger the alarm*/ uint32_t alarm_high; /*Timer 0 time-base counter value higher 32 bits that will trigger the alarm*/ uint32_t load_low; /*Lower 32 bits of the value that will load into timer 0 time-base counter*/ uint32_t load_high; /*higher 32 bits of the value that will load into timer 0 time-base counter*/ uint32_t reload; /*Write any value will trigger timer 0 time-base counter reload*/ } hw_timer[2];
typedef struct {
int type; // the type of timer's event
int timer_group;
int timer_idx;
uint64_t timer_counter_value;
} timer_event_t;
xQueueHandle timer_queue;
void app_main() { timer_queue = xQueueCreate(10, sizeof(timer_event_t));//建立一个队列专门放timer_event_t结构的数据 example_tg0_timer_init(TIMER_0, TEST_WITHOUT_RELOAD, TIMER_INTERVAL0_SEC);//goup0 tim0 noado reload example_tg0_timer_init(TIMER_1, TEST_WITH_RELOAD, TIMER_INTERVAL1_SEC);//goup0 tim1 rel xTaskCreate(timer_example_evt_task, "timer_evt_task", 2048, NULL, 5, NULL);//建立任务 }
static void timer_example_evt_task(void *arg) { while (1) { timer_event_t evt; xQueueReceive(timer_queue, &evt, portMAX_DELAY);//阻塞 /* Print information that the timer reported an event */ if (evt.type == TEST_WITHOUT_RELOAD) { printf("\n Example timer without reload\n"); } else if (evt.type == TEST_WITH_RELOAD) { printf("\n Example timer with auto reload\n"); } else { printf("\n UNKNOWN EVENT TYPE\n"); } printf("Group[%d], timer[%d] alarm event\n", evt.timer_group, evt.timer_idx); /* Print the timer values passed by event */ printf("------- EVENT TIME --------\n"); print_timer_counter(evt.timer_counter_value); /* Print the timer values as visible by this task */ printf("-------- TASK TIME --------\n"); uint64_t task_counter_value; timer_get_counter_value(evt.timer_group, evt.timer_idx, &task_counter_value); print_timer_counter(task_counter_value); } }
1.xQueueReceive(timer_queue, &evt, portMAX_DELAY);//阻塞阻塞等待
2. if (evt.type == TEST_WITHOUT_RELOAD)判断0 还是1
3.打印信息
printf("Group[%d], timer[%d] alarm event\n", evt.timer_group, evt.timer_idx);
/* Print the timer values passed by event */
printf("------- EVENT TIME --------\n");
print_timer_counter(evt.timer_counter_value);
/* Print the timer values as visible by this task */
printf("-------- TASK TIME --------\n");
uint64_t task_counter_value;
timer_get_counter_value(evt.timer_group, evt.timer_idx, &task_counter_value);
print_timer_counter(task_counter_value);
下面看初始化
/* * Initialize selected timer of the timer group 0 * * timer_idx - the timer number to initialize * auto_reload - should the timer auto reload on alarm? * timer_interval_sec - the interval of alarm to set */ 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; config.divider = TIMER_DIVIDER; //80/16=5 config.counter_dir = TIMER_COUNT_UP;//上升沿 config.counter_en = TIMER_PAUSE;//先停止计数 config.alarm_en = TIMER_ALARM_EN;//警报打开 config.intr_type = TIMER_INTR_LEVEL;//LEVEL模式 config.auto_reload = auto_reload;//自动 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);//先清0定时器计数 /* 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); }
1.timer_init初始化
2.清0 counter
3.设置alarm时间。
timer_set_alarm_value(TIMER_GROUP_0, timer_idx, timer_interval_sec * TIMER_SCALE);//
这里设置成timer_interval_sec * TIMER_SCALE 相当于sec级的定时
#define TIMER_DIVIDER 16 // Hardware timer clock divider 80/16
#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // convert counter value to seconds
#define TIMER_INTERVAL0_SEC (3.4179) // sample test interval for the first timer 3.4179s
#define TIMER_INTERVAL1_SEC (5.78) // sample test interval for the second timer
#define TEST_WITHOUT_RELOAD 0 // testing will be done without auto reload 5.78s
#define TEST_WITH_RELOAD 1 // testing will be done with auto reload
查看一下TIMER_BASE_CLK,是80 000 000 ,这里/16就是5M---定时器现在是base on 5M了
0.2us一次中断。
这里相当于 设置5M,但也计5M次,也就是1s-----再乘以上面的设置的3.4179s和5.78s
4.
timer_enable_intr(TIMER_GROUP_0, timer_idx);
enable 组0 的0或者1
5.回调
timer_isr_register(TIMER_GROUP_0, timer_idx, timer_group0_isr,
(void *) timer_idx, ESP_INTR_FLAG_IRAM, NULL);
6.
timer_start(TIMER_GROUP_0, timer_idx);定时器开始
下面看回调
void IRAM_ATTR timer_group0_isr(void *para) { int timer_idx = (int) para; /* Retrieve the interrupt status and the counter value from the timer that reported the interrupt */ uint32_t intr_status = TIMERG0.int_st_timers.val; TIMERG0.hw_timer[timer_idx].update = 1;//写入寄存器,开始计数 uint64_t timer_counter_value = ((uint64_t) TIMERG0.hw_timer[timer_idx].cnt_high) << 32 | TIMERG0.hw_timer[timer_idx].cnt_low; /* Prepare basic event data that will be then sent back to the main program task */ timer_event_t evt; evt.timer_group = 0; evt.timer_idx = timer_idx; evt.timer_counter_value = timer_counter_value; /* Clear the interrupt and update the alarm time for the timer with without reload */ if ((intr_status & BIT(timer_idx)) && timer_idx == TIMER_0) { evt.type = TEST_WITHOUT_RELOAD; TIMERG0.int_clr_timers.t0 = 1; timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE);//下一次报警时间 TIMERG0.hw_timer[timer_idx].alarm_high = (uint32_t) (timer_counter_value >> 32); TIMERG0.hw_timer[timer_idx].alarm_low = (uint32_t) timer_counter_value; } else if ((intr_status & BIT(timer_idx)) && timer_idx == TIMER_1) { evt.type = TEST_WITH_RELOAD; TIMERG0.int_clr_timers.t1 = 1; } else { evt.type = -1; // not supported even type } /* After the alarm has been triggered we need enable it again, so it is triggered the next time */ TIMERG0.hw_timer[timer_idx].config.alarm_en = TIMER_ALARM_EN; /* Now just send the event data back to the main program task */ xQueueSendFromISR(timer_queue, &evt, NULL);//下面阻塞,这里发送过去 }
1.若是0 则增加一次interval加到下一次时间里面。
2.若是1 因为是reload的,就不用了。
3.定时器的alarm值是 32位低位+32位高位的。
4.发送queue,解除task的阻塞,并将此时的count值打印出来
```
Example timer with auto reload
Group[0], timer[1] alarm event
------- EVENT TIME --------
Counter: 0x000000000000000a --------------------evnet1的时间,应该是5.7s多的,应该不会溢出才对,这里为何counter是a???
Time : 0.00000200 s --这里明显可以看出来是 2us/a=0.2us一次计算
-------- TASK TIME --------
Counter: 0x00000000000107ff
Time : 0.01351660 s
Example timer without reload
Group[0], timer[0] alarm event
------- EVENT TIME --------
Counter: 0x00000000092ae316 ----看间隔
Time : 30.76111800 s
-------- TASK TIME --------
Counter: 0x00000000092bd535 ---看间隔
Time : 30.77351460 s
```

浙公网安备 33010602011771号