🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
【90.1 多任务并行处理。】 两路速度不同的跑马灯,代表了两路独立运行的任务,单片机如何“并行”处理这两路任务,就涉及到“多任务并行处理的编程思路”。 ![](https://img.kancloud.cn/0f/49/0f49cc4e7b34f0e8c13dd7e514906c88_214x279.png) 上图90.1.1 灌入式驱动8个LED 第1路跑马灯 ![](https://img.kancloud.cn/1a/a6/1aa6512c1a2da257a8d80b5f06d97f89_244x287.png) 上图90.1.2 灌入式驱动4个LED 新增加的第2路跑马灯 如上图,本节特别值得一提的是,新增加的第2路跑马灯用的是4个LED,这4个LED的驱动IO口是“散装的”,因为,前面3个是P1口的(P1.4,P1.5,P1.6),最后1个是P3口的(P3.3),这种情况下,肯定用不了“移位”的处理思路,只能用跑马灯第3种境界里所介绍的“状态切换非阻塞”思路,可见,“IO口拆分”和“switch状态切换”又一次充分体现了它们“程序框架万能扩展”的优越性。代码如下: \#include "REG52.H" void T0\_time(); void SystemInitial(void) ; void Delay(unsigned long u32DelayTime) ; void PeripheralInitial(void) ; void Led\_1\_Task(void); void Led\_2\_Task(void); \#define BLINK\_TIME\_1 1000 //控制第1路跑马灯的速度,数值越大“跑动”越慢。 \#define BLINK\_TIME\_2 200 //控制第2路跑马灯的速度,数值越大“跑动”越慢。 sbit P0\_0=P0^0; sbit P0\_1=P0^1; sbit P0\_2=P0^2; sbit P0\_3=P0^3; sbit P0\_4=P0^4; sbit P0\_5=P0^5; sbit P0\_6=P0^6; sbit P0\_7=P0^7; sbit P1\_4=P1^4; sbit P1\_5=P1^5; sbit P1\_6=P1^6; sbit P3\_3=P3^3; volatile unsigned char vGu8TimeFlag\_1=0; volatile unsigned int vGu16TimeCnt\_1=0; volatile unsigned char vGu8TimeFlag\_2=0; volatile unsigned int vGu16TimeCnt\_2=0; void main() { SystemInitial(); Delay(10000); PeripheralInitial(); while(1) { Led\_1\_Task(); //第1路跑马灯 Led\_2\_Task(); //第2路跑马灯 } } void T0\_time() interrupt 1 { if(1==vGu8TimeFlag\_1&&vGu16TimeCnt\_1>0) //软件定时器1 { vGu16TimeCnt\_1--; } if(1==vGu8TimeFlag\_2&&vGu16TimeCnt\_2>0) //软件定时器2 { vGu16TimeCnt\_2--; } TH0=0xfc; TL0=0x66; } void SystemInitial(void) { TMOD=0x01; TH0=0xfc; TL0=0x66; EA=1; ET0=1; TR0=1; } void Delay(unsigned long u32DelayTime) { for(;u32DelayTime>0;u32DelayTime--); } void PeripheralInitial(void) { } //第1路跑马灯 void Led\_1\_Task(void) { static unsigned char Su8Step=0; //加static修饰的局部变量,每次进来都会保留上一次值。 switch(Su8Step) { case 0: if(0==vGu16TimeCnt\_1) //时间到 { vGu8TimeFlag\_1=0; vGu16TimeCnt\_1=BLINK\_TIME\_1; //重装定时的时间 vGu8TimeFlag\_1=1; P0\_0=1; //第0个灯熄灭 P0\_1=0; P0\_2=0; P0\_3=0; P0\_4=0; P0\_5=0; P0\_6=0; P0\_7=0; Su8Step=1; //切换到下一个步骤,精髓语句! } break; case 1: if(0==vGu16TimeCnt\_1) //时间到 { vGu8TimeFlag\_1=0; vGu16TimeCnt\_1=BLINK\_TIME\_1; //重装定时的时间 vGu8TimeFlag\_1=1; P0\_0=0; P0\_1=1; //第1个灯熄灭 P0\_2=0; P0\_3=0; P0\_4=0; P0\_5=0; P0\_6=0; P0\_7=0; Su8Step=2; //切换到下一个步骤,精髓语句! } break; case 2: if(0==vGu16TimeCnt\_1) //时间到 { vGu8TimeFlag\_1=0; vGu16TimeCnt\_1=BLINK\_TIME\_1; //重装定时的时间 vGu8TimeFlag\_1=1; P0\_0=0; P0\_1=0; P0\_2=1; //第2个灯熄灭 P0\_3=0; P0\_4=0; P0\_5=0; P0\_6=0; P0\_7=0; Su8Step=3; //切换到下一个步骤,精髓语句! } break; case 3: if(0==vGu16TimeCnt\_1) //时间到 { vGu8TimeFlag\_1=0; vGu16TimeCnt\_1=BLINK\_TIME\_1; //重装定时的时间 vGu8TimeFlag\_1=1; P0\_0=0; P0\_1=0; P0\_2=0; P0\_3=1; //第3个灯熄灭 P0\_4=0; P0\_5=0; P0\_6=0; P0\_7=0; Su8Step=4; //切换到下一个步骤,精髓语句! } break; case 4: if(0==vGu16TimeCnt\_1) //时间到 { vGu8TimeFlag\_1=0; vGu16TimeCnt\_1=BLINK\_TIME\_1; //重装定时的时间 vGu8TimeFlag\_1=1; P0\_0=0; P0\_1=0; P0\_2=0; P0\_3=0; P0\_4=1; //第4个灯熄灭 P0\_5=0; P0\_6=0; P0\_7=0; Su8Step=5; //切换到下一个步骤,精髓语句! } break; case 5: if(0==vGu16TimeCnt\_1) //时间到 { vGu8TimeFlag\_1=0; vGu16TimeCnt\_1=BLINK\_TIME\_1; //重装定时的时间 vGu8TimeFlag\_1=1; P0\_0=0; P0\_1=0; P0\_2=0; P0\_3=0; P0\_4=0; P0\_5=1; //第5个灯熄灭 P0\_6=0; P0\_7=0; Su8Step=6; //切换到下一个步骤,精髓语句! } break; case 6: if(0==vGu16TimeCnt\_1) //时间到 { vGu8TimeFlag\_1=0; vGu16TimeCnt\_1=BLINK\_TIME\_1; //重装定时的时间 vGu8TimeFlag\_1=1; P0\_0=0; P0\_1=0; P0\_2=0; P0\_3=0; P0\_4=0; P0\_5=0; P0\_6=1; //第6个灯熄灭 P0\_7=0; Su8Step=7; //切换到下一个步骤,精髓语句! } break; case 7: if(0==vGu16TimeCnt\_1) //时间到 { vGu8TimeFlag\_1=0; vGu16TimeCnt\_1=BLINK\_TIME\_1; //重装定时的时间 vGu8TimeFlag\_1=1; P0\_0=0; P0\_1=0; P0\_2=0; P0\_3=0; P0\_4=0; P0\_5=0; P0\_6=0; P0\_7=1; //第7个灯熄灭 Su8Step=0; //返回到第0个步骤重新开始往下走,精髓语句! } break; } } //第2路跑马灯 void Led\_2\_Task(void) { /\* 疑点讲解(1): 这里第2路跑马灯的“Su8Step”与第1路跑马灯的“Su8Step”虽然同名,但是,因为它们是静态的局部变量,在两个不同的函数内部,是两个不同的变量,这两个变量所分配的RAM内存地址是不一样的,因此,它们虽然同名,但是不矛盾不冲突。 \*/ static unsigned char Su8Step=0; //加static修饰的局部变量,每次进来都会保留上一次值。 switch(Su8Step) { case 0: if(0==vGu16TimeCnt\_2) //时间到 { vGu8TimeFlag\_2=0; vGu16TimeCnt\_2=BLINK\_TIME\_2; //重装定时的时间 vGu8TimeFlag\_2=1; P1\_4=1; //第0个灯熄灭 P1\_5=0; P1\_6=0; P3\_3=0; Su8Step=1; //切换到下一个步骤,精髓语句! } break; case 1: if(0==vGu16TimeCnt\_2) //时间到 { vGu8TimeFlag\_2=0; vGu16TimeCnt\_2=BLINK\_TIME\_2; //重装定时的时间 vGu8TimeFlag\_2=1; P1\_4=0; P1\_5=1; //第1个灯熄灭 P1\_6=0; P3\_3=0; Su8Step=2; //切换到下一个步骤,精髓语句! } break; case 2: if(0==vGu16TimeCnt\_2) //时间到 { vGu8TimeFlag\_2=0; vGu16TimeCnt\_2=BLINK\_TIME\_2; //重装定时的时间 vGu8TimeFlag\_2=1; P1\_4=0; P1\_5=0; P1\_6=1; //第2个灯熄灭 P3\_3=0; Su8Step=3; //切换到下一个步骤,精髓语句! } break; case 3: if(0==vGu16TimeCnt\_2) //时间到 { vGu8TimeFlag\_2=0; vGu16TimeCnt\_2=BLINK\_TIME\_2; //重装定时的时间 vGu8TimeFlag\_2=1; P1\_4=0; P1\_5=0; P1\_6=0; P3\_3=1; //第3个灯熄灭 Su8Step=0; //返回到第0个步骤重新开始往下走,精髓语句! } break; } }