找回密码
 注册

QQ登录

只需一步,快速开始

搜索

51单片机8层电梯程序(传感器版+定时模拟版)Proteus仿真

[复制链接]
山海致远 发表于 2020-1-22 23:38:20 | 显示全部楼层 |阅读模式
第一个版本:8层楼梯传感器版
第二个版本:8层楼梯定时模拟版
8层楼梯传感器版.zip (125.29 KB)
8层楼梯定时模拟版.zip (125.33 KB)
8层楼梯传感器版仿真
1.png
  1. /*******************电梯主程序**********************/

  2. #include "reg51.h"
  3. #include "intrins.h"

  4. /******************移植部分代码*************************/
  5. sbit DOOR=P3^5;
  6. sbit DlevMotor_P=P3^6; //电梯电机正极
  7. sbit DlevMotor_N=P3^7; //电梯电机负极
  8. #define SEGPort    P0
  9. #define KeyPort_X  P1
  10. #define KeyPort_Y  P2
  11. /******************************************************/


  12. #define u8  unsigned char
  13. #define u16 unsigned int
  14.         
  15. #define MaxFloor   8

  16. #define FloorStayTime 40        //单位:50ms
  17. #define DoorStayTime  2   //单位:S

  18. #define TRUE  1
  19. #define FALSE 0

  20. #define Null  0  
  21. #define STOP  1
  22. #define UP    2
  23. #define DOWN  3
  24. #define Dlev_UP    DlevMotor_P=0;DlevMotor_N=1  //低电平有效
  25. #define Dlev_DOWN  DlevMotor_P=1;DlevMotor_N=0  //低电平有效
  26. #define Dlev_STOP  DlevMotor_P=1;DlevMotor_N=1  //低电平有效

  27. #define OPEN  1  
  28. #define CLOSE 0
  29. #define DOOR_Open  DOOR=OPEN
  30. #define DOOR_Close DOOR=CLOSE


  31. typedef struct
  32. {
  33.         u8 DlevRunning;
  34.   u8 CurrentFloor;
  35.         u8 Direction;
  36.         u8 FloorCallTable[MaxFloor+1];//数组[0]不用,从[1]开始使用
  37.         u8 FloorTimerCount;        
  38.         u8 ArriveFlag;  //到达楼层信号(用于停止或在前一楼层提前加减速)
  39.         u8 FreeFlag;        
  40. }TYPEDEF_DLEVSTATE;
  41. TYPEDEF_DLEVSTATE DlevState;


  42. u8 code SEG_NUM[]={0x3f,0x06,0x5b,0x4f,0x66,0x6D,0x7D,0x07,0x7f,0x6f};   //SEG数码管段码  0~9
  43. u8 Timer_Second;
  44. u16 TimerCount;
  45. u8 RICount=0;
  46. u8 RIOver_Flag=0;
  47. u8 ExternKey[2]={0}; //外部按键按下信息
  48. u8 FloorCallTableBUFF[MaxFloor+10]={0};
  49. u8 KeyPressFlag=0;

  50. void delay_ms(u16 xms);
  51. void delay_s(u8 xs);
  52. void EXTI0_Init(void);
  53. void Timer0_Init(void);
  54. void USART_Configure(u16 BaudRate);
  55. u8 KeyScan(void);
  56. void KeyDatHandle(u8 key);
  57. void WaitDoorOpen(u8 ts);
  58. void WaitDoorClose(u8 ts);
  59. void SEG_Display(u8 segnum);
  60. void DlevWorkState(u8 state);
  61. void Elevator(void);
  62. u8 FloorCall_UP(u8 floorside);
  63. u8 FloorCall_DOWN(u8 floorside);
  64. void FLOORCALLCHECK(void);
  65. void SYSYEM_INIT(void);


  66. void delay_ms(u16 xms)
  67. {
  68.         u8 i;
  69.         u16 t;
  70.   for(t=xms;t>0;t--)
  71.           for(i=112;i>0;i--);
  72. }

  73. void delay_s(u8 xs)
  74. {
  75.    TimerCount=0;
  76.          Timer_Second=0;
  77.    while(Timer_Second<xs);        
  78. }

  79. void EXTI0_Init(void)
  80. {
  81.   EA = 1;  
  82.         IT0= 1; //下降沿触发
  83.         EX0= 1;
  84. }

  85. void EXTI1_Init(void)
  86. {
  87.   EA = 1;  
  88.         IT1= 1; //下降沿触发
  89.         EX1= 1;
  90. }

  91. void Timer0_Init(void)
  92. {
  93.         TMOD |= 0x01;  
  94.   TH0=(65536-50000)/256;
  95.         TL0=(65536-50000)%256;
  96.         EA = 1;
  97.         ET0 = 1;
  98.         TR0 = 1;
  99. }


  100. void USART_Configure(u16 BaudRate)
  101. {
  102.         u8 TH1_Dat;
  103.         
  104.   switch(BaudRate)
  105.         {
  106.           case 1200:  TH1_Dat=0xE8; break;
  107.                 case 2400:  TH1_Dat=0xF4; break;
  108.                 case 4800:  TH1_Dat=0xFA; break;
  109.                 case 9600:  TH1_Dat=0xFD; break;
  110.                 case 14400: TH1_Dat=0xFE; break;
  111.         }
  112.         TMOD |= 0x20;
  113.         SCON |= 0x50;
  114.         TH1 = TH1_Dat;
  115.         TL1 = TH1;
  116.         PCON |= 0x00;
  117.         EA = 1;
  118.         ES = 1;
  119.         TR1 = 1;  
  120. }



  121. u8 KeyScan(void)
  122. {
  123.         u8 keynum;
  124.   
  125.         KeyPort_Y=0x00;
  126.         KeyPort_X=0xFF;
  127.         _nop_(); _nop_(); _nop_(); _nop_();
  128.         if(KeyPort_X!=0xFF)
  129.         {
  130.          delay_ms(10);
  131.          if(KeyPort_X!=0xFF)
  132.          {
  133.                  switch(KeyPort_X)
  134.                  {
  135.                          case 0x7F: keynum=1;   break;
  136.                          case 0xBF: keynum=9;   break;
  137.                          case 0xDF: keynum=17;  break;
  138.                          case 0xEF: keynum=25;  break;
  139.                          case 0xF7: keynum=33;  break;
  140.                          case 0xFB: keynum=41;  break;
  141.                          case 0xFD: keynum=49;  break;
  142.                          case 0xFE: keynum=57;  break;
  143.                  }
  144.                  KeyPort_Y=0xFF;
  145.                  KeyPort_X=0x00;
  146.                  _nop_(); _nop_(); _nop_(); _nop_();
  147.                  if(KeyPort_Y!=0xFF)
  148.                  {
  149.                          switch(KeyPort_Y)
  150.                          {
  151.                                  case 0xFE: keynum=keynum+0;  break;
  152.                                  case 0xFD: keynum=keynum+1;  break;
  153.                                  case 0xFB: keynum=keynum+2;  break;
  154.                                  case 0xF7: keynum=keynum+3;  break;
  155.                                  case 0xEF: keynum=keynum+4;  break;
  156.                                  case 0xDF: keynum=keynum+5;  break;
  157.                                  case 0xBF: keynum=keynum+6;  break;
  158.                                  case 0x7F: keynum=keynum+7;  break;
  159.                          }
  160.                  }
  161.                  KeyPort_Y=0x00;
  162.    }
  163.         }
  164.         else keynum=0;
  165.         return keynum;
  166. }

  167. void KeyDatHandle(u8 key)
  168. {
  169.         if(key==0)
  170.         {
  171.         
  172.         }
  173.         else
  174.         if(key<=MaxFloor) //楼梯内的楼层选择按键
  175.         {
  176.                 if(key>DlevState.CurrentFloor) DlevState.FloorCallTable[key]=UP;
  177.                 else
  178.                 if(key<DlevState.CurrentFloor) DlevState.FloorCallTable[key]=DOWN;
  179.         }
  180.         else
  181.         if((key<=MaxFloor*2)&&(key>MaxFloor+1))  //每个楼层门口外的向下按键(底楼按向下无效)
  182.         {
  183.                  DlevState.FloorCallTable[key-MaxFloor]=DOWN;
  184.         }
  185.         else
  186.         if(key<MaxFloor*3) //每个楼层门口外的向上按键(顶楼按向上无效)
  187.         {
  188.                  DlevState.FloorCallTable[key-MaxFloor*2]=UP;
  189.         }
  190.         else
  191.         if(key==MaxFloor*3+1)  //开门
  192.         {
  193.                 if(DlevState.DlevRunning==FALSE)
  194.                 {
  195.                   if(DOOR==CLOSE) DOOR_Open;
  196.                 }
  197.         }
  198.         else
  199.         if(key==MaxFloor*3+2) //关门
  200.         {
  201.                 if(DOOR==OPEN)
  202.                 {
  203.                         DOOR_Close;
  204.                         DlevState.FloorTimerCount=0;         //计时器清0
  205.                 }
  206.         }
  207. }

  208. void WaitDoorOpen(u8 ts)
  209. {
  210.         DOOR_Open;
  211.         delay_s(ts);
  212. }

  213. void WaitDoorClose(u8 ts)
  214. {
  215.         DOOR_Close;
  216.         delay_s(ts);
  217. }

  218. void SEG_Display(u8 segnum)
  219. {
  220.   SEGPort=~SEG_NUM[segnum];
  221. }

  222. void DlevWorkState(u8 state)
  223. {
  224.   if(state==UP)
  225.         {
  226.                 Dlev_UP;
  227.                 DlevState.DlevRunning=TRUE;
  228.         }
  229.         else
  230.         if(state==DOWN)
  231.         {
  232.                 Dlev_DOWN;
  233.                 DlevState.DlevRunning=TRUE;
  234.         }
  235.         else
  236.         if(state==STOP)
  237.         {
  238.                 Dlev_STOP;
  239.                 DlevState.DlevRunning=FALSE;
  240.         }
  241.         SEG_Display(DlevState.CurrentFloor);                //数码管显示
  242. }
  243.         
  244. void Elevator(void)
  245. {
  246.         if((DOOR==OPEN)||(DlevState.FreeFlag==TRUE)) DlevWorkState(STOP);        
  247.   else
  248.         DlevWorkState(DlevState.Direction);        
  249.         
  250.         if(DlevState.Direction==UP)  //电梯正在向上运行的情况
  251.         {
  252.                 if(DlevState.CurrentFloor<=MaxFloor)  //扫描呼叫列表中的向上方向的呼叫楼层
  253.                 {
  254.                          if(DlevState.FloorCallTable[DlevState.CurrentFloor]==UP) //到达目标楼层,停下开门5秒
  255.                          {
  256.                                  DlevState.FloorCallTable[DlevState.CurrentFloor]=Null; //到达相应的楼层从向上列表中清除                                         
  257.                                  DlevState.FreeFlag=TRUE; //到达楼层,暂停进入空闲状态                                 
  258.                                  DlevWorkState(STOP);
  259.                            WaitDoorOpen(DoorStayTime);
  260.                                  delay_s(2*DoorStayTime);       //保持门开2秒让人进出
  261.                                  WaitDoorClose(DoorStayTime);
  262.                                  DlevWorkState(DlevState.Direction);
  263.                                  DlevState.FreeFlag=FALSE; //离开楼层,退出空闲状态
  264.                                  DlevState.FloorTimerCount=0;         //计时器清0
  265.                          }                 
  266.                 }               
  267.         }
  268.         else
  269.         if(DlevState.Direction==DOWN)  //电梯正在向下运行的情况
  270.         {
  271.                 if(DlevState.CurrentFloor>=1)  //扫描呼叫列表中的向下方向的呼叫楼层
  272.                 {
  273.                          if(DlevState.FloorCallTable[DlevState.CurrentFloor]==DOWN) //到达楼层,停下开门5秒
  274.                          {        
  275.          DlevState.FloorCallTable[DlevState.CurrentFloor]=Null; //到达相应的楼层从向下列表中清除        
  276.                                  DlevState.FreeFlag=TRUE; //到达楼层,暂停进入空闲状态                 
  277.                                  DlevWorkState(STOP);
  278.                            WaitDoorOpen(DoorStayTime);
  279.                                  delay_s(2*DoorStayTime);       //保持门开2秒让人进出
  280.                                  WaitDoorClose(DoorStayTime);
  281.                                  DlevWorkState(DlevState.Direction);
  282.                                  DlevState.FreeFlag=FALSE; //离开楼层,退出空闲状态
  283.                                  DlevState.FloorTimerCount=0;         //计时器清0
  284.                          }                 
  285.                 }               
  286.         }

  287. }  

  288. u8 FloorCall_UP(u8 floorside) // floorside  =  DOWN在楼下  UP在楼上
  289. {
  290.          u8 i;

  291.          if(floorside==UP)
  292.          {
  293.                  for(i=DlevState.CurrentFloor+1;i<=MaxFloor;i++) //扫描呼叫列表楼上是否有要向上的呼叫
  294.                  {
  295.                          if(DlevState.FloorCallTable[i]==UP) //如果扫描到上方楼层有向上的呼叫
  296.                          {
  297.                                  return TRUE;
  298.                          }
  299.                  }
  300.                  return FALSE;
  301.          }
  302.          else
  303.          if(floorside==DOWN)
  304.          {
  305.                  for(i=DlevState.CurrentFloor-1;i>=1;i--) //扫描呼叫列表楼下是否有要向上的呼叫
  306.                  {
  307.                          if(DlevState.FloorCallTable[i]==UP) //如果扫描到上方楼层有向上的呼叫
  308.                          {
  309.                                  return TRUE;
  310.                          }
  311.                  }
  312.                  return FALSE;
  313.          }
  314. }

  315. u8 FloorCall_DOWN(u8 floorside) // floorside  =  DOWN在楼下  UP在楼上
  316. {
  317.          u8 i;

  318.          if(floorside==UP)
  319.          {
  320.                  for(i=DlevState.CurrentFloor+1;i<=MaxFloor;i++) //扫描呼叫列表楼上是否有要向下的呼叫
  321.                  {
  322.                          if(DlevState.FloorCallTable[i]==DOWN) //如果扫描到上方楼层有向下的呼叫
  323.                          {
  324.                                  return TRUE;
  325.                          }
  326.                  }
  327.                  return FALSE;
  328.          }
  329.          else
  330.          if(floorside==DOWN)
  331.          {
  332.                  for(i=DlevState.CurrentFloor-1;i>=1;i--) //扫描呼叫列表楼下是否有要向下的呼叫
  333.                  {
  334.                          if(DlevState.FloorCallTable[i]==DOWN) //如果扫描到上方楼层有向下的呼叫
  335.                          {
  336.                                  return TRUE;
  337.                          }
  338.                  }
  339.                  return FALSE;
  340.          }
  341. }

  342. void FLOORCALLCHECK(void)
  343. {
  344.         u8 i;
  345.                
  346.         for(i=1;i<=MaxFloor;i++) //扫描呼叫列表是否空闲
  347.         {
  348.           if(DlevState.FloorCallTable[i]!=Null) //非空闲
  349.                 {
  350.                          DlevState.FreeFlag=FALSE; //退出空闲状态
  351.                          DlevState.DlevRunning=TRUE;//正在运行标志打开
  352.        break;
  353.                 }
  354.                 else if(i==MaxFloor) DlevState.FreeFlag=TRUE; //进入空闲状态
  355.         }
  356.         if(DlevState.CurrentFloor==1)  DlevState.Direction=UP;  //1楼调头
  357.         else
  358.         if(DlevState.CurrentFloor==MaxFloor)  DlevState.Direction=DOWN; //顶楼调头
  359.   if((DlevState.FreeFlag==FALSE)&&(DOOR==CLOSE)) //非空闲下
  360.         {                                
  361.      if(DlevState.Direction==UP)//方向向上
  362.                  {
  363.                     if((FloorCall_UP(UP)==TRUE)||(FloorCall_DOWN(UP)==TRUE)) //如果当前楼层上方有呼叫向上的 或 如果当前楼层上方有呼叫向下的
  364.                                 {
  365.                                   if(DlevState.ArriveFlag==TRUE) //检测是否到达楼层  如果接收到 到达楼层的限位开关信号,则当前楼层值+1
  366.                                   {               
  367.             DlevState.ArriveFlag=FALSE; //清除标志                                                
  368.                                           DlevState.FloorTimerCount=0;         //计时器清0
  369.                                           DlevState.CurrentFloor++;//电梯继续往上走
  370.                                   }
  371.                                 }
  372.                                 else
  373.         if((FloorCall_UP(DOWN)==TRUE)||(FloorCall_DOWN(DOWN)==TRUE)) //扫描下方是否是有呼叫
  374.                                 {
  375.                                         DlevState.Direction=DOWN; //楼层下方有呼叫则调头
  376.                                 }
  377.                                 else DlevState.FreeFlag=TRUE; //否则进入空闲状态
  378.                  }
  379.                  else
  380.                  if(DlevState.Direction==DOWN)//方向向下
  381.                  {
  382.                     if((FloorCall_DOWN(DOWN)==TRUE)||(FloorCall_UP(DOWN)==TRUE)) //如果当前楼层下方有呼叫向下的 或 如果当前楼层下方有呼叫向上的
  383.                                 {
  384.                                   if(DlevState.ArriveFlag==TRUE) //检测是否到达楼层  如果接收到 到达楼层的限位开关信号,则当前楼层值+1
  385.                                   {        
  386.             DlevState.ArriveFlag=FALSE; //清除标志                                                               
  387.                                           DlevState.FloorTimerCount=0;        
  388.                                           DlevState.CurrentFloor--;//电梯继续往下走
  389.                                   }
  390.                                 }
  391.                                 else
  392.         if((FloorCall_DOWN(UP)==TRUE)||(FloorCall_UP(UP)==TRUE)) //扫描上方是否是有呼叫
  393.                                 {
  394.                                         DlevState.Direction=UP; //楼层上方有呼叫则调头
  395.                                 }
  396.                                 else DlevState.FreeFlag=TRUE; //否则进入空闲状态
  397.                  }
  398.         }
  399.         else
  400.         {               
  401.            DlevWorkState(STOP); //停止运行
  402.                  DlevState.DlevRunning=FALSE;//正在运行标志关闭
  403.         }
  404. }

  405. void SYSYEM_INIT(void)
  406. {
  407.          u8 i;
  408.         
  409.          DlevState.CurrentFloor=1;
  410.          DlevState.Direction=UP;              //初使化方向为向上
  411.          DlevState.FloorTimerCount=0;        
  412.          DlevState.FreeFlag=TRUE;             //初使化为空闲状态
  413.          DlevState.DlevRunning=FALSE;
  414.          RIOver_Flag=FALSE;
  415.          RICount=0;
  416.          for(i=1;i<=MaxFloor;i++)
  417.          {
  418.                  DlevState.FloorCallTable[i]=Null; //初使化呼叫列表为Null
  419.          }
  420.          DOOR_Close;
  421. }

  422. void main(void)
  423. {
  424.         SYSYEM_INIT();
  425.         EXTI0_Init();
  426.         EXTI1_Init();
  427.         Timer0_Init();
  428.         USART_Configure(9600);
  429.   while(1)
  430.         {
  431.                  KeyPort_Y=0x00;
  432.                  FLOORCALLCHECK();
  433.            Elevator();   
  434.         }
  435. }

  436. void EXTI0_IRQHandler(void) interrupt 0
  437. {         
  438.          DlevState.ArriveFlag=TRUE;
  439. }
  440. void EXTI1_IRQHandler(void) interrupt 2
  441. {
  442.    KeyDatHandle(KeyScan());
  443. }

  444. void TIM0_IRQHandler(void)  interrupt 1
  445. {
  446.    TH0=(65536-50000)/256;
  447.          TL0=(65536-50000)%256;
  448.         
  449.          TimerCount++;
  450.          if(TimerCount==20)  //1秒
  451.          {
  452.                  TimerCount=0;
  453.                  Timer_Second++;
  454.          }         
  455.          DlevState.FloorTimerCount++;
  456. }

  457. void USART_IRQHandler(void) interrupt 4
  458. {                  

  459. }

复制代码
8层楼梯定时模拟版仿真:
2.png
  1. /*******************电梯主程序**********************/

  2. #include "reg51.h"
  3. #include "intrins.h"

  4. /******************移植部分代码*************************/
  5. sbit DOOR=P3^5;
  6. sbit DlevMotor_P=P3^6; //电梯电机正极
  7. sbit DlevMotor_N=P3^7; //电梯电机负极
  8. #define SEGPort    P0
  9. #define KeyPort_X  P1
  10. #define KeyPort_Y  P2
  11. /******************************************************/


  12. #define u8  unsigned char
  13. #define u16 unsigned int
  14.         
  15. #define MaxFloor   8

  16. #define FloorStayTime 40        //单位:50ms
  17. #define DoorStayTime  2   //单位:S

  18. #define TRUE  1
  19. #define FALSE 0

  20. #define Null  0  
  21. #define STOP  1
  22. #define UP    2
  23. #define DOWN  3
  24. #define Dlev_UP    DlevMotor_P=0;DlevMotor_N=1  //低电平有效
  25. #define Dlev_DOWN  DlevMotor_P=1;DlevMotor_N=0  //低电平有效
  26. #define Dlev_STOP  DlevMotor_P=1;DlevMotor_N=1  //低电平有效

  27. #define OPEN  1  
  28. #define CLOSE 0
  29. #define DOOR_Open  DOOR=OPEN
  30. #define DOOR_Close DOOR=CLOSE


  31. typedef struct
  32. {
  33.         u8 DlevRunning;
  34.   u8 CurrentFloor;
  35.         u8 Direction;
  36.         u8 FloorCallTable[MaxFloor+1];//数组[0]不用,从[1]开始使用
  37.         u8 FloorTimerCount;        
  38.         u8 ArriveFlag;      //到达楼层信号(用于停止或在前一楼层提前加减速)(此版本是定时器模拟,用不到)
  39.         u8 FreeFlag;        
  40. }TYPEDEF_DLEVSTATE;
  41. TYPEDEF_DLEVSTATE DlevState;


  42. u8 code SEG_NUM[]={0x3f,0x06,0x5b,0x4f,0x66,0x6D,0x7D,0x07,0x7f,0x6f};   //SEG数码管段码  0~9
  43. u8 Timer_Second;
  44. u16 TimerCount;
  45. u8 RICount=0;
  46. u8 RIOver_Flag=0;
  47. u8 ExternKey[2]={0}; //外部按键按下信息
  48. u8 FloorCallTableBUFF[MaxFloor+10]={0};
  49. u8 KeyPressFlag=0;

  50. void delay_ms(u16 xms);
  51. void delay_s(u8 xs);
  52. void EXTI0_Init(void);
  53. void Timer0_Init(void);
  54. void USART_Configure(u16 BaudRate);
  55. u8 KeyScan(void);
  56. void KeyDatHandle(u8 key);
  57. void WaitDoorOpen(u8 ts);
  58. void WaitDoorClose(u8 ts);
  59. void SEG_Display(u8 segnum);
  60. void DlevWorkState(u8 state);
  61. void Elevator(void);
  62. u8 FloorCall_UP(u8 floorside);
  63. u8 FloorCall_DOWN(u8 floorside);
  64. void FLOORCALLCHECK(void);
  65. void SYSYEM_INIT(void);


  66. void delay_ms(u16 xms)
  67. {
  68.         u8 i;
  69.         u16 t;
  70.   for(t=xms;t>0;t--)
  71.           for(i=112;i>0;i--);
  72. }

  73. void delay_s(u8 xs)
  74. {
  75.    TimerCount=0;
  76.          Timer_Second=0;
  77.    while(Timer_Second<xs);        
  78. }

  79. void EXTI0_Init(void)
  80. {
  81.   EA = 1;  
  82.         IT0= 1; //下降沿触发
  83.         EX0= 1;
  84. }

  85. void EXTI1_Init(void)
  86. {
  87.   EA = 1;  
  88.         IT1= 1; //下降沿触发
  89.         EX1= 1;
  90. }

  91. void Timer0_Init(void)
  92. {
  93.         TMOD |= 0x01;  
  94.   TH0=(65536-50000)/256;
  95.         TL0=(65536-50000)%256;
  96.         EA = 1;
  97.         ET0 = 1;
  98.         TR0 = 1;
  99. }


  100. void USART_Configure(u16 BaudRate)
  101. {
  102.         u8 TH1_Dat;
  103.         
  104.   switch(BaudRate)
  105.         {
  106.           case 1200:  TH1_Dat=0xE8; break;
  107.                 case 2400:  TH1_Dat=0xF4; break;
  108.                 case 4800:  TH1_Dat=0xFA; break;
  109.                 case 9600:  TH1_Dat=0xFD; break;
  110.                 case 14400: TH1_Dat=0xFE; break;
  111.         }
  112.         TMOD |= 0x20;
  113.         SCON |= 0x50;
  114.         TH1 = TH1_Dat;
  115.         TL1 = TH1;
  116.         PCON |= 0x00;
  117.         EA = 1;
  118.         ES = 1;
  119.         TR1 = 1;  
  120. }



  121. u8 KeyScan(void)
  122. {
  123.         u8 keynum;
  124.   
  125.         KeyPort_Y=0x00;
  126.         KeyPort_X=0xFF;
  127.         _nop_(); _nop_(); _nop_(); _nop_();
  128.         if(KeyPort_X!=0xFF)
  129.         {
  130.          delay_ms(10);
  131.          if(KeyPort_X!=0xFF)
  132.          {
  133.                  switch(KeyPort_X)
  134.                  {
  135.                          case 0x7F: keynum=1;   break;
  136.                          case 0xBF: keynum=9;   break;
  137.                          case 0xDF: keynum=17;  break;
  138.                          case 0xEF: keynum=25;  break;
  139.                          case 0xF7: keynum=33;  break;
  140.                          case 0xFB: keynum=41;  break;
  141.                          case 0xFD: keynum=49;  break;
  142.                          case 0xFE: keynum=57;  break;
  143.                  }
  144.                  KeyPort_Y=0xFF;
  145.                  KeyPort_X=0x00;
  146.                  _nop_(); _nop_(); _nop_(); _nop_();
  147.                  if(KeyPort_Y!=0xFF)
  148.                  {
  149.                          switch(KeyPort_Y)
  150.                          {
  151.                                  case 0xFE: keynum=keynum+0;  break;
  152.                                  case 0xFD: keynum=keynum+1;  break;
  153.                                  case 0xFB: keynum=keynum+2;  break;
  154.                                  case 0xF7: keynum=keynum+3;  break;
  155.                                  case 0xEF: keynum=keynum+4;  break;
  156.                                  case 0xDF: keynum=keynum+5;  break;
  157.                                  case 0xBF: keynum=keynum+6;  break;
  158.                                  case 0x7F: keynum=keynum+7;  break;
  159.                          }
  160.                  }
  161.                  KeyPort_Y=0x00;
  162.    }
  163.         }
  164.         else keynum=0;
  165.         return keynum;
  166. }

  167. void KeyDatHandle(u8 key)
  168. {
  169.         if(key==0)
  170.         {
  171.         
  172.         }
  173.         else
  174.         if(key<=MaxFloor) //楼梯内的楼层选择按键
  175.         {
  176.                 if(key>DlevState.CurrentFloor) DlevState.FloorCallTable[key]=UP;
  177.                 else
  178.                 if(key<DlevState.CurrentFloor) DlevState.FloorCallTable[key]=DOWN;
  179.         }
  180.         else
  181.         if((key<=MaxFloor*2)&&(key>MaxFloor+1))  //每个楼层门口外的向下按键(底楼按向下无效)
  182.         {
  183.                  DlevState.FloorCallTable[key-MaxFloor]=DOWN;
  184.         }
  185.         else
  186.         if(key<MaxFloor*3) //每个楼层门口外的向上按键(顶楼按向上无效)
  187.         {
  188.                  DlevState.FloorCallTable[key-MaxFloor*2]=UP;
  189.         }
  190.         else
  191.         if(key==MaxFloor*3+1)  //开门
  192.         {
  193.                 if(DlevState.DlevRunning==FALSE)
  194.                 {
  195.                   if(DOOR==CLOSE) DOOR_Open;
  196.                 }
  197.         }
  198.         else
  199.         if(key==MaxFloor*3+2) //关门
  200.         {
  201.                 if(DOOR==OPEN)
  202.                 {
  203.                         DOOR_Close;
  204.                         DlevState.FloorTimerCount=0;         //计时器清0
  205.                 }
  206.         }
  207. }

  208. void WaitDoorOpen(u8 ts)
  209. {
  210.         DOOR_Open;
  211.         delay_s(ts);
  212. }

  213. void WaitDoorClose(u8 ts)
  214. {
  215.         DOOR_Close;
  216.         delay_s(ts);
  217. }

  218. void SEG_Display(u8 segnum)
  219. {
  220.   SEGPort=~SEG_NUM[segnum];
  221. }

  222. void DlevWorkState(u8 state)
  223. {
  224.   if(state==UP)
  225.         {
  226.                 Dlev_UP;
  227.                 DlevState.DlevRunning=TRUE;
  228.         }
  229.         else
  230.         if(state==DOWN)
  231.         {
  232.                 Dlev_DOWN;
  233.                 DlevState.DlevRunning=TRUE;
  234.         }
  235.         else
  236.         if(state==STOP)
  237.         {
  238.                 Dlev_STOP;
  239.                 DlevState.DlevRunning=FALSE;
  240.         }
  241.         SEG_Display(DlevState.CurrentFloor);                //数码管显示
  242. }
  243.         
  244. void Elevator(void)
  245. {
  246.         if((DOOR==OPEN)||(DlevState.FreeFlag==TRUE)) DlevWorkState(STOP);        
  247.   else
  248.         DlevWorkState(DlevState.Direction);        
  249.         
  250.         if(DlevState.Direction==UP)  //电梯正在向上运行的情况
  251.         {
  252.                 if(DlevState.CurrentFloor<=MaxFloor)  //扫描呼叫列表中的向上方向的呼叫楼层
  253.                 {
  254.                          if(DlevState.FloorCallTable[DlevState.CurrentFloor]==UP) //到达目标楼层,停下开门5秒
  255.                          {
  256.                                  DlevState.FloorCallTable[DlevState.CurrentFloor]=Null; //到达相应的楼层从向上列表中清除                                         
  257.                                  DlevState.FreeFlag=TRUE; //到达楼层,暂停进入空闲状态                                 
  258.                                  DlevWorkState(STOP);
  259.                            WaitDoorOpen(DoorStayTime);
  260.                                  delay_s(2*DoorStayTime);       //保持门开2秒让人进出
  261.                                  WaitDoorClose(DoorStayTime);
  262.                                  DlevWorkState(DlevState.Direction);
  263.                                  DlevState.FreeFlag=FALSE; //离开楼层,退出空闲状态
  264.                                  DlevState.FloorTimerCount=0;         //计时器清0
  265.                          }                 
  266.                 }               
  267.         }
  268.         else
  269.         if(DlevState.Direction==DOWN)  //电梯正在向下运行的情况
  270.         {
  271.                 if(DlevState.CurrentFloor>=1)  //扫描呼叫列表中的向下方向的呼叫楼层
  272.                 {
  273.                          if(DlevState.FloorCallTable[DlevState.CurrentFloor]==DOWN) //到达楼层,停下开门5秒
  274.                          {        
  275.          DlevState.FloorCallTable[DlevState.CurrentFloor]=Null; //到达相应的楼层从向下列表中清除        
  276.                                  DlevState.FreeFlag=TRUE; //到达楼层,暂停进入空闲状态                 
  277.                                  DlevWorkState(STOP);
  278.                            WaitDoorOpen(DoorStayTime);
  279.                                  delay_s(2*DoorStayTime);       //保持门开2秒让人进出
  280.                                  WaitDoorClose(DoorStayTime);
  281.                                  DlevWorkState(DlevState.Direction);
  282.                                  DlevState.FreeFlag=FALSE; //离开楼层,退出空闲状态
  283.                                  DlevState.FloorTimerCount=0;         //计时器清0
  284.                          }                 
  285.                 }               
  286.         }

  287. }  

  288. u8 FloorCall_UP(u8 floorside) // floorside  =  DOWN在楼下  UP在楼上
  289. {
  290.          u8 i;

  291.          if(floorside==UP)
  292.          {
  293.                  for(i=DlevState.CurrentFloor+1;i<=MaxFloor;i++) //扫描呼叫列表楼上是否有要向上的呼叫
  294.                  {
  295.                          if(DlevState.FloorCallTable[i]==UP) //如果扫描到上方楼层有向上的呼叫
  296.                          {
  297.                                  return TRUE;
  298.                          }
  299.                  }
  300.                  return FALSE;
  301.          }
  302.          else
  303.          if(floorside==DOWN)
  304.          {
  305.                  for(i=DlevState.CurrentFloor-1;i>=1;i--) //扫描呼叫列表楼下是否有要向上的呼叫
  306.                  {
  307.                          if(DlevState.FloorCallTable[i]==UP) //如果扫描到上方楼层有向上的呼叫
  308.                          {
  309.                                  return TRUE;
  310.                          }
  311.                  }
  312.                  return FALSE;
  313.          }
  314. }

  315. u8 FloorCall_DOWN(u8 floorside) // floorside  =  DOWN在楼下  UP在楼上
  316. {
  317.          u8 i;

  318.          if(floorside==UP)
  319.          {
  320.                  for(i=DlevState.CurrentFloor+1;i<=MaxFloor;i++) //扫描呼叫列表楼上是否有要向下的呼叫
  321.                  {
  322.                          if(DlevState.FloorCallTable[i]==DOWN) //如果扫描到上方楼层有向下的呼叫
  323.                          {
  324.                                  return TRUE;
  325.                          }
  326.                  }
  327.                  return FALSE;
  328.          }
  329.          else
  330.          if(floorside==DOWN)
  331.          {
  332.                  for(i=DlevState.CurrentFloor-1;i>=1;i--) //扫描呼叫列表楼下是否有要向下的呼叫
  333.                  {
  334.                          if(DlevState.FloorCallTable[i]==DOWN) //如果扫描到上方楼层有向下的呼叫
  335.                          {
  336.                                  return TRUE;
  337.                          }
  338.                  }
  339.                  return FALSE;
  340.          }
  341. }

  342. void FLOORCALLCHECK(void)
  343. {
  344.         u8 i;
  345.                
  346.         for(i=1;i<=MaxFloor;i++) //扫描呼叫列表是否空闲
  347.         {
  348.           if(DlevState.FloorCallTable[i]!=Null) //非空闲
  349.                 {
  350.                          DlevState.FreeFlag=FALSE; //退出空闲状态
  351.                          DlevState.DlevRunning=TRUE;//正在运行标志打开
  352.        break;
  353.                 }
  354.                 else if(i==MaxFloor) DlevState.FreeFlag=TRUE; //进入空闲状态
  355.         }
  356.         if(DlevState.CurrentFloor==1)  DlevState.Direction=UP;  //1楼调头
  357.         else
  358.         if(DlevState.CurrentFloor==MaxFloor)  DlevState.Direction=DOWN; //顶楼调头
  359.   if((DlevState.FreeFlag==FALSE)&&(DOOR==CLOSE)) //非空闲下
  360.         {                                
  361.      if(DlevState.Direction==UP)//方向向上
  362.                  {
  363.                     if((FloorCall_UP(UP)==TRUE)||(FloorCall_DOWN(UP)==TRUE)) //如果当前楼层上方有呼叫向上的 或 如果当前楼层上方有呼叫向下的
  364.                                 {
  365.                                   if(DlevState.FloorTimerCount>FloorStayTime) //检测是否到达楼层  如果接收到 到达楼层的限位开关信号,则当前楼层值+1(这里用定时器来模拟)
  366.                                   {                                                               
  367.                                           DlevState.FloorTimerCount=0;         //计时器清0
  368.                                           DlevState.CurrentFloor++;//电梯继续往上走
  369.                                   }
  370.                                 }
  371.                                 else
  372.         if((FloorCall_UP(DOWN)==TRUE)||(FloorCall_DOWN(DOWN)==TRUE)) //扫描下方是否是有呼叫
  373.                                 {
  374.                                         DlevState.Direction=DOWN; //楼层下方有呼叫则调头
  375.                                 }
  376.                                 else DlevState.FreeFlag=TRUE; //否则进入空闲状态
  377.                  }
  378.                  else
  379.                  if(DlevState.Direction==DOWN)//方向向下
  380.                  {
  381.                     if((FloorCall_DOWN(DOWN)==TRUE)||(FloorCall_UP(DOWN)==TRUE)) //如果当前楼层下方有呼叫向下的 或 如果当前楼层下方有呼叫向上的
  382.                                 {
  383.                                   if(DlevState.FloorTimerCount>FloorStayTime) //检测是否到达楼层  如果接收到 到达楼层的限位开关信号,则当前楼层值+1(这里用定时器来模拟)
  384.                                   {                                                               
  385.                                           DlevState.FloorTimerCount=0;        
  386.                                           DlevState.CurrentFloor--;//电梯继续往下走
  387.                                   }
  388.                                 }
  389.                                 else
  390.         if((FloorCall_DOWN(UP)==TRUE)||(FloorCall_UP(UP)==TRUE)) //扫描上方是否是有呼叫
  391.                                 {
  392.                                         DlevState.Direction=UP; //楼层上方有呼叫则调头
  393.                                 }
  394.                                 else DlevState.FreeFlag=TRUE; //否则进入空闲状态
  395.                  }
  396.         }
  397.         else
  398.         {               
  399.            DlevWorkState(STOP); //停止运行
  400.                  DlevState.DlevRunning=FALSE;//正在运行标志关闭
  401.         }
  402. }

  403. void SYSYEM_INIT(void)
  404. {
  405.          u8 i;
  406.         
  407.          DlevState.CurrentFloor=1;
  408.          DlevState.Direction=UP;              //初使化方向为向上
  409.          DlevState.FloorTimerCount=0;        
  410.          DlevState.FreeFlag=TRUE;             //初使化为空闲状态
  411.          DlevState.DlevRunning=FALSE;
  412.          RIOver_Flag=FALSE;
  413.          RICount=0;
  414.          for(i=1;i<=MaxFloor;i++)
  415.          {
  416.                  DlevState.FloorCallTable[i]=Null; //初使化呼叫列表为Null
  417.          }
  418.          DOOR_Close;
  419. }

  420. void main(void)
  421. {
  422.         SYSYEM_INIT();
  423.         EXTI0_Init();
  424.         EXTI1_Init();
  425.         Timer0_Init();
  426.         USART_Configure(9600);
  427.   while(1)
  428.         {
  429.                  KeyPort_Y=0x00;
  430.                  FLOORCALLCHECK();
  431.            Elevator();   
  432.         }
  433. }

  434. //void EXTI0_IRQHandler(void) interrupt 0     //楼层传感器中断(此模拟版本用不到)
  435. //{         
  436. //         DlevState.ArriveFlag=TRUE;
  437. //}
  438. void EXTI1_IRQHandler(void) interrupt 2    //矩阵按键中断
  439. {
  440.    KeyDatHandle(KeyScan());
  441. }

  442. void TIM0_IRQHandler(void)  interrupt 1    //定时模拟电梯上升和下降
  443. {
  444.    TH0=(65536-50000)/256;
  445.          TL0=(65536-50000)%256;
  446.         
  447.          TimerCount++;
  448.          if(TimerCount==20)  //1秒
  449.          {
  450.                  TimerCount=0;
  451.                  Timer_Second++;
  452.          }         
  453.          DlevState.FloorTimerCount++;
  454. }

  455. void USART_IRQHandler(void) interrupt 4  //用于电梯之间的通信
  456. {                  

  457. }

复制代码


您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|手机版|小黑屋|ELEOK |网站地图

GMT+8, 2024-3-29 22:46

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表