非阻塞延时实现LED闪烁功能(累计主循环次数)
阻塞延时
void main()
{
while(1){
LED = 0;
delay_xms(500);
LED = 1;
delay_xms(500);
}
}
非阻塞延时
定义一个变量作为累计循环次数的计数(将for循环或者while循环改为判断的形式,便于后面的多任务处理。)
sbit LED0 = P1^0;
#define LED_DELAY_TIME 5000
unsigned int u16_led_cnt;
unsigned char u8_led_delay_flag
void main()
{
U16_led_cnt = LED_DELAY_TIME;
//依靠while(1)来计数
while(1){
if(U16_led_cnt)
{
u16_led_cnt--;//该变量会减5000次
if(!u16_led_cnt){
u8_led_delay_flag = 1;
}
if(u8_led_delay_flag == 1)//代表时间到了
{
//首先将标志清零,防止多次触发
u8_led_delay_flag = 0;
U16_led_cnt = LED_DELAY_TIME;
LED0 = ~LED0;
}
}
}
}
没有独占系统,他每次都是执行一次就出去了,并不像阻塞函数的for循环一直卡在循环里面。
实现不同灯闪烁不同时间,虽然两个任务差了微秒的量级,但是他们看着像同步运行,每次在while循环里面都是顺序执行。
例子:人只有一个大脑,但是可以边吃饭边看手机,感觉同时做两件事情
特点:我们要把每个大循环执行的延时任务分割开来,不要一次将延时执行完,而是每次执行一点点,但是借助while大循环可以多次执行,同样可以起到一个延时的目的。
sbit LED0 = P1^0;
sbit LED1 = P1^1;
#define LED0_DELAY_TIME 5000
#define LED1_DELAY_TIME 10 000
void main()
{
unsigned int u16_led0_cnt;
unsigned char u8_led0_delay_flag
unsigned int u16_led1_cnt;
unsigned char u8_led1_delay_flag
U16_led0_cnt = LED0_DELAY_TIME;
U16_led1_cnt = LED1_DELAY_TIME;
//依靠while(1)来计数
while(1){
if(U16_led0_cnt)
{
u16_led0_cnt--;//该变量会减5000次
if(!u16_led0_cnt){
u8_led0_delay_flag = 1;
}
if(u8_led0_delay_flag == 1)//代表时间到了
{
//首先将标志清零,防止多次触发
u8_led0_delay_flag = 0;
U16_led0_cnt = LED0_DELAY_TIME;
LED0 = ~LED0;
}
if(U16_led1_cnt)
{
u16_led1_cnt--;//该变量会减5000次
if(!u16_led1_cnt){
u8_led1_delay_flag = 1;
}
if(u8_led1_delay_flag == 1)//代表时间到了
{
//首先将标志清零,防止多次触发
u8_led1_delay_flag = 0;
U16_led1_cnt = LED1_DELAY_TIME;
LED1 = ~LED1;
}
}
}
}
总结
软件延时如直接用for或while循环实现延时的函数,他们是独占CPU的延时函数,当该软件延时启动的时候,CPU的其他任务无法执行,整个系统处于停止等待的状态,不利于多任务并行。此时我们可以实现一种非阻塞的延时,定义一个变量作为累计循环次数的计数,将for循环或者while循环改为判断的形式,每次执行一次就进行–操作,然后判断是否计数完成,然后跳出程序,进而执行其他任务函数。最终呈现的效果是一种多任务并行的效果,而不像阻塞函数的for循环一直卡在循环里面。