先看看效果
具体思路
实现流水灯的效果其实就是控制相应的I/O口,以P2为例,通过有规律的改变P2各I/O口的状态就可实现相应规律的流水灯效果,这其中需要用到与、或、异或、左移、右移等操作。
流水灯向左闪烁点亮就是将P2最低位的1不断左移,每次左移其最低位都补0且延时一段时间,所以在初始时P2可赋值0x01。
流水灯向右闪烁点亮就是将P2最高位的1不断右移,每次右移其最高位都补0且延时一段时间,所以在初始时P2可赋值0x80。
流水灯逐个向左点亮是说在初始时,P2赋值为0x01,并将P2整体左移,每移动一次就将最低为置为1且延时一段时间。
流水灯逐个向右点亮是说在初始时,P2赋值为0x80,并将P2整体右移,每移动一次就将最高为置为1且延时一段时间。
流水灯两端向内点亮是结合了逐个向左和逐个向右点亮的思想,P2 低4位 逐个向左点亮, 高4位逐个向右点亮。
流水灯由内向两端熄灭同样是结合了逐个向左和逐个向右点亮的思想,P2 低4位逐个向右熄灭,高4位逐个向左熄灭。
流水灯以两个灯为主体向左移动点亮其本质也就是一个灯向左移动点亮。
程序
#include <reg51.h>#define Led P2unsigned int time=0; //延时时长变量void InitTimer0(void) //10ms
{TMOD = 0x01; //定时器模式1//赋值TH0 = 0xDC;TL0 = 0x00;EA = 1; //开总中断ET0 = 1; //开定时器0中断
}void delay(unsigned int ms_10) //延时函数
{time=ms_10; //给time赋予具体延时时间的数值TR0 = 1; //打开定时器0while(time); //等待延时结束TR0 = 0; //关闭定时器0
}void light_water() //流水灯函数
{int i=0,Led_H=0,Led_L=0,temp=0x06,num=0; //Led_H存储P2高8位Led_L存储P2低8位Led=0x01;delay(10);//100msfor(;i < 7;i++) //单个左移{Led=Led<<1; //P2数值左移delay(10);//100ms }for(i=0;i < 7;i++) //单个右移{Led=Led>>1; //P2数值右移delay(10);//100ms }for(i=0;i < 7;i++) //依次向左点亮{Led=Led<<1|0x01; //P2数值左移并将最低位置为1delay(10);//100ms }for(i=0;i < 7;i++) //依次向右点亮{Led=Led>>1; //P2数值右移,依次将位1清零delay(10);//100ms }Led=0x00;for(i=0;i < 7;i++) //两端向内依次点亮{Led_L=Led<<1|0x01&0x0f; //取出P2的低4位,并将其左移最低位置1Led_H=((Led&0xf0)>>1)^0x80; //取出P2的高4位,并将其右移最高位置1Led=Led|Led_L; //将低4位赋予P2Led=Led|Led_H; //将高4位赋予P2delay(10);//100ms }for(i=0;i < 7;i++) //由内向两端依次点亮{Led_L=(Led&0x0f)>>1; //取P2低4位并右移Led_H=(Led&0xf0)<<1; //取P2高4位并左移Led=Led&Led_L; //将低4位赋予P2Led=Led^Led_H; //将高4位赋予P2delay(10);//100ms }Led=0x00;for(i=0;i < 10;i++) //依次向左点亮2个灯{num=Led<<1|0x01; //P2数值左移并最低位置1if(num>=0x06) //第2、3个灯亮后,以2个灯为主体向左移动{Led=num&temp;temp=temp<<1; }else Led=num;delay(7);//100ms }Led=0x00;temp=0xc0;for(i=0;i < 10;i++) //依次向右点亮2个灯{num=Led>>1|0x80; //将P2数值右移并最高位置1if(num>=temp) //第6、7个灯亮时以两个灯为整体向右移动{Led=num&temp;temp=temp>>1;}elseLed=num;delay(7);//100ms }
}void main(void)
{InitTimer0(); //定时器初始化while(1){light_water();}
}void Timer0Interrupt(void) interrupt 1
{TH0 = 0xDC;TL0 = 0x00;time--;if(time < 0){time = 0; //time为0时不在减}
}