最近突然碰到小鸟归巢问题,网上也基本上没有很好的解决办法,现在自己也花费几个小时得到了三种实现方法。
- 单循环
#include <REGX52.H>
void Delay(unsigned int t) //@11.0592MHz,5ms延迟器
{
unsigned char i, j;
while(t--){
i = 54;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void main(){
unsigned char x=128; //用于控制j的值
unsigned char i,j=1; // i为循环次数,j控制进行流水的位数
unsigned char n=8; //表示8位流水灯
P2 = 0xFE; //8位LED的初始状态
while(1)
{
for(i=0;i<n;i++){
Delay(20); //先延迟100ms用于显示初始状态
j=j*2; //第j个LED亮
if(j<=x){ //j要小于等于x的值,实现后面高位恒亮
P2=(P2-j)+j/2;
}
if(j==x){
P2=P2-1;
x=x/2;
if(P2==0x00){ //全部亮时从头开始
x=128;
Delay(20);
P2=0xFE;
}
j=1;
}
/*
上面两个if进行解释一下,例如第一次j=2,j的二进制为0000 0010,
j/2等于1,二进制为0000 0001,初始P2=0xFE=1111 1110那么
P2=(P2-0000 0010)+0000 0001=1111 1101,从而实现流水灯
以此类推,当满足j==x的条件时,这时候while将要执行第一次for循环
这时x=128,j=128,P2=1011 1111,j/2等于64,
执行j==x后,P2=(P2-1000 0000)+0100 0000=0111 1111
while第二次执行for循环后,下面条件j==x时,根据上一步有P2=0111 1111
P2=P2-1=0111 1111-1=0111 1110,保留了最高位显示
这时x=x/2=64,j只能到64,因此当第一个if到j==x时,P2=0011 1111
执行第二个if时,P2=P2-1=0011 1110,保留了最高位和次高位,以此类推,
从而实现小鸟归巢
*/
}
}
}
- 双循环
#include <REGX52.H>
void Delay(unsigned int t) //@11.0592MHz,5ms延迟器
{
unsigned char i, j;
while(t--){
i = 54;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void main(){ //这个方法是上一个方法的改进
unsigned char x=128;
unsigned char i,j=1,k=0;
P2 = 0xFE;
while(1)
{
for(k=7;k>0;k--){ //控制进行流水灯的位数,从而实现保留高位恒亮
for(i=0;i<k;i++){ //实现流水灯
Delay(20);
j=j*2;
if(j<=x){
P2=(P2-j)+j/2;
}
if(i==k-1){
P2=P2-1;
j=1;
}
if(P2==0x00){ //当P2全亮时从头开始
Delay(20);
P2=0xFE;
}
}
}
}
}
- 双向移位法
#include <REGX52.H>
#include <INTRINS.H>
void Delay(unsigned int t) //@11.0592MHz,5ms延迟器
{
unsigned char i, j;
while(t--){
i = 54;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void main()
{
unsigned char i,j=0,P=0xFF;
P2 = 0xFE;
while(1)
{
for(j=8;j>0;j--){
for(i=0;i<j-1;i++){
Delay(10);
P2=(P2<<1)+1;
P2=P2&P;
}
Delay(10);
P=(P>>1)-1;
P2=P2&P;
P=P+1;
}
P2 = 0xFE;
P=0xFF;
}
}
- 位数拼凑法
接下来这个方法简单粗暴,直截了当,通过位移函数和移位符号相结合就可实现
#include <REGX52.H>
#include <INTRINS.H>
void Delay(unsigned int t) //@11.0592MHz,5ms延迟器
{
unsigned char i, j;
while(t--){
i = 54;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void main(){ //这个方法简单粗暴
unsigned char i,k=0;
while(1)
{
for(k=8;k>0;k--){ //控制流水灯位数,并且保留高位恒亮
for(i=0;i<k;i++){ //实现流水灯效果的循环
P2 = _crol_(0xFE,i);//实现流水灯效果
P2 = (0xFF>>(8-k))&(P2);//通过(0xFF>>(8-k))保留高位恒亮
Delay(20);
}
}
}
}
觉得不错的话点个赞吧~~~~