找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于51单片机的八层电梯设计代码

[复制链接]
跳转到指定楼层
楼主
ID:1137639 发表于 2026-2-11 17:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  • /*-----------------------单梯实验程序----------------------------/
  • /*************************电梯主程序*****************************/
  • #include "reg51.h"
  • #include "intrins.h"
  • /***********************楼梯参数设置*****************************/
  • #define MaxFloor      8  //电梯总楼层
  • #define FloorStayTime 10//40 //单位:50ms, 楼层停留时间:40*50ms=2S
  • #define DoorStayTime  2  //单位:S   , 电梯门停留时间
  • #define SEG_Num       2  //数码管数量(当楼层总数<=8时,楼层显示可用
  •                          //1位或2位数码管显示,当设为1时请在仿真中
  •                                                  //删除第一个595芯片,并把信号线直接接到第二
  •                                                  //个595即可)
  • /****************************************************************/
  • /***********************程序工作模式选择**************************/
  • #define USE_MODE 0   //0-定时模拟
  • /****************************************************************/
  • /*********************平台移植部分代码****************************/
  • //定时器模拟版接口:
  • #if (USE_MODE==0)
  • sbit DOOR=P3^5;        //电梯门开关控制信号
  • sbit ElevMotor_P=P3^6; //电梯电机正极控制信号
  • sbit ElevMotor_N=P3^7; //电梯电机负极控制信号
  • sbit SHCP=P0^5;        //74HC595  LED、数码管显示驱动
  • sbit DS=P0^6;          //74HC595  LED、数码管显示驱动
  • sbit STCP=P0^7;        //74HC595  LED、数码管显示驱动
  • #define KeyPort_X  P1  //矩阵按键接口
  • #define KeyPort_Y  P2  //矩阵按键接口
  • #endif
  • //除以上定义的IO外,还需用到P33作为矩阵键盘的中断触发引脚
  • //8路与门:用8路与非门CD4068或74LS30+输出端接一个三极管反向电平。
  • //传感器版接口:
  • #if (USE_MODE==1)
  • sbit DOOR_CLOSE_SENSOR=P3^4;//电梯门关闭检测传感器输入
  • sbit DOOR=P3^5;        //电梯门开关控制信号
  • sbit ElevMotor_P=P3^6; //电梯电机正极控制信号
  • sbit ElevMotor_N=P3^7; //电梯电机负极控制信号
  • sbit SHCP=P0^5;        //74HC595  LED、数码管显示驱动
  • sbit DS=P0^6;          //74HC595  LED、数码管显示驱动
  • sbit STCP=P0^7;        //74HC595  LED、数码管显示驱动
  • #define KeyPort_X  P1  //矩阵按键接口
  • #define KeyPort_Y  P2  //矩阵按键接口
  • #endif
  • //除以上定义的IO外,还需用到P33作为矩阵键盘的中断触发引脚
  • //需用到P32作为楼层限位开关触发中断引脚
  • //每个楼层一个限位开关,接在N路输入的与门芯片上
  • //如果大于8层,可用两个8路输入的与门芯片+一个2路的与门芯片组合
  • /****************************************************************/
  • //以下为程序源码,用户不可改动
  • #define u8  unsigned char
  • #define u16 unsigned int
  • #define TRUE  1    //真
  • #define FALSE 0    //假
  • //电梯运行状态
  • #define Null  0     //空闲
  • #define STOP  1     //停止
  • #define UP    2     //向上
  • #define DOWN  3     //向下
  • #define UP_IN     0x01     //内部向上标记(在呼叫列表中的标记  用bit0标记)
  • #define UP_OUT    0x02     //外部向上标记(在呼叫列表中的标记  用bit1标记)
  • #define DOWN_IN   0x04     //内部向下标记(在呼叫列表中的标记  用bit2标记)
  • #define DOWN_OUT  0x08     //外部向下标记(在呼叫列表中的标记  用bit3标记)
  • #define Elev_UP    ElevMotor_P=0;ElevMotor_N=1  //低电平有效
  • #define Elev_DOWN  ElevMotor_P=1;ElevMotor_N=0  //低电平有效  电机正转
  • #define Elev_STOP  ElevMotor_P=1;ElevMotor_N=1  //低电平有效  电机反转
  • #define OPEN  1
  • #define CLOSE 0
  • #define DOOR_Open  DOOR=OPEN     //开门
  • #define DOOR_Close DOOR=CLOSE    //关门
  • #define SHCP_H SHCP=1
  • #define SHCP_L SHCP=0
  • #define DS_H   DS=1
  • #define DS_L   DS=0
  • #define STCP_H STCP=1
  • #define STCP_L STCP=0
  • #if MaxFloor>8
  • #define MHC595_NUM 8
  • #else
  • #define MHC595_NUM 5
  • #endif
  • #define SEGPort 0x01
  • #define LED_IN_Port 0x02
  • #define LED_OUT_UP_Port 0x03
  • #define LED_OUT_DOWN_Port 0x04
  • //FloorCallTable[]呼叫列表说明:该列表由数组构成,下标和每个楼层一一对应,如FloorCallTable[1]表示1楼的呼叫状态
  • // bit3-DOWN_OUT  bit2-DOWN_IN  bit1-UP_OUT  bit0-UP_IN   bit=0为没有呼叫,=1为有呼叫
  • typedef struct
  • {
  •         u8 ElevRunning;      //电梯运行状态标志
  •         u8 CurrentFloor;     //当前电梯所处楼层
  •         u8 Direction;        //电梯运行方向
  •         u8 FloorCallTable[MaxFloor+1];//数组[0]不用,从[1]开始使用 ,呼叫列表(所有楼层呼叫的信息均保存于此)
  •         u8 FloorTimerCount;         //计时
  •         u8 ArriveFlag;       //到达楼层信号(用于停止或在前一楼层提前加减速)(定时器模拟的用不到)
  •         u8 FreeFlag;             //电梯空闲状态标志
  • }TYPEDEF_ELEVSTATE;
  • TYPEDEF_ELEVSTATE ElevState; //电梯状态结构体
  • //u8 code SEG_NUM[]={0x3f,0x06,0x5b,0x4f,0x66,0x6D,0x7D,0x07,0x7f,0x6f};   //共阴SEG数码管段码  0~9
  • u8 code SEG_NUM[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //共阳SEG数码管段码  0~F
  • u16 code LED_NUM[]={0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};   //SEG数码管段码  0~9
  • u8 HC595_BUFF[MHC595_NUM]={0};
  • u8 Timer_Second;
  • u16 TimerCount;
  • u8 ExternKey[2]={0}; //外部按键按下信息
  • u8 FloorCallTableBUFF[MaxFloor+10]={0};
  • u8 KeyPressFlag=0;
  • #define Uart_RX_LEN 20  //接收缓存长度(请勿超过芯片rom剩余大小)
  • typedef struct
  • {
  •         u8 RX_BUFF[Uart_RX_LEN]; //接收缓存
  •         u8 TX_BUFF[Uart_RX_LEN]; //发送缓存
  •         u16 RX_COUNT;
  • }UART;
  • UART Uart;
  • void delay_ms(u16 xms); //ms延时
  • void delay_s(u8 xs);    //s延时
  • void EXTI0_Init(void);
  • void EXTI1_Init(void);
  • void TIMER0_Init(void);
  • void HC595_Send(u8 *p);
  • u8 KeyScan(void);
  • void KeyDatHandle(u8 key);
  • void WaitDoorOpen(u8 ts);
  • void WaitDoorClose(u8 ts);
  • void SEG_Display(u8 segnum);
  • void LED_ON(u8 addr,u8 lednum);
  • void LED_OFF(u8 addr,u8 lednum);
  • void ElevWorkState(u8 state);
  • void Elevator(void);
  • u8 FloorCall_UP(u8 floorside);
  • u8 FloorCall_DOWN(u8 floorside);
  • u8 DelNullCheck(void);
  • void FloorCallCheck(void);
  • void SYSYEM_INIT(void);
  • void delay_ms(u16 xms)
  • {
  •         u8 i;
  •         u16 t;
  •   for(t=xms;t>0;t--)
  •           for(i=112;i>0;i--);
  • }
  • void delay_s(u8 xs)
  • {
  •         TimerCount=0;
  •         Timer_Second=0;
  •         while(Timer_Second<xs);
  • }
  • void EXTI0_Init(void)
  • {
  •         EA = 1;
  •         IT0= 1; //下降沿触发
  •         EX0= 1;
  • }
  • void EXTI1_Init(void)
  • {
  •         EA = 1;
  •         IT1= 1; //下降沿触发
  •         EX1= 1;
  • }
  • void Timer0_Init(void)
  • {
  •         TMOD |= 0x01;
  •         TH0=(65536-50000)/256;
  •         TL0=(65536-50000)%256;
  •         EA = 1;
  •         ET0 = 1;
  •         TR0 = 1;
  • }
  • void HC595_Send(u8 *p)
  • {
  •         u8 i,j;
  •         u8 temp;
  •         for(i=MHC595_NUM;i>2-SEG_Num;i--)
  •         {
  •                 temp=p[i-1];
  •                 for(j=0;j<8;j++)
  •                 {
  •                   DS=temp&0x80;
  •                   temp<<=1;
  •                   SHCP_L;
  •                   SHCP_H;
  •                 }
  •         }
  •         STCP_L;
  •         STCP_H;
  • }
  • /*键盘剪裁说明:
  • 按键扫描函数 8*8  如要改为4*4或其他
  • 请把KeyPort_Y 和 KeyPort_X 对应的IO口数量减少,如4*4,则用KeyPort_Y低4位和KeyPort_X高4位
  • 键盘分布如下:(序号和IO口高低位对应)
  •        P20      ->         P27
  •             Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7
  • P10         X0 *  *  *  *  *  *  *  *                57 58 59 60 61 62 63 64
  •          X1 *  *  *  *  *  *  *  *                49 50 51 52 53 54 55 56
  •          X2 *  *  *  *  *  *  *  *                41 42 43 44 45 46 47 48
  • |         X3 *  *  *  *  *  *  *  *  对应按键扫描  33 34 35 36 37 38 39 40  仿真文件
  • |         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
  •          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
  •          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
  • 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
  • */
  • //KeyScan()扫描函数兼容8*8以下所有键盘,键盘改小时无需修改
  • u8 KeyScan(void)
  • {
  •         u8 keynum;
  •         KeyPort_Y=0x00;
  •         KeyPort_X=0xFF;
  •         _nop_(); _nop_(); _nop_(); _nop_();
  •         if(KeyPort_X!=0xFF)
  •         {
  •          delay_ms(10);
  •          if(KeyPort_X!=0xFF)
  •          {
  •                  switch(KeyPort_X)
  •                  {
  •                          case 0x7F: keynum=1;   break;
  •                          case 0xBF: keynum=9;   break;
  •                          case 0xDF: keynum=17;  break;
  •                          case 0xEF: keynum=25;  break;
  •                          case 0xF7: keynum=33;  break;
  •                          case 0xFB: keynum=41;  break;
  •                          case 0xFD: keynum=49;  break;
  •                          case 0xFE: keynum=57;  break;
  •                  }
  •                  KeyPort_Y=0xFF;
  •                  KeyPort_X=0x00;
  •                  _nop_(); _nop_(); _nop_(); _nop_();
  •                  if(KeyPort_Y!=0xFF)
  •                  {
  •                          switch(KeyPort_Y)
  •                          {
  •                                  case 0xFE: keynum=keynum+0;  break;
  •                                  case 0xFD: keynum=keynum+1;  break;
  •                                  case 0xFB: keynum=keynum+2;  break;
  •                                  case 0xF7: keynum=keynum+3;  break;
  •                                  case 0xEF: keynum=keynum+4;  break;
  •                                  case 0xDF: keynum=keynum+5;  break;
  •                                  case 0xBF: keynum=keynum+6;  break;
  •                                  case 0x7F: keynum=keynum+7;  break;
  •                          }
  •                  }
  •                  KeyPort_Y=0x00;
  •    }
  •         }
  •         else keynum=0;
  •         return keynum;
  • }
  • //键值处理函数:当键盘键值需要改动时,请根据上面的键值改动
  • void KeyDatHandle(u8 key)
  • {
  •         u8 tempkey;
  •         if(key==0)
  •         {
  •         }
  •         else
  •         if(((key>0)&&(key<=8))||((key>32)&&(key<=40))) //楼梯内的楼层选择按键(使用1-8 和 33-40作为按键)
  •         {
  •                 if(key>32) tempkey=key-32+8;
  •                 else       tempkey=key;
  •                 if(tempkey<=MaxFloor)
  •                 {
  •                         LED_ON(LED_IN_Port,tempkey);
  •                         if(((tempkey>ElevState.CurrentFloor)&&(tempkey<MaxFloor))||(tempkey==1)) ElevState.FloorCallTable[tempkey]|=UP_IN;//内部按1只能往上
  •                         else
  •                         if((tempkey<ElevState.CurrentFloor)||(tempkey==MaxFloor)) ElevState.FloorCallTable[tempkey]|=DOWN_IN;
  •                 }
  •         }
  •         else
  •         if(((key>9)&&(key<=16))||((key>40)&&(key<=48)))  //每个楼层门口外的向下按键(底楼按向下无效)(使用10-16 和 41-48作为按键)
  •         {
  •                  if(key>40) tempkey=key-40+8;
  •                  else       tempkey=key-8;
  •                  if((tempkey>1)&&(tempkey<=MaxFloor))
  •                  {
  •                          LED_ON(LED_OUT_DOWN_Port,tempkey);
  •                          ElevState.FloorCallTable[tempkey]|=DOWN_OUT;
  •                  }
  •         }
  •         else
  •         if(((key>16)&&(key<=24))||((key>48)&&(key<56))) //每个楼层门口外的向上按键(顶楼按向上无效)(使用17-24 和 49-55作为按键)
  •         {
  •                  if(key>48) tempkey=key-48+8;
  •                  else       tempkey=key-16;
  •                  if(tempkey<MaxFloor)
  •                  {
  •                          LED_ON(LED_OUT_UP_Port,tempkey);
  •                          ElevState.FloorCallTable[tempkey]|=UP_OUT;
  •                  }
  •         }
  •         else
  •         if(key==25)  //开门   (使用25 作为按键)
  •         {
  •                 if(ElevState.ElevRunning==FALSE)
  •                 {
  •                   if(DOOR==CLOSE) DOOR_Open;
  •                 }
  •         }
  •         else
  •         if(key==26) //关门    (使用26 作为按键)
  •         {
  •                 if(DOOR==OPEN)
  •                 {
  •                         DOOR_Close;
  •                         ElevState.FloorTimerCount=0;         //计时器清0
  •                 }
  •         }
  • }
  • //第待开门
  • void WaitDoorOpen(u8 ts)
  • {
  •         DOOR_Open;
  •         delay_s(ts);
  • }
  • //第待关门
  • void WaitDoorClose(u8 ts)
  • {
  •         DOOR_Close;
  •         #if (USE_MODE==0)
  •         delay_s(ts);
  •         #endif
  •         #if (USE_MODE==1)
  •         ts=ts; //防止警告
  •         while(DOOR_CLOSE_SENSOR==OPEN);
  •         #endif
  • }
  • //数码管显示驱动
  • void SEG_Display(u8 segnum)
  • {
  •         HC595_BUFF[0]=SEG_NUM[segnum/10];
  •         HC595_BUFF[1]=SEG_NUM[segnum%10];
  •         HC595_Send(HC595_BUFF);
  • }
  • //LED显示驱动
  • void LED_ON(u8 addr,u8 lednum)
  • {
  •         switch(addr)
  •         {
  •                 case LED_IN_Port:        if(lednum<9)   HC595_BUFF[2]|=LED_NUM[lednum];
  •                                                                  else           HC595_BUFF[5]|=LED_NUM[lednum-8]; break;
  •                 case LED_OUT_DOWN_Port:  if(lednum<9)   HC595_BUFF[3]|=LED_NUM[lednum];
  •                                                                  else           HC595_BUFF[6]|=LED_NUM[lednum-8]; break;
  •                 case LED_OUT_UP_Port:    if(lednum<9)   HC595_BUFF[4]|=LED_NUM[lednum];
  •                                                                  else           HC595_BUFF[7]|=LED_NUM[lednum-8]; break;
  •         }
  •         HC595_Send(HC595_BUFF);
  • }
  • //LED显示驱动
  • void LED_OFF(u8 addr,u8 lednum)
  • {
  •         switch(addr)
  •         {
  •                 case LED_IN_Port:        if(lednum<9)  HC595_BUFF[2]&=~LED_NUM[lednum];
  •                                      else          HC595_BUFF[5]&=~LED_NUM[lednum-8]; break;
  •                 case LED_OUT_DOWN_Port:  if(lednum<9)  HC595_BUFF[3]&=~LED_NUM[lednum];
  •                                                                  else          HC595_BUFF[6]&=~LED_NUM[lednum-8]; break;
  •                 case LED_OUT_UP_Port:    if(lednum<9)  HC595_BUFF[4]&=~LED_NUM[lednum];
  •                                                                  else          HC595_BUFF[7]&=~LED_NUM[lednum-8]; break;
  •         }
  •         HC595_Send(HC595_BUFF);
  • }
  • //电梯运行状态设置
  • void ElevWorkState(u8 state)
  • {
  •   if(state==UP)
  •         {
  •                 Elev_UP;
  •                 ElevState.ElevRunning=TRUE;
  •         }
  •         else
  •         if(state==DOWN)
  •         {
  •                 Elev_DOWN;
  •                 ElevState.ElevRunning=TRUE;
  •         }
  •         else
  •         if(state==STOP)
  •         {
  •                 Elev_STOP;
  •                 ElevState.ElevRunning=FALSE;
  •         }
  •         SEG_Display(ElevState.CurrentFloor);                //数码管显示
  • }
  • //调头检测函数
  • void TurnHead_Check(void)
  • {
  •         if(ElevState.CurrentFloor==1)
  •         {
  •                 ElevState.Direction=UP;  //1楼调头
  •         }
  •         else if(ElevState.CurrentFloor==MaxFloor)
  •         {
  •                 ElevState.Direction=DOWN; //顶楼调头
  •         }
  • }
  • //电梯运行函数
  • void Elevator(void)
  • {
  •         if((DOOR==OPEN)||(ElevState.FreeFlag==TRUE)) ElevWorkState(STOP);
  •         else   ElevWorkState(ElevState.Direction);
  •         TurnHead_Check();  //调头检测
  •         if(ElevState.Direction==UP)  //电梯正在向上运行的情况
  •         {
  •                 if(ElevState.CurrentFloor<=MaxFloor)  //扫描呼叫列表中的向上方向的呼叫楼层
  •                 {
  •                          if(((ElevState.FloorCallTable[ElevState.CurrentFloor]&UP_IN)==UP_IN)||((ElevState.FloorCallTable[ElevState.CurrentFloor]&UP_OUT)==UP_OUT)) //到达目标楼层,停下开门5秒
  •                          {
  •                                  LED_OFF(LED_IN_Port,ElevState.CurrentFloor);
  •                                  LED_OFF(LED_OUT_UP_Port,ElevState.CurrentFloor);
  •                                  ElevState.FloorCallTable[ElevState.CurrentFloor]&=~UP_IN; //到达相应的楼层从向上列表中清除
  •                                  ElevState.FloorCallTable[ElevState.CurrentFloor]&=~UP_OUT; //到达相应的楼层从向上列表中清除
  •                                  ElevState.FreeFlag=TRUE; //到达楼层,暂时进入空闲状态
  •                                  ElevWorkState(STOP);     //修改电梯状态为停止态
  •                              WaitDoorOpen(DoorStayTime);    //延时等待电梯门打开
  •                                  delay_s(2*DoorStayTime);       //适当延时
  •                                  WaitDoorClose(DoorStayTime);   //等待门关好
  •                                  ElevWorkState(ElevState.Direction);
  •                                  ElevState.FreeFlag=FALSE; //离开楼层,退出空闲状态
  •                                  ElevState.FloorTimerCount=0;         //计时器清0
  •                          }
  •                 }
  •         }
  •         else
  •         if(ElevState.Direction==DOWN)  //电梯正在向下运行的情况
  •         {
  •                 if(ElevState.CurrentFloor>=1)  //扫描呼叫列表中的向下方向的呼叫楼层
  •                 {
  •                          if(((ElevState.FloorCallTable[ElevState.CurrentFloor]&DOWN_IN)==DOWN_IN)||((ElevState.FloorCallTable[ElevState.CurrentFloor]&DOWN_OUT)==DOWN_OUT)) //到达楼层,停下开门5秒
  •                          {
  •                                  LED_OFF(LED_IN_Port,ElevState.CurrentFloor);
  •                                  LED_OFF(LED_OUT_DOWN_Port,ElevState.CurrentFloor);
  •                                  ElevState.FloorCallTable[ElevState.CurrentFloor]&=~DOWN_IN; //到达相应的楼层从向下列表中清除
  •                                  ElevState.FloorCallTable[ElevState.CurrentFloor]&=~DOWN_OUT; //到达相应的楼层从向下列表中清除
  •                                  ElevState.FreeFlag=TRUE; //到达楼层,暂时进入空闲状态
  •                                  ElevWorkState(STOP);     //修改电梯状态为停止态
  •                                  WaitDoorOpen(DoorStayTime);    //延时等待电梯门打开
  •                                  delay_s(2*DoorStayTime);       //保持门开2秒让人进出
  •                                  WaitDoorClose(DoorStayTime);   //适当延时
  •                                  ElevWorkState(ElevState.Direction);   //等待门关好
  •                                  ElevState.FreeFlag=FALSE; //离开楼层,退出空闲状态
  •                                  ElevState.FloorTimerCount=0;         //计时器清0
  •                          }
  •                 }
  •         }
  • }
  • //扫描呼叫列表查看楼上或楼下是否有要向上的呼叫,有则返回TRUE,没有返回FALSE
  • u8 FloorCall_UP(u8 floorside) // floorside  =  DOWN楼下  UP楼上
  • {
  •          u8 i;
  •          if(floorside==UP)
  •          {
  •                  for(i=ElevState.CurrentFloor+1;i<=MaxFloor;i++) //扫描呼叫列表楼上是否有要向上的呼叫
  •                  {
  •                          if(((ElevState.FloorCallTable&UP_IN)==UP_IN)||((ElevState.FloorCallTable&UP_OUT)==UP_OUT)) //如果扫描到上方楼层有向上的呼叫
  •                          {
  •                                  return TRUE;
  •                          }
  •                  }
  •                  return FALSE;
  •          }
  •          else
  •          if(floorside==DOWN)
  •          {
  •                  for(i=ElevState.CurrentFloor-1;i>=1;i--) //扫描呼叫列表楼下是否有要向上的呼叫
  •                  {
  •                          if(((ElevState.FloorCallTable&UP_IN)==UP_IN)||((ElevState.FloorCallTable&UP_OUT)==UP_OUT)) //如果扫描到上方楼层有向上的呼叫
  •                          {
  •                                  return TRUE;
  •                          }
  •                  }
  •                  return FALSE;
  •          }
  •          else return FALSE;
  • }
  • //扫描呼叫列表查看楼上或楼下是否有要向下的呼叫,有则返回TRUE,没有返回FALSE
  • u8 FloorCall_DOWN(u8 floorside) // floorside  =  DOWN楼下  UP楼上
  • {
  •          u8 i;
  •          if(floorside==UP)
  •          {
  •                  for(i=ElevState.CurrentFloor+1;i<=MaxFloor;i++) //扫描呼叫列表楼上是否有要向下的呼叫
  •                  {
  •                          if(((ElevState.FloorCallTable&DOWN_IN)==DOWN_IN)||((ElevState.FloorCallTable&DOWN_OUT)==DOWN_OUT)) //如果扫描到上方楼层有向下的呼叫
  •                          {
  •                                  return TRUE;
  •                          }
  •                  }
  •                  return FALSE;
  •          }
  •          else
  •          if(floorside==DOWN)
  •          {
  •                  for(i=ElevState.CurrentFloor-1;i>=1;i--) //扫描呼叫列表楼下是否有要向下的呼叫
  •                  {
  •                          if(((ElevState.FloorCallTable&DOWN_IN)==DOWN_IN)||((ElevState.FloorCallTable&DOWN_OUT)==DOWN_OUT)) //如果扫描到上方楼层有向下的呼叫
  •                          {
  •                                  return TRUE;
  •                          }
  •                  }
  •                  return FALSE;
  •          }
  •          else return FALSE;
  • }
  • ////扫描呼叫列表是否为空(没有呼叫),空-返回TRUE  有呼叫-返回FALSE
  • u8 DelNullCheck(void) //扫描呼叫列表是否空闲
  • {
  •         u8 i;
  •         u8 result;
  •         for(i=1;i<=MaxFloor;i++)
  •         {
  •           if(ElevState.FloorCallTable!=Null)
  •                 {
  •                          result=FALSE; //非空闲
  •        break;
  •                 }
  •                 else if(i==MaxFloor) result=TRUE;  //空闲
  •         }
  •         return result;
  • }
  • //楼层呼叫处理函数(无需修改)
  • void FloorCallCheck(void)
  • {
  •         if(DelNullCheck()==FALSE) //非空闲
  •         {
  •                  ElevState.FreeFlag=FALSE; //退出空闲状态
  •                  ElevState.ElevRunning=TRUE;//正在运行标志打开
  •         }
  •         else  ElevState.FreeFlag=TRUE; //进入空闲状态
  •         TurnHead_Check();
  •         if((ElevState.FreeFlag==FALSE)&&(DOOR==CLOSE)) //非空闲下
  •         {
  •      if(ElevState.Direction==UP)//方向向上
  •                  {
  •                     if((FloorCall_UP(UP)==TRUE)||(FloorCall_DOWN(UP)==TRUE)) //如果当前楼层上方有呼叫向上的 或 如果当前楼层上方有呼叫向下的
  •                                 {
  •                                   if(ElevState.FloorTimerCount>FloorStayTime) //检测是否到达楼层  如果接收到 到达楼层的限位开关信号,则当前楼层值+1(这里用定时器来模拟)
  •                                   {
  •                                           ElevState.FloorTimerCount=0;         //计时器清0
  •                                           ElevState.CurrentFloor++;//电梯继续往上走
  •                                   }
  •                                 }
  •                                 else ElevState.Direction=DOWN; //调头
  •                  }
  •                  else
  •                  if(ElevState.Direction==DOWN)//方向向下
  •                  {
  •                     if((FloorCall_DOWN(DOWN)==TRUE)||(FloorCall_UP(DOWN)==TRUE)) //如果当前楼层下方有呼叫向下的 或 如果当前楼层下方有呼叫向上的
  •                                 {
  •                                   if(ElevState.FloorTimerCount>FloorStayTime) //检测是否到达楼层 (这里用定时器来模拟)
  •                                   {
  •                                           ElevState.FloorTimerCount=0;
  •                                           ElevState.CurrentFloor--;//电梯继续往下走
  •                                   }
  •                                 }
  •                                 else ElevState.Direction=UP; //调头
  •                  }
  •         }
  •         else
  •         {
  •                 ElevWorkState(STOP); //停止运行
  •                 ElevState.ElevRunning=FALSE;//正在运行标志关闭
  •         }
  • }
  • //系统初使化
  • void SYSYEM_INIT(void)
  • {
  •          u8 i;
  •          ElevState.CurrentFloor=1;
  •          ElevState.Direction=UP;              //初使化方向为向上
  •          ElevState.FloorTimerCount=0;                //定时器版计时清0
  •          ElevState.FreeFlag=TRUE;             //初使化为空闲状态
  •          ElevState.ElevRunning=FALSE;         //运行标志置FALSE  表示暂停运行
  •          Uart.RX_COUNT=0;                    //串口接收计数清0
  •          for(i=0;i<=MaxFloor;i++)
  •          {
  •                  ElevState.FloorCallTable=Null;  //初使化呼叫列表为Null
  •          }
  •          DOOR_Close;                          //关门
  • }
  • void EXTI0_IRQHandler(void) interrupt 0   //楼层传感器中断
  • {
  •         #if (USE_MODE==1)
  •         ElevState.ArriveFlag=TRUE;//触发中断后表示到达楼层,让到达楼层标志置TRUE
  •         #endif
  • }
  • void EXTI1_IRQHandler(void) interrupt 2    //矩阵按键中断
  • {
  •    KeyDatHandle(KeyScan()); //把KeyScan()按键扫描函数返回的按键值带入到KeyDatHandle()处理按键
  • }
  • void TIM0_IRQHandler(void)  interrupt 1    //定时模拟电梯上升和下降
  • {
  •          TH0=(65536-50000)/256;//定时50ms
  •          TL0=(65536-50000)%256;//定时50ms
  •          TimerCount++;
  •          if(TimerCount==20)  //1秒
  •          {
  •                  TimerCount=0;
  •                  Timer_Second++;
  •          }
  •          if(DelNullCheck()==FALSE) ElevState.FloorTimerCount++; //非空闲状态计时累加
  •          else ElevState.FloorTimerCount=0;  //空闲状态计时清0
  • }
  • void Uart_IRQHandler(void) interrupt 4  //用于电梯之间的通信
  • {
  •   if(RI==1)        //判断是否为接收中断(串口中断分为发送中断和接收中断,均用同一个中断服务函数入口)
  •         {
  •                 RI = 0;        //清除RI接收中断标志
  •                 Uart.RX_BUFF[Uart.RX_COUNT++]=SBUF;
  •                 if(Uart.RX_COUNT==Uart_RX_LEN) Uart.RX_COUNT=0;
  •         }
  • }
  • void main(void)  //主函数
  • {
  •         SYSYEM_INIT();
  •         EXTI0_Init();
  •         EXTI1_Init();
  •         TIMER0_Init();
  •         while(1)
  •         {
  •                  KeyPort_Y=0x00;   //不可删除
  •                  FloorCallCheck();
  •                  Elevator();
  •         }
  • }


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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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