我的电梯模拟实验里,在按下多个电梯楼层那个部分出了点问题,就是run()函数那里的count>2部分,应该是逻辑出了问题,导致当它遍历完已经按下的楼层后继续进行流水灯,到最高部分,不能继续按按键,但我看了半天也不知道问题出在哪里,可以帮我瞅一眼
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define M 8
unsigned char LED; //LED当前状态
unsigned char begin; //LED灯初始状态
unsigned char tmp; //当前楼层只有其亮时的亮灯状态
unsigned char flag; //当前输入的目的楼层
unsigned char first; //初始楼层数
unsigned char b[M];
sbit Max7219_pinCS = P2^5;
sbit Max7219_pinDIN = P2^6;
sbit Max7219_pinCLK = P2^7;
sbit beep=P2^3;
uchar code disp[8][8]={
{0x18,0x8,0x8,0x8,0x8,0x8,0x8,0x3E},//1
{0x7C,0x44,0x44,0x8,0x10,0x20,0x40,0x7C},//2
{0x7C,0x4,0x4,0x7C,0x4,0x4,0x4,0x7C},//3
{0x22,0x22,0x22,0x22,0x3E,0x2,0x2,0x2},//4
{0x20,0x3E,0x20,0x20,0x3E,0x2,0x2,0x3E},//5
{0x3E,0x22,0x20,0x20,0x3E,0x22,0x22,0x3E},//6
{0x7E,0x4,0x8,0x10,0x20,0x20,0x20,0x20},//7
{0x7C,0x44,0x44,0x44,0x7C,0x44,0x44,0x7C},//8
};
void delay1ms(uint n) //延时n毫秒
{
uint i,j;
for(i=n;i>0;i--)
for(j=112;j>0;j--);
}
void Write_Max7219_byte(uchar DATA) //向MAX7219写入字节
{
uchar i;
Max7219_pinCS=0;
for(i=8;i>=1;i--)
{
Max7219_pinCLK=0;
Max7219_pinDIN=DATA&0x80;
DATA=DATA<<1;
Max7219_pinCLK=1;
}
}
void Write_Max7219(uchar address,uchar dat) //向MAX7219写入数据
{
Max7219_pinCS=0;
Write_Max7219_byte(address); //写入地址,即数码管编号
Write_Max7219_byte(dat); //写入数据,即数码管显示数字
Max7219_pinCS=1;
}
//初始化MAX7219
void Init_MAX7219(void)
{
Write_Max7219(0x09, 0x00); //译码方式:BCD码:0x07;不译码,直接存字形码:0x00
Write_Max7219(0x0a, 0x03); //亮度
Write_Max7219(0x0b, 0x07); //扫描界限;8个数码管显示
Write_Max7219(0x0c, 0x01); //掉电模式:0,普通模式:1
Write_Max7219(0x0f, 0x00); //显示测试:1;正常显示:0
}
int check() //检查当前8个LED中灯亮起的数量及位置
{
uchar i,j=0,count=0;
for(i=1;i<9;i++)
{
if((0x01&LED>>(i-1))==0)
{
count++;
b[count]=9-i;
}
}
/*for(j=0;j<8;j++)
{
a[j]=(LED>>(7-j))&1;//将当前的的LED的每一位存入a数组中
}
for(i=0;i<8;i++)
{
if(a[i]==0) //当前灯亮
{
count++; //灯的数量
b[i]=i+1; //b数组里非零数表示第i+1层是目标楼层
}
}*/
return count;
}
void display(uchar n,uchar m) //当前输入楼层的灯亮情况n以及其所对应的楼层数m
{
uchar i;
flag=m; //flag所输入的目的楼层
tmp=n; //当前楼层只有其亮时的亮灯状态
for(i=1;i<9;i++)
{
Write_Max7219(i,disp[flag-1][i-1]);
}
P1=~(P1^tmp); //此时LED亮起,表示输入楼层的对应灯亮以及当前所在楼层亮的情况*/ P1=1101 0111
LED=P1; //
}
void run() //电梯运行
{
uchar i,j,x,y,q,p,z,m,n;
uint t=0;
uchar count,smaller,s=0;
count=check();
if(count==1) return;
if(count==2)
{
if(first<flag)
{
P1=begin; //p1 1101 1111
for(i=0;i<8;i++)
{
delay1ms(500);
P1=P1>>1;
P1=P1|0x80;
if(P1==tmp) break; //表示已到达目的层
}
for(j=1;j<9;j++)
{
Write_Max7219(j,disp[flag-1][j-1]);
}
begin=P1;//begin 1101 1111
first=flag;
}
else if(first>flag)
{
P1=begin; //p1 1101 1111
for(x=0;x<8;x++)
{
delay1ms(500);
P1=P1<<1;
P1=P1|0x01;
if(P1==tmp) break; //表示已到达目的层
}
for(y=1;y<9;y++)
{
Write_Max7219(y,disp[flag-1][y-1]);
}
begin=P1;//begin 1101 1111
first=flag;
}
}
if(count>2)
{
for(p=count-1;p>0;p--)
{
if(b[p]>first)
{
P1=begin;
for(q=0;q<8;q++)
{
first++;
delay1ms(500);
P1=P1>>1;
P1=P1|0x80;
if(first==b[p]) break;
}
for(m=1;m<9;m++)
{
Write_Max7219(m,disp[b[p]-1][m-1]);
}
delay1ms(3000);
begin=P1;
first=b[p];
}
if(b[p]<first)
{
smaller=b[p];
t=1;
continue;
}
}
if(p==0&&t==1)
{
begin=P1;
for(z=0;z<8;z++)
{
first--;
delay1ms(500);
P1=P1<<1;
P1=P1|0x01;
if(smaller==first) break;
}
for(n=1;n<9;n++)
{
Write_Max7219(n,disp[first-1][n-1]);
}
delay1ms(3000);
begin=P1;
first=smaller;
}
}
}
void keyscan4x4()
{
uchar temp,key,index;
///////////////第一行扫描///////////////////
P3=0xfe;//1111 1110 让P3.0口输出低
temp=P3;
temp=temp&0xf0;//1111 0000 位与操作 屏蔽后四位
if(temp!=0xf0)
{
delay1ms(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee: //1110 1110 S1被按下
key=0xf7;
index=5;
break;
case 0xde: //1101 1110 S2被按下
key=0xfb;
index=6;
break;
case 0xbe: //1011 1110 S3被按下
key=0xfd;
index=7;
break;
case 0x7e: //0111 1110 S4被按下
key=0xfe;
index=8;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
display(key,index);
}
}
///////////////第二行扫描///////////////////
P3=0xfd;//1111 1101 让P3.1口输出低
temp=P3;
temp=temp&0xf0;//1111 0000 位与操作 屏蔽后四位
if(temp!=0xf0)
{
delay1ms(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xed: //1110 1101 S5被按下
key=0x7f;
index=1;
break;
case 0xdd: //1101 1101 S6被按下
key=0xbf;
index=2;
break;
case 0xbd: //1011 1101 S7被按下
key=0xdf;
index=3;
break;
case 0x7d: //0111 1101 S8被按下
key=0xef;
index=4;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
display(key,index);
}
}
///////////////第三行扫描///////////////////
P3=0xfb;//1111 1011 让P3.2口输出低
temp=P3;
temp=temp&0xf0;//1111 0000 位与操作 屏蔽后四位
if(temp!=0xf0)
{
delay1ms(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xeb: //1110 1011 S9被按下
break;
case 0xdb: //1101 1011 S10被按下
break;
case 0xbb: //1011 1011 S11被按下
break;
case 0x7b: //0111 1011 S12被按下
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
}
///////////////第四行扫描///////////////////
P3=0xf7;//1111 0111 让P3.0口输出低
temp=P3;
temp=temp&0xf0;//1111 0000 位与操作 屏蔽后四位
if(temp!=0xf0)
{
delay1ms(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xe7: //1110 0111 S13被按下
run();
break;
case 0xd7: //1101 0111 S14被按下
break;
case 0xb7: //1011 0111 S15被按下
break;
case 0x77: //0111 0111 S16被按下
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
}
}
void main()
{
uchar i;
P1=0x7f; //0111 1111
first=1; //first表示当前楼层数
begin=P1; //初始电梯状态
delay1ms(50);
Init_MAX7219();
for(i=1;i<9;i++)
{
Write_Max7219(i,disp[0][i-1]);
}
delay1ms(1000);
while(1)
{
keyscan4x4();
}
}
首先,你的代码很整洁,这使得理解它的功能变得容易。但我看到了一个可能的问题,它出现在你的 run
函数中。在处理电梯运行时,你根据不同楼层按键的数量(count
)来确定电梯的行为。在处理 count>2
的情况时,你使用了一个循环去找到高于当前楼层(first
)的目标楼层(b[p]
),然后电梯向上运行到这些楼层。这部分看起来没什么问题,但是在找到低于当前楼层的目标楼层时,你将这个楼层存入变量 smaller
,并设置 t=1
,以标记找到了一个低于当前楼层的目标。
这个逻辑的问题在于,你没有考虑到可能有多个低于当前楼层的目标。你的代码只会记住最后一个找到的低楼层目标,并在循环结束后运行到那个楼层。这意味着如果有多个低楼层的目标,电梯可能会跳过其中的一些。
解决这个问题的一种可能的方法是在找到一个低于当前楼层的目标时就立即让电梯运行到那个楼层,而不是等到循环结束后再运行。这可以通过在找到低楼层目标时添加一段运行电梯的代码来实现。你可能需要对你的代码做一些修改,以确保在每次电梯运行到一个新的楼层时都会更新 first
和 begin
的值。
这只是我从你的代码中找到的可能的问题,并且我也假设了你的电梯行为应该是这样的:当有多个目标楼层时,电梯应该先运行到所有高楼层的目标,然后再运行到所有低楼层的目标。如果你的电梯行为应该不同,那么你可能需要用不同的方式来修改你的代码。