51单片机课设:模拟电梯控制系统的实现
基于51单片机的模拟电梯控制系统
利用51单片机模拟5层电梯控制系统,还原真实生活场景。当某层被按下呼梯按键(电梯厢外)时,电梯将运行到该楼层,同时步进电机模拟电梯运转,液晶显示屏实时显示楼层数及电梯运行方向,到达该楼层时电机停止,电梯开门,乘客进入电梯后按下目的楼层按键,电梯运行至目的楼层。同时设有消防呼叫功能,且在所有呼叫中,消防优先级最高,当消防呼叫按键被按下时,电梯就近平层停车,不再响应任何外呼叫信号。
一、系统功能
二、硬件电路原理图
结构框图如下:
电路图如下:
三、C语言实现

主要逻辑:
void main()
{
Speed = 20;
LCD1602_Init();
LCD1602_DisplayOneCharOnAddr(0,0,floor[lc-1]); //显示初始楼层
init(); //构造函数,初始化
while(1)
{
keyscan();
zhishideng();
if(flag==0) //电梯静止时
{
LCD1602_MoveToPosition(1,0); //显示位置移动到指定位置(第二行)
LCD1602_DisplayString(jz); //显示静止
shang[lc]=0;
xia[lc]=0;
nei[lc]=0; //按键初始化
n=lc ;
for(i=n+1;i<=5;i++)// 上行
{
keyscan();
zhishideng();
if(shang[i]==1||xia[i]==1||nei[i]==1)
{
flag=1;
break;
}
}
for(i=n-1;i>=1;i--)// 下行
{
keyscan();
zhishideng();
if(shang[i]==1||xia[i]==1||nei[i]==1)
{
flag=2;
break;
}
}
}
if(flag==1)
{
keyscan();
zhishideng();
LCD1602_MoveToPosition(1,0); //显示位置移动到指定位置(第二行)
LCD1602_DisplayString(up); //显示上升
UPUP();//步进电机正转
delay(200);
lc++;
LCD1602_DisplayOneCharOnAddr(0,0,floor[lc-1]); //显示楼层
if(shang[lc]==1||nei[lc]==1){ //上升一层后再次判断
shang[lc]=0;
nei[lc]=0;
zhishideng();
LCD1602_MoveToPosition(1,0); //显示位置移动到指定位置(第二行)
LCD1602_DisplayString(jz); //显示静止
delay(200);
}
if(xf == 1){
LCD1602_MoveToPosition(1,0); //显示位置移动到指定位置(第二行)
LCD1602_DisplayString(xiaofang); //显示out
while(1);
}
flag=0;
n=lc ;
for(i=n+1;i<=5;i++)
{
keyscan();
zhishideng();
if(shang[i]==1||xia[i]==1||nei[i]==1)
{
flag=1;
break;
}
}
if(flag==0||lc>=5)
{
n=lc ;
if(shang[n]==0&&nei[n]==0)
{
LCD1602_MoveToPosition(1,0); //显示位置移动到指定位置(第二行)
LCD1602_DisplayString(jz); //显示静止
}
xia[n]=0;
for(i=n-1;i>=1;i--)
{
keyscan();
zhishideng();
if(shang[i]==1||xia[i]==1||nei[i]==1)
{
flag=2;
break;
}
}
}
}
if(flag==2)
{
keyscan();
zhishideng();
LCD1602_MoveToPosition(1,0); //显示位置移动到指定位置(第二行)
LCD1602_DisplayString(down); //显示下降
DOWNDOWN();//步进电机反转
delay(200);
lc--;
LCD1602_DisplayOneCharOnAddr(0,0,floor[lc-1]); //显示楼层
if(xia[lc]==1||nei[lc]==1)
{
xia[lc]=0;
nei[lc]=0;
zhishideng();
LCD1602_MoveToPosition(1,0); //显示位置移动到指定位置(第二行)
LCD1602_DisplayString(jz); //显示静止
delay(200);
}
if(xf == 1){
LCD1602_MoveToPosition(1,0); //显示位置移动到指定位置(第二行)
LCD1602_DisplayString(xiaofang); //显示静止
while(1);
}
flag=0;
n=lc;
for(i=n-1;i>=1;i--)
{
keyscan();
zhishideng();
if(shang[i]==1||xia[i]==1||nei[i]==1)
{
flag=2;
break;
}
}
if(flag==0||lc<=1)
{
n=lc ;
if(xia[n]==0&&nei[n]==0)
{
LCD1602_MoveToPosition(1,0); //显示位置移动到指定位置(第二行)
LCD1602_DisplayString(jz); //显示静止
}
shang[n]=0;
for(i=n+1;i<=5;i++)
{
keyscan();
zhishideng();
if(shang[i]==1||xia[i]==1||nei[i]==1)
{
flag=1;
break;
}
}
}
}
}
}
键盘扫描函数:
void keyscan()
{
num=0;
P1=0xfe; //11111110
temp=P1;
temp=temp&0xf0; //11110000
while(temp!=0xf0) //有键被按下
{
delay(5);
temp=P1;
temp=temp&0xf0; //11110000
while(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xee:num=1; //11101110 第一行第一个按键
break;
case 0xde:num=2; //11011110 第一行第二个按键
break;
case 0xbe:num=3; //10111110 第一行第三个按键
break;
case 0x7e:num=4; //01111110 第一行第四个按键
break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
}
}
P1=0xfd; //11111101
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0) //11110000
{
delay(5);
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xed:num=5; //11101101 二行第一个
break;
case 0xdd:num=6; //11011101 二行第二个
break;
case 0xbd:num=7; //10111101 二行第三个
break;
case 0x7d:num=8; //01111101 二行第四个
break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
}
}
P1=0xfb;
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xeb:num=9; //三行一
break;
case 0xdb:num=10; // 三行二
break;
case 0xbb:num=11; // 三行三
break;
case 0x7b:num=12; //三行四
break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
}
}
P1=0xf7;
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xe7:num=13; // 四行一
break;
case 0xd7:num=14; //四行二
break;
case 0xb7:num=15; //四行三
break;
case 0x77:num=16; //四行四
break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
}
}
//红外遥控功能
if(irok) //如果接收好了进行红外处理
{
Ircordpro();
irok=0;
}
if(irpro_ok) //如果处理好后进行工作处理,如按对应的按键后显示对应的数字等
{
Ir_work();
}
switch(num)
{
case 1:shang[1]=1;
break;
case 2:shang[2]=1;
break;
case 3:shang[3]=1;
break;
case 4:shang[4]=1;
break;
case 5:xia[2]=1;
break;
case 6:xia[3]=1;
break;
case 7:xia[4]=1;
break;
case 8:xia[5]=1;
break;
case 9:nei[1]=1;
break;
case 10:nei[2]=1;
break;
case 11:nei[3]=1;
break;
case 12:nei[4]=1;
break;
case 13:nei[5]=1;
break;
case 14:
break;
case 15:
break;
case 16:alarm1=0;alarm2=1;while(1);
break;
}
}
变量声明:
unsigned char code floor[]="12345"; //楼层字符用于液晶屏显示
unsigned char code up[]="up "; //显示上升"up"
unsigned char code down[]="down"; //显示下降"down"
unsigned char code jz[]=" "; //到达目的楼层后清除up/down
unsigned char code xiaofang[]="out "; //消防呼叫显示
unsigned char Speed;//步进电机速度变量
uint xf=0;
uint shang[6]={0,0,0,0,0,0};
uint xia[6]={0,0,0,0,0,0};
uint nei[6]={0,0,0,0,0,0};
uint num,temp,flag=0,lc=1,i,n; //i,n是层数
电梯上升函数:
void UPUP(void)
{
unsigned int i = 128;
while(i--){
Coil_A1
delay(Speed);
Coil_AB1 //遇到Coil_AB1 用{A1=1;B1=1;C1=0;D1=0;}代替
delay(Speed); //改变这个参数可以调整电机转速
Coil_B1 //数字越小,转速越大,力矩越小
delay(Speed);
Coil_BC1
delay(Speed);
Coil_C1
delay(Speed);
Coil_CD1
delay(Speed);
Coil_D1
delay(Speed);
Coil_DA1
delay(Speed);
Coil_OFF
}
}
电梯下降函数类似……
四、结果
下降中:
按下消防按键:
欢迎大佬提出优化方案!
如有错漏之处,敬请指正,不吝赐教。