传统的程序设计思想是按程序流程顺序执行指令,系统每次只能完成一个任务。当一个任务正在执行时,其它任务处在等待状态,且无法满足多任务调度、实时处理的要求。这里举一个例子,比如处理键盘按键按下这个过程,大家都知道,当按键按下之后需要抖动处理,一般会延时20MS再判断按键是否有效,如果这20MS内处在原地踏步的等待状态,那么效率会非常低。如何处理才能使CPU的效率更高呢?采用时间片轮转算法可以解决这个问题。 ??? 时间片轮转算法是实现多任务调度的一种常用算法。在这种算法中,系统将所有的任务按顺序排成一个队列,每次调度时把CPU分配给队首的任务,并令其执行一个时间片,构成微观上轮流运行、宏观上并行执行的多任务效果。 ??? 采用时间片轮转算法可以极大地改善了程序结构。在进行程序设计时,先根据具体需要,设计出一个合理的时间片,在规定的时间片内,将系统的所有模块运行一遍,每个功能模块都设置成彼此独立的子程序,在每个功能模块的开始处都设置了一个标志位,进入功能模块后,首先根据标志位判断是否执行该子程序,如满足要求则执行,否则,进入下一个功能模块,如果某些功能模块涉及到延时(如按键去抖动延时),不再像传统的编程思想那样,进行延时等待,而是以时间片设置的时间为基准,在某些功能模块延时期间,继续执行其他模块的功能,这样系统执行完一遍所有功能模块需用一个时间片的时间,如果时间片的时间足够短,在程序的执行过程中,就相当于所有的功能模块同时工作一样,从而满足多任务实时要求。 ?? 下面以IAR FOR STM8为例,说说时间片轮转法如何实现。 先设定一个合理的时间片,这里设为400us,采用TIM4中断现实,即每400us中断一次处理。然后在中断处理模块里面根据标志位判断是否执行某个子程序。
//TIM4初始化,400us中断一次 void init_hard_SysClk(void) {?? ? ??????? asm("sim"); ??????? TIM4_IER = 0x00;?? ?//禁止中断 ??????? TIM4_EGR = 0x01;?? ?//允许产生更新事件 ??????? TIM4_PSCR = SYSPRESCALER; ??????? TIM4_ARR = SYSTIME; ??????? TIM4_CNTR = SYSTIME; ??????? TIM4_CR1 = 0x01; ??????? TIM4_IER = 0x01; ??????? asm("rim"); }
//中断处理程序,系统所有任务在这里进行调度。 #pragma vector = TIM4_OVR_UIF_vector __interrupt void TIM4_OVR_UIF(void) {?? ? ??????? TIM4_SR = 0x00; ??????? //-------------------------------------- ??????? SysCount ++; ??????? if( (SysCount%5) == 1 )???????????????? //1,6,11...即5*400=2000us ??????? {?? ? ??????????? SysDealFlag = 1;?? ???????????????? //系统处理,每2ms ??????? }?? ? ??????? //--------------------------------------- ??????? else if( SysCount == 5 )?? ??? ?//5 --- 2ms ??????? {?? ? ??????????? BuzzerDeal_Flag = 1;?? ???????? //蜂鸣器处理 ??????? }?? ??? ??? ? ??????? else if( SysCount == 10 )?? ??? ?//10 --- 4ms ??????? {?? ? ??????????? KeyDeal_Flag = 1;?? ???????????????? //按键处理 ??????? }????? ? ??????? else if( SysCount == 15 )?? ??? ?//15 --- 6ms ??????? {?? ? ??????????? Disp_Flag = 1;?? ???????????????? //显示处理 ??????? }????????????? ? ??????? . ??????? . ??????? . ??????? else if( SysCount >= 25 )?????????????? //25 --- 10ms ??????? {?? ? ??????????? SysCount = 0; ??????? } ??????? //--------------------------------------- ??????? else ??????? {?? ? ??????????? ADC_Flag = 1;?? ???????????????? //AD采集 ??????? }?? ??? ? }
//在主程序里,根据标志位执行任务 void main( void ) { ??? while(1) ??? { ??????? //------2ms的任务-------------------------------- ??????? if( SysDealFlag == 1 ) ??????? {?? ? ?????????? . ?????????? . ?????????? . ??????? } ??????? //------剩余时间的任务-------------------------------- ??????? if( ADC_Flag == 1 ) ??????? { ?????????? . ?????????? . ?????????? .?? ? ??????? } ??????? //------10ms的任务----------------------------------------------------- ??????? if( BuzzerDeal_Flag == 1 ) ??????? {?? ? ?????????? . ?????????? . ?????????? . ??????? } ??????? //-------------------------------------- ??????? if( KeyDeal_Flag == 1 ) ??????? { ?????????? . ?????????? . ?????????? . ??????? } ??????? //-------------------------------------- ??????? if( Disp_Flag == 1 ) ??????? { ?????????? . ?????????? . ?????????? . ?? ?} ?? ?. ??????? . ??????? .?? ? ??? }?? ? }
|