之前写过一篇使用stm32的滴答定时器构建多组软件定时器的博客,有感兴趣的可以看一下:
stm32滴答定时器构建多组软件定时器
- 使用滴答定时器构建软件定时器,其中定时器的超时是靠轮询来实现的,所以精度不高。但是实现方法及其简单,甚至都不用配置什么外设,对于一般的定时任务来说够用了。
- 如果是对定时精度较高的任务来说,我们最好用硬件定时器来实现了。但是MCU的硬件定时器资源有限,而且定时器开多了可能会混乱,不好管理。能不能用一两组硬件定时器来实现更多的定时任务呢?我们今天就来一起研究一下这个问题。
我们使用定时器的溢出中断来实现这个构想(暂且称之为构想)吧,这里主要说下实现的思想,具体代码暂时没有时间调试哈:
- 定义定时任务相关的结构体
typedef void (*pfunc)(uint8_t);
typedef struct TMR_t{
pfunc cb_tmr; //定时器超时任务
uint8_t parameter; //任务函数参数
bool cycle; //是否循环定时
uint32_t tick; //时基
}HTMR_TypeDef;
typedef struct list_t{
struct list_t *next; //单向链表->next node
struct TMR_t *htmr; //指向定时器任务块
}LIST_TypeDef ;
2.初始化定时器,打开更新(溢出)中断
TIMx_Init();
void TIMx_IRQHandler(void){
HAL_TIM_IRQHandler(&htimx);
}
3.假设有如下定时任务
//task 1
任务:LED_toggle 超时时间:5s 是否循环:是
//task 2
任务:beep 超时时间:18s 是否循环:否
//task3
任务:print 超时时间:8s 是否循环:否
//task 4
任务:lcd_off 超时时间10s 是否循环:否
4.把定时任务加入到链表中
- –>
LED_toggle / 5s / true
-->print / 8s / false
-->lcd_off / 10s / false
-->beep / 18s / false
- 5秒定时中断
- –> LED_toggle() -->
print / 3s / false
-->LED_toggle / 5s / true
-->lcd_off / 5s / fase
-->beep / 13s / false
- 3秒定时中断
- –> print() -->
LED_toggle / 2s / true
-->lcd_off / 2s / fase
-->beep / 10s / false
- 2秒定时中断
- –> LED_toggle() lcd_off() -->
LED_toggle / 5s / true
-->beep / 8s / false
- 5秒定时中断
- –> LED_toggle() -->
beep / 3s / false
-->LED_toggle / 5s / true
- 3秒定时器中断
- –> beep() -->
LED_toggle / 2s / true
- 2秒定时器中断
- –> beep() -->
LED_toggle / 5s / true
以上就是大致的思路,每次进入定时器溢出中断,触发超时任务、更新链表中的数据,更新定时器的溢出周期。
暂时没有时间调试具体代码,有感兴趣的童鞋也可以顺着这个思路实现一下咯