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

    电梯下降函数类似……

    四、结果

    下降中:
    测试
    按下消防按键:

    欢迎大佬提出优化方案!
    如有错漏之处,敬请指正,不吝赐教。

    物联沃分享整理
    物联沃-IOTWORD物联网 » 51单片机课设:模拟电梯控制系统的实现

    发表评论