51单片机课设——模拟电梯控制系统

基于51单片机的模拟电梯控制系统

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

一、系统功能

  • 矩阵键盘模拟电梯内外按键。其中8个按键为电梯厢外按键,作为电梯呼叫信号,分别为“1楼上、2楼上、3楼上、4楼上、2楼下、3楼下、4楼下、5楼下”。其中5个按键为电梯厢内目的楼层按键。1个按键为报警功能。
  • LCD1602液晶显示屏实时显示当前楼层以及电梯运行方向“up/down”。
  • 28BYJ48步进电机模拟电梯运转,电梯上行为正转,电梯下行为反转。
  • 外部中断系统(外部中断1)触发消防呼叫,且在所有呼叫中,消防优先级最高,当消防呼叫按键被按下时,电梯就近平层停车,电梯开门,乘客出来,并不再响应任何外呼叫信号。(显示out)
  • 红外遥控功能 :可以利用遥控器模拟矩阵键盘所有按键。(仅拓展供娱乐QWQ)
  • 报警功能,电梯紧急停止,其他所有按键失效。

二、硬件电路原理图

结构框图如下:
结构框图
电路图如下:
电路图

三、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
	}
}

电梯下降函数类似……

四、结果

下降中:
测试
按下消防按键:
在这里插入图片描述
欢迎大佬提出优化方案!
如有错漏之处,敬请指正,不吝赐教。

  • 43
    点赞
  • 315
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值