应用代码(1)——软件定时器

这一部分代码是在自己实际项目中看到的代码,可以借鉴到其他地方!

原理解析:

举例:有两个定时器任务,2ms和2.5ms的定时任务
应用代码(1)——软件定时器_第1张图片

原码分享:

功能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
	}
}


你可能感兴趣的:(应用代码)