点灯嘛,谁不会啊,若是10年前stc89C52的芯片,连个锁存器都没得,直接对P0口操作就直接点亮了 ,而对应蓝桥杯的stc15F2K60芯片而言,无非就是多了锁存器,初始化P0口,P0口给对应的灯赋值,开锁存器送信号再关锁存器不就行了。是的,这样就行了。
引言:(一次性点亮一个灯)
void LedRunning(u8 s){
if(s>7)return ;
P0=0xff;
P2=P2&0x1f|0x80;
P0=~(1<<s);//s为0-7对应点亮L1到L8,低电平有效再取反
P2&=0x1f;
}
而往往赛题中都是有可能出现一次性点亮多个灯,比如xxx模式下开某个灯 ,xxx模式下关闭某个灯,温度大于xxx时开某个灯,低于多少时又开xx灯或是关xxx灯,电位器rb2值为xxx时开某个灯,光敏电阻读出来为xxx值时又对led灯操作。
假设,一种模式只对应会开一个灯,上述的假设就会出现3-4个灯同时点亮的情况下,若是用引言里的函数一次性点亮一个灯的函数去一一操作,不够精致。
&如果你用引言里的一次性点亮一个灯
不稳定和逻辑不正确的问题:
若是程序运行地很快,你也是一个灯接着一个灯地点亮,如果你直接放在while里跑,灯绝对会闪烁而显得不稳定,如果你隔30ms去点亮一次,那灯也是一个接一个地点亮,而点灯的时间又很短,所以最后灯显示的是最后一次点亮的那个灯(也就是只有一个灯亮)
&如果你通过判断几个灯的状态来得到合理的P0的值然后一次性点亮
多重条件判断的问题:
一个灯两种状态,三个灯的状态判断就有2*2*2为2^3为8种,那你得写8个if来判断,然后得到正确得P0值(P0=第n个灯&第m个灯&第~个灯)再一次性同时对三个灯进行操作,代码显得冗余繁琐。
我的答案:
鄙人给出得一个解决办法:先读题,看题目中总共会用到那几个灯,判断同时最多有几个灯会亮
然后建立一个可读的数组存所用的那几个灯的一次性点亮所对应的P0值,和灯熄灭的状态0xff。
例如比如我一次性可能点亮8个灯中的任意灯(所亮灯的范围为全部范围)
u8 LED[]={0xff,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
然后再建立一个维护LED状态的动态数组
u8 LEDDT[]={0,0,0,0,0,0,0,0,0};//习惯性可以多一位,从数组序号映射到第几个灯
这样,据题目要求,跟据标志改动态数组LEDDT[ ]的值就行了,比如
//点亮 1 2 3 5
LEDDT[1]=1;
LEDDT[2]=2;
LEDDT[3]=3;
LEDDT[4]=0;
LEDDT[5]=5;
LEDDT[6]=0;
LEDDT[7]=0;
LEDDT[8]=0;
由于我定义动态数组时数组的长度是同一时刻所亮灯的最大数目+1,就看起来更加美观,嘿嘿。
若是为了节省内存,同一时刻最多亮8个灯,那LEDDT [ ]的大小就为 8 以LEDDT的数组序号 0-7映射第1-8个灯的状态,若是同时只亮三个灯,那就以LEDDT[ ] 0 -2的数组序号去映射LED[ ]x y z 的灯的状态如一下伪代码:
LEDDT[0]=X;//第x盏灯
LEDDT[1]=Y;//第y盏灯
LEDDDT[2]=Z;//第z盏灯
//熄灭则让其为0映射到LED的0xff
最后无脑定时执行
//同一时刻最多能亮起三个任意灯
void LedRunning(){
P0=0xff;
P0=LED[LEDDT[0]]&LED[LEDDT[1]]&LED[LEDDT[2];
P2=P2&0x1f|0x80;
P2=P2&0x1f;
}
若是题目要求xxx灯闪烁,怎么做,简单,改LEDDT[ ]不就行了。
-----------------------------------------分割线--------------------------------------
从中午下课写博客到此没吃饭,应我那位不会点灯的朋友要求,忍辱负重写下这篇博客。
此时13:13,写完吃饭!生活啊,总要有些不一样的~