《MCU软件定时器常见的实现方式.docx》由会员分享,可在线阅读,更多相关《MCU软件定时器常见的实现方式.docx(37页珍藏版)》请在优知文库上搜索。
1、在一般的嵌入式产品设计中,介于成本、功耗等,所选型的MCU基本都是资源受限的,而里面的定时器的数盘更是有限.在我们软件设计中往往有多种定时需求,例如脉冲输出、按捷检测、1.CD切屏延时等等,我们不可能让每一个定时业务都去开一个硬件定时器,一来硬件资源可能不足,二米会使软件过度依赖F健件平台,从而导致较差的可移植性.而若我们有一个软件定时器,所有定时业务都依赖于软件定时器,不仅节省硬件资滁,以后在移植的时候也只需要将软件定时器和硬件相关的部分修改就行了,其他部分都不用动。软件定时器实现方式:一、用结构体数蛆的方式实现软件定时器用结构体数组的方式实现起来较简单,也容易理解,除此之外和之后的链去实现
2、方式比起来没有其他优点。但还是介绍一下实现方法:在结构体数组内定义一个Start标志和定时时长duration,还有一个为计数值count,这3个变量为爆墙本的3个变量,其他的可以自己补充,比如运行模式、向调函数指针等.还有就是每一个结构体数组就是一个定时滞.能要我们提前定义好这个结构体数组有多大。定义好之后,在开启定时渊的时候我们将对应的数组内Start标志置位,在硬件tick中断服务函数里面我们去向所有结构体数组内的Stan标志是否置位,当查到当前start被置位时将此数组内的duration和count做比较,如果相等就说明此定时器定时时间到了,如果不等就将count+.然后接着查其他数
3、组的start标志,以此无限循环.此种方式缺点非常明显,那就是在硬件tick中断服务函数内,我们得轮询所有数组,如果我们软件业务需求是20个定时任务,那我们就存在软件定时器的实现里定义20个数组,空间浪费倒是其次的,关键是硬件tick轮询的数组越多,执行到某个数组的时间就越长,若以后有50个、100个定时需求时,将会导致定时时间极不精准.二、用链表实现软件定时得介于以上用结构体数组实现软件定时的种种缺点,我们提出改进方案.经过分析,在大多数定时业务中,往往只M要在某个时间段定时一次,也就是说定时岩会开R定时和结束定时,当然,用数组的实现的定时岩也可以开启定时和关闭定时,只需要用Start标志去
4、决定就行了,但是用散组实现的方式中,即使你关闭了定时器,也就是去掉了Start标志,此定时器虽然不运行了,但是数组的空间不会减少,梗件tick依然要轮询所有数组。所以我们福要用链表来实现软件定时器,在硬件tick中轮询所有节点,开启一个定时那就加入一个书点,关闭定时器就删除一个节点,可以保证在当前时刻只轮询器要定时的节点,可以极大的保证定时准确性.在加上可以让用户选择定时时间到了直接在硬件tick内执行或者在硬件tick内置标志,然后在whi1.e循环内排队执行,可以非常有效的解决关键业务定时不精准的问即.比如脉冲输出这种需要定时准确的业务.性表实现方式H文件:* sfor_timer_1.i
5、st.h* 彼表实现的软件定时器库* /*1.fndef_SOFT_TIMER_1.IST_H-define* 硬件中断tick* /edefineriMER_HARD_TICK1Ums,硬件tick取决于硬件定时中断时间*/typedefenumONCE_MODE,公行延时单次定时愎式,即超时后自动关闭定时器/CONTINUEJODE,/持续定时模式.只转开J:除非手动关闭否则永不停歇/DEFINjNUM_MODE,/*定义次数的模式行指定的次数后关闭定时器*/TimerTimi11gModeType;/typedefenumRUN_IN_1.OOP_MODE,*轮询执行模式*/RUN_IN
6、_INTERRUPT_MODE,/*中断实时执行模式/JTimerRunModeType;*软件定时器根本类型*/typedefstructSoftTimerunsigned1.ongcounter;*计数*/unsigned1.ongduration;*定时时长*/unsigned1.ongrun-num;*自定义的定时次数*/BOO1.Start_f1.ag;*启动标志/BOO1.1.oop_f1.ag;*轮询标志*/数TimerRunModeTyperun-mode;TimerTimingModeTypetimingJnOe1.e;void(*ca1.1.back_function)(v
7、oid);/*回调函structSoftTimer,next;SoftTimer;duration:要计时的时长,冷位为硬件中断的tick*timeout_hand1.er:定时到了之后要执行的函数指针return:无/externvoidcreat_sing1.e_soft_timer(SoftTimer*p,TimerRunModeTypemode,unsigned1.ongduration,void(*timeout-had1.er)(void);/*创建永远运行的软件定时器并立刻开始计时* 初始化软件定时器的硬件tick/externvoidsoft_timer_tick_init(v
8、oid);* 创建一个只运行次的软件定时器并立刻开始计时* 参数表:p:定时器结构体指针,由用户创建*mode:选择运行模代,可选定时器到了之后是H接在tick中断内执行还是置起标志在WhiIe循环内轮询执行*参数表:P:定时器结构体指针,由用户创建* mode:选择运行模式,可选定时器到了之后是直接在tick中断内执行还是置起标志在WhiIe循环内轮起执行* duration:要计时的时长,单位为硬件中断的tick* timeOUt.hand1.er:定时到了之.后要执行的函数指什* return:无externvoidcreat_continue_soft_timer(SoftTimerm
9、ode:选择运行模式,可选定时器到了之后是直接在tick中断内执行还是置起标志在whi1.e循环内轮渐执行*duration:要计时的时长,单位为映件中断的tick*time。UjhandIer:定时到了之后要执行的函数指针*return:无*/externvoidrestart_sing1.e_soft_timer(SoftTimer*p,TimerRunModeTypemode,unsigned1.ongduration,void(*timeout-hand1.er)(void);/*p,TimerRunModeTypemode,unsigned1.ongduration,void(*ti
10、meout_hand1.er)(void)* 创建指定次数运行的软件定时器并立刻开始计时* 参数表:p:定时器结构体指针,由用户创建eTypemode,unsigned1.ongrun_num,unsigned1.ongduration,void(timeout-ha11d1.er)(void);/* 重启指定的单次软件定时器* 参数衣:p:定时器结构体指针,由用户创建* 系统main循环进程,用于执行轮询模式的回调函数/externvoidsoft_timer_main_1.oop(void);* 此函数为tick中断服务函数,而要桂我在外部硬件定时器上* 因此蟆件定时器的定时精度由此函数挂
11、载的硬件定时时间决定,* 比如此函数挂载在定时50ms的外部定时器上,那么定时dutation* 为2。时定时时间就是2e*50ms=1.S* /externvoidsystem_tick_IrqHand1.er(void);endif*!1SOFTTIMER_1.IST_H/C文件:sfor_timer_1.ist.c* 链表实现的软件定时阵SdefineNU1.1.(void*软件定时器内部变量/staticSoftTimerhead-point=NU1.1.;staticstructSoftTimer*creat-node(SoftTimer*node);staticcharde1.et
12、e-node(SoftTimer*node);staticBOO1.is_node_a1.ready_creat(SoftTimertnode);初始化软件定时器的硬件tick*/voidsoft_timer_tick_init(void)R_IT_Create();1.1.11j.-,iWtick10ms/)0)typedefenumFA1.SE=,TRUE=!FA1.SEBOO1.;inc1.udemeter_inc1.ude.h包含用户的燃件定时滞初始化南族inc1.udesoft_timer_1.ist.hR_IT_Start();*系统main衡环进程,用于执行轮询模式的回调函数*/
13、voidsoft_timer_main_1.oop(void)(structSoftTimerp1.=head-poi11t;whi1.e(p1.I=NU1.1.)卜二不为,if(p1.-1.oop_f1.ag=TRUE)p1.-1.oop_f1.ag=FA1.SE;p1.-ca1.1.back-function();if(p1.-start-f1.agI=TRUE)de1.ete,node(p1.);*寻找下个有意义的节点*/p1.p1.-next;/*创建一个只运行一次的软件定时器并刻开始计时*参数表:p:定时器结构体指针,由用户创建 mode:选择运行模式,可选定时器到了之后是直接在ti
14、ck中断内执行还是月起标志在Whi1.e沛环内轮询执行 duration:要计时的时长,通位为硬件中断的tick timeout,hand1.er:定时到了之后要执行的函数指针 return:无 /voidcreat_sing1.e_soft_timer(SoftTimerp,TimerRunModeTypemode,unsigned1.ongduration,void(timeout-ha11d1.er)(void)if(p=NU1.1.)II(timeout_hand1.er=NU1.1.)duration=0)return;p-start-f1.agTRUE;p-counter=0;p-1.oop-f1.ag三FA1.SE;p-duration=duration;if(modeRUN_IN_1.OOP_MODE)p-run-mode=RUN_IN_1.OOP_MODE;e1.sep-run_mode=RUN_IN_INTERRUPT_MODE;p-ca1.1.back-function=timeout-hand1.er;p-timing-mode=ONCE_MODE;p-run-num=0;/1.m1.门定M故的靖一卜此片dhead-point=creat-node(p);)* 创建永远运行的软件定时器并立刻开始计时* 参数表:p:定时器结构体指