这一部分代码是在自己实际项目中看到的代码,可以借鉴到其他地方!
原理解析:
举例:有两个定时器任务,2ms和2.5ms的定时任务
原码分享:
功能1:定时器的添加
//定义一个软件定时器的全局变量
blt_soft_timer_t blt_timer;
/* 这边是软件定时器的定义:
* typedef struct blt_soft_timer_t
* {
blt_time_event_t timer[MAX_TIMER_NUM]; //timer0 - timer3,注意,这个0~3个定时器器是按排序来的,并不是说真的有0~3个定时器,而是有0~3个定时任务
u8 currentNum; //total valid timer num 目前的软件定时器数量
}
* timer[MAX_TIMER_NUM]; --》是以下的定时器变量包括:
* typedef struct blt_time_event_t {
blt_timer_callback_t cb; //定时器超时的回调函数
u32 t; //下一次间隔的时间点
u32 interval; //设置的时间间隔
} blt_time_event_t;
*/
//user add timer
//添加软件定时器 :带参(回调函数,时间间隔)这是创建软件定时器的地方
int blt_soft_timer_add(blt_timer_callback_t func, u32 interval_us)
{
int i;
u32 now = clock_time(); //获取当前的tick时钟
//不能写入的软件定时器号不能超过设置的最大定时器号
if(blt_timer.currentNum >= MAX_TIMER_NUM){ //timer full
return 0;
}
//没有超过的话
else{
//绑定回调函数
blt_timer.timer[blt_timer.currentNum].cb = func;
//绑定时间间隔
blt_timer.timer[blt_timer.currentNum].interval = interval_us * CLOCK_16M_SYS_TIMER_CLK_1US;//单位是1us
//绑定目前的时间+目前的时间间隔
blt_timer.timer[blt_timer.currentNum].t = now + blt_timer.timer[blt_timer.currentNum].interval;
blt_timer.currentNum ++; //软件定时器数量+1
blt_soft_timer_sort(); //排序,根据目前的时间来进行对这几个定时器进行排序,这个排序是核心,目的是让每个定时都能触发到
//因为在这个定时器的创建中,每次只和表头的那个定时器的目前时间元素(blt_timer.timer[0].t)进行比较
//这边是因为芯片厂商定义的,如果有定时器就会从低功耗唤醒,我们在使用的过程中可以屏蔽下面的唤醒
if(blt_timer.currentNum ){ //timer table not empty
if( (u32)(blt_timer.timer[0].t - now) < 3000 * CLOCK_16M_SYS_TIMER_CLK_1MS){
bls_pm_setAppWakeupLowPower(blt_timer.timer[0].t, 1);
}
else{
bls_pm_setAppWakeupLowPower(0, 0); //disable
}
}
return 1;
}
}
子函数_排序:
//if t1 < t2 return 1
#define TIME_COMPARE_SMALL(t1,t2) ( (u32)((t2) - (t1)) < BIT(30) )
// if t1 > t2 return 1
#define TIME_COMPARE_BIG(t1,t2) ( (u32)((t1) - (t2)) < BIT(30) )//这边是因为转换成了无符号数,所以是比较最高位
//按照定时时间将timer排序,便于process时 依次触发timer
int blt_soft_timer_sort(void)
{
if(blt_timer.currentNum < 1 || blt_timer.currentNum > MAX_TIMER_NUM){
write_reg32(0x40000, 0x11111120); while(1); //debug ERR
return 0;
}
else{
// 冒泡排序 BubbleSort
int n = blt_timer.currentNum;
u8 temp[sizeof(blt_time_event_t)];
for(int i=0;i<n-1;i++)
{
for(int j=0;j<n-i-1;j++)
{
if(TIME_COMPARE_BIG(blt_timer.timer[j].t, blt_timer.timer[j+1].t))
{
//swap
memcpy(temp, &blt_timer.timer[j], sizeof(blt_time_event_t));
memcpy(&blt_timer.timer[j], &blt_timer.timer[j+1], sizeof(blt_time_event_t));
memcpy(&blt_timer.timer[j+1], temp, sizeof(blt_time_event_t));
}
}
}
}
return 1;
}
功能2:定时器的删除
有添加就有删除
//软件定时器的删除
int blt_soft_timer_delete(blt_timer_callback_t func)
{
for(int i=0; i<blt_timer.currentNum; i++){
if(blt_timer.timer[i].cb == func){//通过回调函数的比较,确定当前是哪个定是哪个定时器
blt_soft_timer_delete_by_index(i);
if(i == 0){ //删除的是最近的timer,需要更新时间
//这边是如果距离下次定时器任务在3秒内,那么我们就不进入低功耗状态
if( (u32)(blt_timer.timer[0].t - clock_time()) < 3000 * CLOCK_16M_SYS_TIMER_CLK_1MS){
bls_pm_setAppWakeupLowPower(blt_timer.timer[0].t, 1);
}
else{
//不唤醒
bls_pm_setAppWakeupLowPower(0, 0); //disable
}
}
return 1;
}
}
return 0;
}
子函数_软件定时器删除
//timer 本来就是有序的,删除的时候,采用往前覆盖,所以不会破坏顺序,不需要重新排序
int blt_soft_timer_delete_by_index(u8 index)
{
//如果删除的值大于最大数,就跳出
if(index >= blt_timer.currentNum){
write_reg32(0x40000, 0x11111121); while(1); //debug ERR
return 0;
}
//这个就是把后面的定时器往前移动
for(int i=index; i<blt_timer.currentNum - 1; i++){
memcpy(&blt_timer.timer[i], &blt_timer.timer[i+1], sizeof(blt_time_event_t));
}
blt_timer.currentNum --;
return 1;
}
功能3:软件定时器的调用
void bls_pm_registerAppWakeupLowPowerCb(pm_appWakeupLowPower_callback_t cb);
#define BLT_TIMER_SAFE_MARGIN_PRE (CLOCK_16M_SYS_TIMER_CLK_1US<<7) //128 us
#define BLT_TIMER_SAFE_MARGIN_POST (CLOCK_16M_SYS_TIMER_CLK_1S<<2) // 4S
static int inline blt_is_timer_expired(u32 t, u32 now) {
//这边一条是很核心的,其实也是比较u32的值,这边很巧妙的利用了“无符号整型复数为一个很大值”的特性,来进行比较;又很巧妙的利用了
//如果是正数的时候,不能大于4s的这个条件,来作为时间限制。用一句话抵用了好几句语句。
return ((u32)(now + BLT_TIMER_SAFE_MARGIN_PRE - t) < BLT_TIMER_SAFE_MARGIN_POST);
}//BLT_TIMER_SAFE_MARGIN_PRE 就是128us,BLT_TIMER_SAFE_MARGIN_POST就是4s
//------------------------------定时器的初始化-----------------------------
void blt_soft_timer_init(void)
{
bls_pm_registerAppWakeupLowPowerCb(blt_soft_timer_process);
}
//初始化实际调用的函数
void blt_soft_timer_process(int type)
{
if(type == CALLBACK_ENTRY){ //callback trigger
}
u32 now = clock_time();//获取当前的时间
if(!blt_timer.currentNum){//如果没有定时任务
//不唤醒
bls_pm_setAppWakeupLowPower(0, 0);
return;
}
//如果 (现在的时间+128us) - 下次间隔的时间点 < 4S 这边的128是128us的补偿
//------------------------------timer[0]是最先要触发的定时器任务---------------------
if( !blt_is_timer_expired(blt_timer.timer[0].t, now) ){//每次都是比较表头(最先执行的定时器),所以要排序
return;
}
int change_flg = 0;
int result;
for(int i=0; i<blt_timer.currentNum; i++){
//定时器超时判断 ---》这里元素t = (now0 + blt_timer.timer[i].interval)
//blt_is_timer_expired函数里就是---》now1 +128us - (now0 + blt_timer.timer[i].interval) 是否>0
//如果大于0了就为真,也就是触发了
//--------------------定时时间到触发的判断条件--------------------
if(blt_is_timer_expired(blt_timer.timer[i].t ,now) ){ //timer trigger
if(blt_timer.timer[i].cb == NULL){
write_reg32(0x40000, 0x11111122); while(1); //debug ERR
}
else{
result = blt_timer.timer[i].cb();//执行回调函数
if(result < 0){
blt_soft_timer_delete_by_index(i);
}
//定时器任务执行成功的话
else if(result == 0){
change_flg = 1;
blt_timer.timer[i].t = now + blt_timer.timer[i].interval;
}
else{ //set new timer interval
change_flg = 1;
blt_timer.timer[i].interval = result * CLOCK_16M_SYS_TIMER_CLK_1US;
blt_timer.timer[i].t = now + blt_timer.timer[i].interval;
}
}
}
}
if(blt_timer.currentNum ){ //timer table not empty
if(change_flg){
blt_soft_timer_sort();
}
if( (u32)(blt_timer.timer[0].t - now) < 3000 * CLOCK_16M_SYS_TIMER_CLK_1MS){
bls_pm_setAppWakeupLowPower(blt_timer.timer[0].t, 1);
}
else{
bls_pm_setAppWakeupLowPower(0, 0); //disable
}
}
else{
bls_pm_setAppWakeupLowPower(0, 0); //disable
}
}