找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1188|回复: 0
打印 上一主题 下一主题
收起左侧

16层楼梯单片机源程序+Proteus仿真

[复制链接]
跳转到指定楼层
楼主
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. /*************************电梯主程序*****************************/

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

  4. /*********************程序选择****************************/
  5. #define USE_MODE 0   //0-定时模拟  1-传感器
  6. /****************************************************************/
  7. /*********************平台移植部分代码****************************/
  8. //定时器模拟版接口:
  9. #if (USE_MODE==0)
  10. sbit DOOR=P3^5;        //电梯门开关控制信号
  11. sbit ElevMotor_P=P3^6; //电梯电机正极控制信号
  12. sbit ElevMotor_N=P3^7; //电梯电机负极控制信号
  13. sbit SHCP=P0^5;        //74HC595  LED、数码管显示驱动
  14. sbit DS=P0^6;          //74HC595  LED、数码管显示驱动
  15. sbit STCP=P0^7;        //74HC595  LED、数码管显示驱动
  16. #define KeyPort_X  P1  //矩阵按键接口
  17. #define KeyPort_Y  P2  //矩阵按键接口
  18. #endif
  19. //除以上定义的IO外,还需用到P33作为矩阵键盘的中断触发引脚
  20. //8路与门:用8路与非门CD4068或74LS30+输出端接一个三极管反向电平。


  21. //传感器版接口:
  22. #if (USE_MODE==1)
  23. sbit DOOR_CLOSE_SENSOR=P3^4;//电梯门关闭检测传感器输入
  24. sbit DOOR=P3^5;        //电梯门开关控制信号
  25. sbit ElevMotor_P=P3^6; //电梯电机正极控制信号
  26. sbit ElevMotor_N=P3^7; //电梯电机负极控制信号
  27. sbit SHCP=P0^5;        //74HC595  LED、数码管显示驱动
  28. sbit DS=P0^6;          //74HC595  LED、数码管显示驱动
  29. sbit STCP=P0^7;        //74HC595  LED、数码管显示驱动
  30. #define KeyPort_X  P1  //矩阵按键接口
  31. #define KeyPort_Y  P2  //矩阵按键接口
  32. #endif
  33. //除以上定义的IO外,还需用到P33作为矩阵键盘的中断触发引脚
  34. //需用到P32作为楼层限位开关触发中断引脚
  35. //每个楼层一个限位开关,接在N路输入的与门芯片上
  36. //如果大于8层,可用两个8路输入的与门芯片+一个2路的与门芯片组合
  37. /****************************************************************/
  38. /***********************楼梯参数设置*****************************/
  39. #define MaxFloor      16  //电梯总楼层(最大16)

  40. #define FloorStayTime 40 //单位:50ms, 楼层停留时间:40*50ms=2S
  41. #define DoorStayTime  2  //单位:S   , 电梯门停留时间
  42. #define SEG_Num       2  //数码管数量(为1时请删除第一个数码管的595)
  43. /****************************************************************/
  44. #define u8  unsigned char
  45. #define u16 unsigned int
  46.    
  47. #define TRUE  1    //真
  48. #define FALSE 0    //假

  49. //电梯运行状态
  50. #define Null  0     //空闲
  51. #define STOP  1     //停止
  52. #define UP    2     //向上
  53. #define DOWN  3     //向下

  54. #define UP_IN     0x01     //内部向上标记(在呼叫列表中的标记  用bit0标记)
  55. #define UP_OUT    0x02     //外部向上标记(在呼叫列表中的标记  用bit1标记)
  56. #define DOWN_IN   0x04     //内部向下标记(在呼叫列表中的标记  用bit2标记)
  57. #define DOWN_OUT  0x08     //外部向下标记(在呼叫列表中的标记  用bit3标记)

  58. #define Elev_UP    ElevMotor_P=0;ElevMotor_N=1  //低电平有效
  59. #define Elev_DOWN  ElevMotor_P=1;ElevMotor_N=0  //低电平有效  电机正转
  60. #define Elev_STOP  ElevMotor_P=1;ElevMotor_N=1  //低电平有效  电机反转

  61. #define OPEN  1  
  62. #define CLOSE 0
  63. #define DOOR_Open  DOOR=OPEN     //开门
  64. #define DOOR_Close DOOR=CLOSE    //关门

  65. #define SHCP_H SHCP=1
  66. #define SHCP_L SHCP=0
  67. #define DS_H   DS=1
  68. #define DS_L   DS=0
  69. #define STCP_H STCP=1
  70. #define STCP_L STCP=0

  71. #if MaxFloor>8  
  72. #define MHC595_NUM 8
  73. #else
  74. #define MHC595_NUM 5
  75. #endif

  76. #define SEGPort 0x01
  77. #define LED_IN_Port 0x02
  78. #define LED_OUT_UP_Port 0x03
  79. #define LED_OUT_DOWN_Port 0x04

  80. //FloorCallTable[]呼叫列表说明:该列表由数组构成,下标和每个楼层一一对应,如FloorCallTable[1]表示1楼的呼叫状态
  81. // bit3-DOWN_OUT  bit2-DOWN_IN  bit1-UP_OUT  bit0-UP_IN   bit=0为没有呼叫,=1为有呼叫
  82. typedef struct
  83. {
  84.     u8 ElevRunning;      //电梯运行状态标志
  85.   u8 CurrentFloor;     //当前电梯所处楼层
  86.     u8 Direction;        //电梯运行方向
  87.     u8 FloorCallTable[MaxFloor+1];//数组[0]不用,从[1]开始使用 ,呼叫列表(所有楼层呼叫的信息均保存于此)
  88.     u8 FloorTimerCount;     //计时
  89.     u8 ArriveFlag;       //到达楼层信号(用于停止或在前一楼层提前加减速)(定时器模拟的用不到)
  90.     u8 FreeFlag;           //电梯空闲状态标志
  91. }TYPEDEF_ELEVSTATE;
  92. TYPEDEF_ELEVSTATE ElevState; //电梯状态结构体

  93. //u8 code SEG_NUM[]={0x3f,0x06,0x5b,0x4f,0x66,0x6D,0x7D,0x07,0x7f,0x6f};   //共阴SEG数码管段码  0~9
  94. u8 code SEG_NUM[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //共阳SEG数码管段码  0~F
  95. u16 code LED_NUM[]={0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};   //SEG数码管段码  0~9

  96. u8 HC595_BUFF[MHC595_NUM]={0};
  97. u8 Timer_Second;
  98. u16 TimerCount;

  99. u8 ExternKey[2]={0}; //外部按键按下信息
  100. u8 FloorCallTableBUFF[MaxFloor+10]={0};
  101. u8 KeyPressFlag=0;

  102. #define USART_RX_LEN 20  //接收缓存长度(请勿超过芯片rom剩余大小)
  103. typedef struct
  104. {
  105.   u8 RX_BUFF[USART_RX_LEN]; //接收缓存
  106.     u8 TX_BUFF[USART_RX_LEN]; //发送缓存
  107.     u16 RX_COUNT;
  108. }USART;
  109. USART Usart;

  110. void delay_ms(u16 xms); //ms延时
  111. void delay_s(u8 xs);    //s延时
  112. void EXTI0_Init(void);
  113. void EXTI1_Init(void);
  114. void TIMER0_Init(void);
  115. void USART_Config(u16 BaudRate);
  116. void HC595_Send(u8 *p);
  117. u8 KeyScan(void);
  118. void KeyDatHandle(u8 key);
  119. void WaitDoorOpen(u8 ts);
  120. void WaitDoorClose(u8 ts);
  121. void SEG_Display(u8 segnum);
  122. void LED_ON(u8 addr,u8 lednum);
  123. void LED_OFF(u8 addr,u8 lednum);
  124. void ElevWorkState(u8 state);
  125. void Elevator(void);
  126. u8 FloorCall_UP(u8 floorside);
  127. u8 FloorCall_DOWN(u8 floorside);
  128. u8 DelNullCheck(void);
  129. void FloorCallCheck(void);
  130. void USART_SendByte(u8 dat);
  131. void USART_Send(u8* arr,u16 len);
  132. void USART_SendStr(u8* str);
  133. void SYSYEM_INIT(void);

  134. void delay_ms(u16 xms)
  135. {
  136.     u8 i;
  137.     u16 t;
  138.   for(t=xms;t>0;t--)
  139.       for(i=112;i>0;i--);
  140. }

  141. void delay_s(u8 xs)
  142. {
  143.    TimerCount=0;
  144.      Timer_Second=0;
  145.    while(Timer_Second<xs);   
  146. }

  147. void EXTI0_Init(void)
  148. {
  149.   EA = 1;  
  150.     IT0= 1; //下降沿触发
  151.     EX0= 1;
  152. }

  153. void EXTI1_Init(void)
  154. {
  155.   EA = 1;  
  156.     IT1= 1; //下降沿触发
  157.     EX1= 1;
  158. }

  159. void Timer0_Init(void)
  160. {
  161.     TMOD |= 0x01;  
  162.   TH0=(65536-50000)/256;
  163.     TL0=(65536-50000)%256;
  164.     EA = 1;
  165.     ET0 = 1;
  166.     TR0 = 1;
  167. }


  168. void USART_Config(u16 BaudRate)
  169. {
  170.     u8 TH1_Dat;
  171.    
  172.   switch(BaudRate)
  173.     {
  174.       case 1200:  TH1_Dat=0xE8; break;
  175.         case 2400:  TH1_Dat=0xF4; break;
  176.         case 4800:  TH1_Dat=0xFA; break;
  177.         case 9600:  TH1_Dat=0xFD; break;
  178.         case 14400: TH1_Dat=0xFE; break;
  179.     }
  180.     TMOD |= 0x20;
  181.     SCON |= 0x50;
  182.     TH1 = TH1_Dat;
  183.     TL1 = TH1;
  184.     PCON |= 0x00;
  185.     EA = 1;
  186.     ES = 1;
  187.     TR1 = 1;  
  188. }

  189. void HC595_Send(u8 *p)
  190. {
  191.   u8 i,j;
  192.     u8 temp;
  193.     for(i=MHC595_NUM;i>2-SEG_Num;i--)
  194.     {
  195.         temp=p[i-1];
  196.         for(j=0;j<8;j++)
  197.         {
  198.           DS=temp&0x80;   
  199.       temp<<=1;   
  200.       SHCP_L;
  201.       SHCP_H;            
  202.         }
  203.     }
  204.     STCP_L;
  205.   STCP_H;   
  206. }
  207. /*键盘剪裁说明:
  208. 按键扫描函数 8*8  如要改为4*4或其他  
  209. 请把KeyPort_Y 和 KeyPort_X 对应的IO口数量减少,如4*4,则用KeyPort_Y低4位和KeyPort_X高4位
  210. 键盘分布如下:(序号和IO口高低位对应)

  211.        P20      ->         P27

  212.              Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7
  213. P10     X0 *  *  *  *  *  *  *  *                57 58 59 60 61 62 63 64  
  214.          X1 *  *  *  *  *  *  *  *                49 50 51 52 53 54 55 56
  215.          X2 *  *  *  *  *  *  *  *                41 42 43 44 45 46 47 48
  216. |     X3 *  *  *  *  *  *  *  *  对应按键扫描  33 34 35 36 37 38 39 40  仿真文件
  217. |     X4 *  *  *  *  *  *  *  *   函数返回值-> 25 26 27 28 29 30 31 32    布局->  25 26 27 28 29 30 31 32  57 58 59 60 61 62 63 64
  218.          X5 *  *  *  *  *  *  *  *                17 18 19 20 21 22 23 24            17 18 19 20 21 22 23 24  49 50 51 52 53 54 55 56
  219.          X6 *  *  *  *  *  *  *  *                9  10 11 12 13 14 15 16            9  10 11 12 13 14 15 16  41 42 43 44 45 46 47 48
  220. P17     X7 *  *  *  *  *  *  *  *                1  2  3  4  5  6  7  8             1  2  3  4  5  6  7  8   33 34 35 36 37 38 39 40

  221. */
  222. //KeyScan()扫描函数兼容8*8以下所有键盘,键盘改小时无需修改
  223. u8 KeyScan(void)
  224. {
  225.     u8 keynum;
  226.   
  227.     KeyPort_Y=0x00;
  228.     KeyPort_X=0xFF;
  229.     _nop_(); _nop_(); _nop_(); _nop_();
  230.     if(KeyPort_X!=0xFF)
  231.     {
  232.      delay_ms(10);
  233.      if(KeyPort_X!=0xFF)
  234.      {
  235.          switch(KeyPort_X)
  236.          {
  237.              case 0x7F: keynum=1;   break;
  238.              case 0xBF: keynum=9;   break;
  239.              case 0xDF: keynum=17;  break;
  240.              case 0xEF: keynum=25;  break;
  241.              case 0xF7: keynum=33;  break;
  242.              case 0xFB: keynum=41;  break;
  243.              case 0xFD: keynum=49;  break;
  244.              case 0xFE: keynum=57;  break;
  245.          }
  246.          KeyPort_Y=0xFF;
  247.          KeyPort_X=0x00;
  248.          _nop_(); _nop_(); _nop_(); _nop_();
  249.          if(KeyPort_Y!=0xFF)
  250.          {
  251.              switch(KeyPort_Y)
  252.              {
  253.                  case 0xFE: keynum=keynum+0;  break;
  254.                  case 0xFD: keynum=keynum+1;  break;
  255.                  case 0xFB: keynum=keynum+2;  break;
  256.                  case 0xF7: keynum=keynum+3;  break;
  257.                  case 0xEF: keynum=keynum+4;  break;
  258.                  case 0xDF: keynum=keynum+5;  break;
  259.                  case 0xBF: keynum=keynum+6;  break;
  260.                  case 0x7F: keynum=keynum+7;  break;
  261.              }
  262.          }
  263.          KeyPort_Y=0x00;
  264.    }
  265.     }
  266.     else keynum=0;
  267.     return keynum;
  268. }
  269. //键值处理函数:当键盘键值需要改动时,请根据上面的键值改动
  270. void KeyDatHandle(u8 key)
  271. {
  272.     u8 tempkey;
  273.     if(key==0)
  274.     {
  275.    
  276.     }
  277.     else
  278.     if(((key>0)&&(key<=8))||((key>32)&&(key<=40))) //楼梯内的楼层选择按键(使用1-8 和 33-40作为按键)
  279.     {
  280.         if(key>32) tempkey=key-32+8;
  281.         else       tempkey=key;
  282.         if(tempkey<=MaxFloor)
  283.         {
  284.             LED_ON(LED_IN_Port,tempkey);
  285.             if(((tempkey>ElevState.CurrentFloor)&&(tempkey<MaxFloor))||(tempkey==1)) ElevState.FloorCallTable[tempkey]|=UP_IN;//内部按1只能往上
  286.             else
  287.             if((tempkey<ElevState.CurrentFloor)||(tempkey==MaxFloor)) ElevState.FloorCallTable[tempkey]|=DOWN_IN;   
  288.         }
  289.     }
  290.     else
  291.     if(((key>9)&&(key<=16))||((key>40)&&(key<=48)))  //每个楼层门口外的向下按键(底楼按向下无效)(使用10-16 和 41-48作为按键)
  292.     {
  293.          if(key>40) tempkey=key-40+8;
  294.          else       tempkey=key-8;
  295.          if((tempkey>1)&&(tempkey<=MaxFloor))
  296.          {
  297.              LED_ON(LED_OUT_DOWN_Port,tempkey);
  298.            ElevState.FloorCallTable[tempkey]|=DOWN_OUT;
  299.          }
  300.     }
  301.     else
  302.     if(((key>16)&&(key<=24))||((key>48)&&(key<56))) //每个楼层门口外的向上按键(顶楼按向上无效)(使用17-24 和 49-55作为按键)
  303.     {
  304.          if(key>48) tempkey=key-48+8;
  305.          else       tempkey=key-16;
  306.          if(tempkey<MaxFloor)
  307.          {
  308.              LED_ON(LED_OUT_UP_Port,tempkey);
  309.              ElevState.FloorCallTable[tempkey]|=UP_OUT;
  310.          }
  311.     }
  312.     else
  313.     if(key==25)  //开门   (使用25 作为按键)
  314.     {
  315.         if(ElevState.ElevRunning==FALSE)
  316.         {
  317.           if(DOOR==CLOSE) DOOR_Open;
  318.         }
  319.     }
  320.     else
  321.     if(key==26) //关门    (使用26 作为按键)
  322.     {
  323.         if(DOOR==OPEN)
  324.         {
  325.             DOOR_Close;
  326.             ElevState.FloorTimerCount=0;     //计时器清0
  327.         }
  328.     }
  329. }
  330. //第待开门
  331. void WaitDoorOpen(u8 ts)
  332. {
  333.     DOOR_Open;
  334.     delay_s(ts);
  335. }
  336. //第待关门
  337. void WaitDoorClose(u8 ts)
  338. {
  339.     DOOR_Close;
  340.     #if (USE_MODE==0)
  341.     delay_s(ts);
  342.     #endif
  343.     #if (USE_MODE==1)
  344.     ts=ts; //防止警告
  345.     while(DOOR_CLOSE_SENSOR==OPEN);
  346.     #endif
  347.    
  348. }
  349. //数码管显示驱动
  350. void SEG_Display(u8 segnum)
  351. {
  352.     HC595_BUFF[0]=SEG_NUM[segnum/10];
  353.     HC595_BUFF[1]=SEG_NUM[segnum%10];
  354.     HC595_Send(HC595_BUFF);   
  355. }
  356. //LED显示驱动
  357. void LED_ON(u8 addr,u8 lednum)
  358. {
  359.     switch(addr)
  360.     {
  361.         case LED_IN_Port:        if(lednum<9)   HC595_BUFF[2]|=LED_NUM[lednum];
  362.                                else           HC595_BUFF[5]|=LED_NUM[lednum-8]; break;
  363.         case LED_OUT_DOWN_Port:  if(lednum<9)   HC595_BUFF[3]|=LED_NUM[lednum];
  364.                                                  else           HC595_BUFF[6]|=LED_NUM[lednum-8]; break;
  365.         case LED_OUT_UP_Port:    if(lednum<9)   HC595_BUFF[4]|=LED_NUM[lednum];
  366.                                                  else           HC595_BUFF[7]|=LED_NUM[lednum-8]; break;
  367.     }
  368.     HC595_Send(HC595_BUFF);   
  369. }
  370. //LED显示驱动
  371. void LED_OFF(u8 addr,u8 lednum)
  372. {
  373.     switch(addr)
  374.     {
  375.         case LED_IN_Port:        if(lednum<9)  HC595_BUFF[2]&=~LED_NUM[lednum];
  376.                                else          HC595_BUFF[5]&=~LED_NUM[lednum-8]; break;
  377.         case LED_OUT_DOWN_Port:  if(lednum<9)  HC595_BUFF[3]&=~LED_NUM[lednum];
  378.                                                  else          HC595_BUFF[6]&=~LED_NUM[lednum-8]; break;
  379.         case LED_OUT_UP_Port:    if(lednum<9)  HC595_BUFF[4]&=~LED_NUM[lednum];
  380.                                                  else          HC595_BUFF[7]&=~LED_NUM[lednum-8]; break;
  381.     }
  382.     HC595_Send(HC595_BUFF);   
  383. }
  384. //电梯运行状态设置
  385. void ElevWorkState(u8 state)
  386. {
  387.   if(state==UP)
  388.     {
  389.         Elev_UP;
  390.         ElevState.ElevRunning=TRUE;
  391.     }
  392.     else
  393.     if(state==DOWN)
  394.     {
  395.         Elev_DOWN;
  396.         ElevState.ElevRunning=TRUE;
  397.     }
  398.     else
  399.     if(state==STOP)
  400.     {
  401.         Elev_STOP;
  402.         ElevState.ElevRunning=FALSE;
  403.     }
  404.     SEG_Display(ElevState.CurrentFloor);        //数码管显示
  405. }
  406. //调头检测函数
  407. void TurnHead_Check(void)
  408. {
  409.     if(ElevState.CurrentFloor==1)  
  410.     {
  411.         ElevState.Direction=UP;  //1楼调头
  412.     }
  413.     else if(ElevState.CurrentFloor==MaxFloor)
  414.     {
  415.         ElevState.Direction=DOWN; //顶楼调头
  416.     }
  417. }
  418. //电梯运行函数
  419. void Elevator(void)
  420. {
  421.     if((DOOR==OPEN)||(ElevState.FreeFlag==TRUE)) ElevWorkState(STOP);   
  422.   else   ElevWorkState(ElevState.Direction);   
  423.     TurnHead_Check();  //调头检测
  424.     if(ElevState.Direction==UP)  //电梯正在向上运行的情况
  425.     {
  426.         if(ElevState.CurrentFloor<=MaxFloor)  //扫描呼叫列表中的向上方向的呼叫楼层
  427.         {
  428.              if(((ElevState.FloorCallTable[ElevState.CurrentFloor]&UP_IN)==UP_IN)||((ElevState.FloorCallTable[ElevState.CurrentFloor]&UP_OUT)==UP_OUT)) //到达目标楼层,停下开门5秒
  429.              {
  430.                  LED_OFF(LED_IN_Port,ElevState.CurrentFloor);
  431.                  LED_OFF(LED_OUT_UP_Port,ElevState.CurrentFloor);
  432.                  ElevState.FloorCallTable[ElevState.CurrentFloor]&=~UP_IN; //到达相应的楼层从向上列表中清除   
  433.          ElevState.FloorCallTable[ElevState.CurrentFloor]&=~UP_OUT; //到达相应的楼层从向上列表中清除                     
  434.                  ElevState.FreeFlag=TRUE; //到达楼层,暂时进入空闲状态                 
  435.                  ElevWorkState(STOP);     //修改电梯状态为停止态
  436.                WaitDoorOpen(DoorStayTime);    //延时等待电梯门打开
  437.                  delay_s(2*DoorStayTime);       //适当延时
  438.                  WaitDoorClose(DoorStayTime);   //等待门关好
  439.                  ElevWorkState(ElevState.Direction);
  440.                  ElevState.FreeFlag=FALSE; //离开楼层,退出空闲状态
  441.                  ElevState.FloorTimerCount=0;     //计时器清0
  442.              }         
  443.         }        
  444.     }
  445.     else
  446.     if(ElevState.Direction==DOWN)  //电梯正在向下运行的情况
  447.     {
  448.         if(ElevState.CurrentFloor>=1)  //扫描呼叫列表中的向下方向的呼叫楼层
  449.         {
  450.              if(((ElevState.FloorCallTable[ElevState.CurrentFloor]&DOWN_IN)==DOWN_IN)||((ElevState.FloorCallTable[ElevState.CurrentFloor]&DOWN_OUT)==DOWN_OUT)) //到达楼层,停下开门5秒
  451.              {   
  452.                  LED_OFF(LED_IN_Port,ElevState.CurrentFloor);
  453.                  LED_OFF(LED_OUT_DOWN_Port,ElevState.CurrentFloor);
  454.          ElevState.FloorCallTable[ElevState.CurrentFloor]&=~DOWN_IN; //到达相应的楼层从向下列表中清除   
  455.                  ElevState.FloorCallTable[ElevState.CurrentFloor]&=~DOWN_OUT; //到达相应的楼层从向下列表中清除   
  456.                  ElevState.FreeFlag=TRUE; //到达楼层,暂时进入空闲状态         
  457.                  ElevWorkState(STOP);     //修改电梯状态为停止态
  458.                WaitDoorOpen(DoorStayTime);    //延时等待电梯门打开
  459.                  delay_s(2*DoorStayTime);       //保持门开2秒让人进出
  460.                  WaitDoorClose(DoorStayTime);   //适当延时
  461.                  ElevWorkState(ElevState.Direction);   //等待门关好
  462.                  ElevState.FreeFlag=FALSE; //离开楼层,退出空闲状态
  463.                  ElevState.FloorTimerCount=0;     //计时器清0
  464.              }            
  465.         }        
  466.     }

  467. }  

  468. //扫描呼叫列表查看楼上或楼下是否有要向上的呼叫,有则返回TRUE,没有返回FALSE
  469. u8 FloorCall_UP(u8 floorside) // floorside  =  DOWN楼下  UP楼上
  470. {
  471.      u8 i;

  472.      if(floorside==UP)
  473.      {
  474.          for(i=ElevState.CurrentFloor+1;i<=MaxFloor;i++) //扫描呼叫列表楼上是否有要向上的呼叫
  475.          {
  476.              if(((ElevState.FloorCallTable[i]&UP_IN)==UP_IN)||((ElevState.FloorCallTable[i]&UP_OUT)==UP_OUT)) //如果扫描到上方楼层有向上的呼叫
  477.              {
  478.                  return TRUE;
  479.              }
  480.          }
  481.          return FALSE;
  482.      }
  483.      else
  484.      if(floorside==DOWN)
  485.      {
  486.          for(i=ElevState.CurrentFloor-1;i>=1;i--) //扫描呼叫列表楼下是否有要向上的呼叫
  487.          {
  488.              if(((ElevState.FloorCallTable[i]&UP_IN)==UP_IN)||((ElevState.FloorCallTable[i]&UP_OUT)==UP_OUT)) //如果扫描到上方楼层有向上的呼叫
  489.              {
  490.                  return TRUE;
  491.              }
  492.          }
  493.          return FALSE;
  494.      }
  495.      else return FALSE;
  496. }
  497. //扫描呼叫列表查看楼上或楼下是否有要向下的呼叫,有则返回TRUE,没有返回FALSE
  498. u8 FloorCall_DOWN(u8 floorside) // floorside  =  DOWN楼下  UP楼上
  499. {
  500.      u8 i;

  501.      if(floorside==UP)
  502.      {
  503.          for(i=ElevState.CurrentFloor+1;i<=MaxFloor;i++) //扫描呼叫列表楼上是否有要向下的呼叫
  504.          {
  505.              if(((ElevState.FloorCallTable[i]&DOWN_IN)==DOWN_IN)||((ElevState.FloorCallTable[i]&DOWN_OUT)==DOWN_OUT)) //如果扫描到上方楼层有向下的呼叫
  506.              {
  507.                  return TRUE;
  508.              }
  509.          }
  510.          return FALSE;
  511.      }
  512.      else
  513.      if(floorside==DOWN)
  514.      {
  515.          for(i=ElevState.CurrentFloor-1;i>=1;i--) //扫描呼叫列表楼下是否有要向下的呼叫
  516.          {
  517.              if(((ElevState.FloorCallTable[i]&DOWN_IN)==DOWN_IN)||((ElevState.FloorCallTable[i]&DOWN_OUT)==DOWN_OUT)) //如果扫描到上方楼层有向下的呼叫
  518.              {
  519.                  return TRUE;
  520.              }
  521.          }
  522.          return FALSE;
  523.      }
  524.      else return FALSE;
  525. }

  526. ////扫描呼叫列表是否为空(没有呼叫),空-返回TRUE  有呼叫-返回FALSE
  527. u8 DelNullCheck(void) //扫描呼叫列表是否空闲
  528. {
  529.   u8 i;
  530.     u8 result;
  531.         
  532.     for(i=1;i<=MaxFloor;i++)
  533.     {
  534.       if(ElevState.FloorCallTable[i]!=Null)
  535.         {
  536.              result=FALSE; //非空闲
  537.        break;
  538.         }
  539.         else if(i==MaxFloor) result=TRUE;  //空闲
  540.     }
  541.     return result;
  542. }
  543. //楼层呼叫处理函数(无需修改)
  544. void FloorCallCheck(void)
  545. {
  546.     if(DelNullCheck()==FALSE) //非空闲
  547.     {
  548.          ElevState.FreeFlag=FALSE; //退出空闲状态
  549.          ElevState.ElevRunning=TRUE;//正在运行标志打开
  550.     }
  551.     else  ElevState.FreeFlag=TRUE; //进入空闲状态
  552.     TurnHead_Check();
  553.   if((ElevState.FreeFlag==FALSE)&&(DOOR==CLOSE)) //非空闲下
  554.     {               
  555.      if(ElevState.Direction==UP)//方向向上
  556.          {
  557.             if((FloorCall_UP(UP)==TRUE)||(FloorCall_DOWN(UP)==TRUE)) //如果当前楼层上方有呼叫向上的 或 如果当前楼层上方有呼叫向下的
  558.                 {
  559.                     #if (USE_MODE==0)
  560.                   if(ElevState.FloorTimerCount>FloorStayTime) //检测是否到达楼层  如果接收到 到达楼层的限位开关信号,则当前楼层值+1(这里用定时器来模拟)
  561.                   {                                
  562.                       ElevState.FloorTimerCount=0;     //计时器清0
  563.                       ElevState.CurrentFloor++;//电梯继续往上走
  564.                   }
  565.                     #endif
  566.                     #if (USE_MODE==1)
  567.                   if(ElevState.ArriveFlag==TRUE) //检测是否到达楼层  如果接收到 到达楼层的限位开关信号,则当前楼层值+1
  568.                   {        
  569.             ElevState.ArriveFlag=FALSE; //清除标志                        
  570.                       ElevState.FloorTimerCount=0;     //计时器清0
  571.                       ElevState.CurrentFloor++;//电梯继续往上走
  572.                   }   
  573.           #endif                    
  574.                 }
  575.                 else ElevState.Direction=DOWN; //调头               
  576.          }
  577.          else
  578.          if(ElevState.Direction==DOWN)//方向向下
  579.          {
  580.             if((FloorCall_DOWN(DOWN)==TRUE)||(FloorCall_UP(DOWN)==TRUE)) //如果当前楼层下方有呼叫向下的 或 如果当前楼层下方有呼叫向上的
  581.                 {
  582.                     #if (USE_MODE==0)
  583.                   if(ElevState.FloorTimerCount>FloorStayTime) //检测是否到达楼层  如果接收到 到达楼层的限位开关信号,则当前楼层值+1(这里用定时器来模拟)
  584.                   {                                
  585.                       ElevState.FloorTimerCount=0;   
  586.                       ElevState.CurrentFloor--;//电梯继续往下走
  587.                   }
  588.                     #endif
  589.                     #if (USE_MODE==1)
  590.                   if(ElevState.ArriveFlag==TRUE) //检测是否到达楼层  如果接收到 到达楼层的限位开关信号,则当前楼层值+1
  591.                   {   
  592.             ElevState.ArriveFlag=FALSE; //清除标志                                
  593.                       ElevState.FloorTimerCount=0;   
  594.                       ElevState.CurrentFloor--;//电梯继续往下走
  595.                   }
  596.                     #endif
  597.                 }
  598.                 else ElevState.Direction=UP; //调头            
  599.          }
  600.     }
  601.     else
  602.     {        
  603.        ElevWorkState(STOP); //停止运行
  604.          ElevState.ElevRunning=FALSE;//正在运行标志关闭
  605.     }
  606. }

  607. void USART_SendByte(u8 dat)
  608. {
  609.     SBUF=dat;
  610.     while(!TI);  //等待发送数据完成
  611.     TI=0;                //清除发送完成标志位
  612. }
  613. void USART_Send(u8* arr,u16 len)
  614. {
  615.   u16 i;
  616.     for(i=0;i<len;i++)
  617.     {
  618.         SBUF=arr[i];
  619.       while(!TI);  //等待发送数据完成
  620.       TI=0;                //清除发送完成标志位  
  621.     }
  622. }
  623. void USART_SendStr(u8* str)
  624. {
  625.   while(1)
  626.     {
  627.       if(*str=='\0') break;
  628.         SBUF=*str++;
  629.         while(!TI);  //等待发送数据完成
  630.       TI=0;                //清除发送完成标志位
  631.     }
  632. }
  633. //系统初使化
  634. void SYSYEM_INIT(void)
  635. {
  636.      u8 i;
  637.      ElevState.CurrentFloor=1;
  638.      ElevState.Direction=UP;              //初使化方向为向上
  639.      ElevState.FloorTimerCount=0;            //定时器版计时清0
  640.      ElevState.FreeFlag=TRUE;             //初使化为空闲状态
  641.      ElevState.ElevRunning=FALSE;         //运行标志置FALSE  表示暂停运行
  642.      Usart.RX_COUNT=0;                    //串口接收计数清0
  643.      for(i=0;i<=MaxFloor;i++)
  644.      {
  645.          ElevState.FloorCallTable[i]=Null;  //初使化呼叫列表为Null
  646.      }
  647.      DOOR_Close;                          //关门
  648. }
  649. void main(void)
  650. {
  651.     SYSYEM_INIT();
  652.     EXTI0_Init();
  653.     EXTI1_Init();
  654.     TIMER0_Init();
  655.     USART_Config(9600);
  656.     USART_SendStr("Welcome to use Hailin's elevator program \r\n");
  657.   while(1)
  658.     {     
  659.          KeyPort_Y=0x00;   //不可删除
  660.          FloorCallCheck();
  661.        Elevator();   
  662.     }
  663. }
  664. void EXTI0_IRQHandler(void) interrupt 0   //楼层传感器中断
  665. {     
  666.     #if (USE_MODE==1)
  667.     ElevState.ArriveFlag=TRUE;//触发中断后表示到达楼层,让到达楼层标志置TRUE
  668.     #endif
  669. }
  670. void EXTI1_IRQHandler(void) interrupt 2    //矩阵按键中断
  671. {
  672.    KeyDatHandle(KeyScan()); //把KeyScan()按键扫描函数返回的按键值带入到KeyDatHandle()处理按键
  673. }
  674. void TIM0_IRQHandler(void)  interrupt 1    //定时模拟电梯上升和下降
  675. {
  676.    TH0=(65536-50000)/256;//定时50ms
  677.      TL0=(65536-50000)%256;//定时50ms
  678.    
  679.      TimerCount++;
  680.      if(TimerCount==20)  //1秒
  681.      {
  682.          TimerCount=0;
  683.          Timer_Second++;
  684.      }   
  685.      if(DelNullCheck()==FALSE) ElevState.FloorTimerCount++; //非空闲状态计时累加
  686.      else ElevState.FloorTimerCount=0;  //空闲状态计时清0
  687. }

  688. void USART_IRQHandler(void) interrupt 4  //用于电梯之间的通信
  689. {         
  690.   if(RI==1)    //判断是否为接收中断(串口中断分为发送中断和接收中断,均用同一个中断服务函数入口)
  691.     {
  692.         RI = 0;    //清除RI接收中断标志
  693.         Usart.RX_BUFF[Usart.RX_COUNT++]=SBUF;
  694.         if(Usart.RX_COUNT==USART_RX_LEN) Usart.RX_COUNT=0;
  695.     }   
  696. }
  697. /*Uart串口发送函数示例:
  698. 1.USART_SendByte(u8 dat) //发送单字节数据
  699.   例:USART_SendByte(0x04);

  700. 2.USART_Send(u8* arr,u16 len) //发送多字节数据
  701.   例:
  702.   Usart.TX_BUFF[0]=0xA1;
  703.   Usart.TX_BUFF[1]=0x08;
  704.   Usart.TX_BUFF[2]=0x04;
  705.   Usart.TX_BUFF[3]=0xF9;
  706.   USART_SendByte(Usart.TX_BUFF,4);
  707.   或
  708.   u8 Arr[16]={0xA1,0x08,0x04,0xF9};
  709.   USART_SendByte(Arr,4);

  710. 3.USART_SendStr(u8* str) //发送字符串数据
  711.   USART_SendStr("大吉在利,晚上吃鸡!\r\n");

  712. 4.有关电梯通信代码参考:
  713. <1>发送电梯当前楼层给其他设备:     USART_SendByte(ElevState.CurrentFloor);
  714. <2>发送电梯当前运行方向给其他设备: USART_SendByte(ElevState.Direction);
  715. <3>发送电梯当前所有数据给其他设备: USART_Send((u8*)(&ElevState),sizeof(ElevState));

  716. */

  717. /*Uart串口接收函数示例:
  718. 1.单字符指令接收:
  719. #include "reg51.h"
  720. void main(void)
  721. {
  722.    USART_Configure(9600);//配置9600波特率(默认无奇偶校验,1位停止位,8位数据位)
  723.    while(1)
  724.      {
  725.        if(Usart.RX_COUNT>0) //判断串口是否有接收
  726.          {
  727.            Usart.RX_COUNT=0;
  728.              if(Usart.RX_BUFF[0]=='A') //如果控制对象比较多请换成switch()
  729.              {
  730.                P1=0x0F;
  731.              }
  732.              if(Usart.RX_BUFF[0]=='B')
  733.              {
  734.                P1=0xF0;
  735.              }
  736.          }
  737.      }
  738. }
  739. 2.多字符指令接收:(为了方便,我们用C标准库自带的string.h)
  740. #include "reg51.h"
  741. #include <string.h>
  742. void main(void)
  743. {
  744.    char xbuff[20];
  745.    USART_Configure(9600);//配置9600波特率(默认无奇偶校验,1位停止位,8位数据位)
  746.    while(1)
  747.      {
  748.        if(Usart.RX_COUNT>4) //判断串口是否接收到指令(设指令格式为:开灯/  关灯/  用/来表示指令结束符)
  749.          {
  750.            if(Usart.RX_BUFF[4]=='/') //断判结束符
  751.              {
  752.                  Usart.RX_COUNT=0;
  753.                  strncpy(xbuff, Usart.RX_BUFF+0 , 4);//+0表示从接收缓存的第0个字符开始截取4个字符到xbuff判断指令
  754.                  if(strncmp(xbuff,"开灯",4) == 0)
  755. ……………………

  756. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
16层电梯.zip (102.19 KB, 下载次数: 21)



评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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