|
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.png (83.28 KB, 下載次數(shù): 41)
下載附件
2020-12-2 23:39 上傳
單片機(jī)源程序如下:
- /*************************電梯主程序*****************************/
- #include "reg51.h"
- #include "intrins.h"
- /*********************程序選擇****************************/
- #define USE_MODE 0 //0-定時模擬 1-傳感器
- /****************************************************************/
- /*********************平臺移植部分代碼****************************/
- //定時器模擬版接口:
- #if (USE_MODE==0)
- sbit DOOR=P3^5; //電梯門開關(guān)控制信號
- sbit ElevMotor_P=P3^6; //電梯電機(jī)正極控制信號
- sbit ElevMotor_N=P3^7; //電梯電機(jī)負(fù)極控制信號
- sbit SHCP=P0^5; //74HC595 LED、數(shù)碼管顯示驅(qū)動
- sbit DS=P0^6; //74HC595 LED、數(shù)碼管顯示驅(qū)動
- sbit STCP=P0^7; //74HC595 LED、數(shù)碼管顯示驅(qū)動
- #define KeyPort_X P1 //矩陣按鍵接口
- #define KeyPort_Y P2 //矩陣按鍵接口
- #endif
- //除以上定義的IO外,還需用到P33作為矩陣鍵盤的中斷觸發(fā)引腳
- //8路與門:用8路與非門CD4068或74LS30+輸出端接一個三極管反向電平。
- //傳感器版接口:
- #if (USE_MODE==1)
- sbit DOOR_CLOSE_SENSOR=P3^4;//電梯門關(guān)閉檢測傳感器輸入
- sbit DOOR=P3^5; //電梯門開關(guān)控制信號
- sbit ElevMotor_P=P3^6; //電梯電機(jī)正極控制信號
- sbit ElevMotor_N=P3^7; //電梯電機(jī)負(fù)極控制信號
- sbit SHCP=P0^5; //74HC595 LED、數(shù)碼管顯示驅(qū)動
- sbit DS=P0^6; //74HC595 LED、數(shù)碼管顯示驅(qū)動
- sbit STCP=P0^7; //74HC595 LED、數(shù)碼管顯示驅(qū)動
- #define KeyPort_X P1 //矩陣按鍵接口
- #define KeyPort_Y P2 //矩陣按鍵接口
- #endif
- //除以上定義的IO外,還需用到P33作為矩陣鍵盤的中斷觸發(fā)引腳
- //需用到P32作為樓層限位開關(guān)觸發(fā)中斷引腳
- //每個樓層一個限位開關(guān),接在N路輸入的與門芯片上
- //如果大于8層,可用兩個8路輸入的與門芯片+一個2路的與門芯片組合
- /****************************************************************/
- /***********************樓梯參數(shù)設(shè)置*****************************/
- #define MaxFloor 16 //電梯總樓層(最大16)
- #define FloorStayTime 40 //單位:50ms, 樓層停留時間:40*50ms=2S
- #define DoorStayTime 2 //單位:S , 電梯門停留時間
- #define SEG_Num 2 //數(shù)碼管數(shù)量(為1時請刪除第一個數(shù)碼管的595)
- /****************************************************************/
- #define u8 unsigned char
- #define u16 unsigned int
-
- #define TRUE 1 //真
- #define FALSE 0 //假
- //電梯運行狀態(tài)
- #define Null 0 //空閑
- #define STOP 1 //停止
- #define UP 2 //向上
- #define DOWN 3 //向下
- #define UP_IN 0x01 //內(nèi)部向上標(biāo)記(在呼叫列表中的標(biāo)記 用bit0標(biāo)記)
- #define UP_OUT 0x02 //外部向上標(biāo)記(在呼叫列表中的標(biāo)記 用bit1標(biāo)記)
- #define DOWN_IN 0x04 //內(nèi)部向下標(biāo)記(在呼叫列表中的標(biāo)記 用bit2標(biāo)記)
- #define DOWN_OUT 0x08 //外部向下標(biāo)記(在呼叫列表中的標(biāo)記 用bit3標(biāo)記)
- #define Elev_UP ElevMotor_P=0;ElevMotor_N=1 //低電平有效
- #define Elev_DOWN ElevMotor_P=1;ElevMotor_N=0 //低電平有效 電機(jī)正轉(zhuǎn)
- #define Elev_STOP ElevMotor_P=1;ElevMotor_N=1 //低電平有效 電機(jī)反轉(zhuǎn)
- #define OPEN 1
- #define CLOSE 0
- #define DOOR_Open DOOR=OPEN //開門
- #define DOOR_Close DOOR=CLOSE //關(guān)門
- #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[]呼叫列表說明:該列表由數(shù)組構(gòu)成,下標(biāo)和每個樓層一一對應(yīng),如FloorCallTable[1]表示1樓的呼叫狀態(tài)
- // bit3-DOWN_OUT bit2-DOWN_IN bit1-UP_OUT bit0-UP_IN bit=0為沒有呼叫,=1為有呼叫
- typedef struct
- {
- u8 ElevRunning; //電梯運行狀態(tài)標(biāo)志
- u8 CurrentFloor; //當(dāng)前電梯所處樓層
- u8 Direction; //電梯運行方向
- u8 FloorCallTable[MaxFloor+1];//數(shù)組[0]不用,從[1]開始使用 ,呼叫列表(所有樓層呼叫的信息均保存于此)
- u8 FloorTimerCount; //計時
- u8 ArriveFlag; //到達(dá)樓層信號(用于停止或在前一樓層提前加減速)(定時器模擬的用不到)
- u8 FreeFlag; //電梯空閑狀態(tài)標(biāo)志
- }TYPEDEF_ELEVSTATE;
- TYPEDEF_ELEVSTATE ElevState; //電梯狀態(tài)結(jié)構(gòu)體
- //u8 code SEG_NUM[]={0x3f,0x06,0x5b,0x4f,0x66,0x6D,0x7D,0x07,0x7f,0x6f}; //共陰SEG數(shù)碼管段碼 0~9
- u8 code SEG_NUM[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //共陽SEG數(shù)碼管段碼 0~F
- u16 code LED_NUM[]={0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //SEG數(shù)碼管段碼 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 USART_RX_LEN 20 //接收緩存長度(請勿超過芯片rom剩余大小)
- typedef struct
- {
- u8 RX_BUFF[USART_RX_LEN]; //接收緩存
- u8 TX_BUFF[USART_RX_LEN]; //發(fā)送緩存
- u16 RX_COUNT;
- }USART;
- USART Usart;
- 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 USART_Config(u16 BaudRate);
- 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 USART_SendByte(u8 dat);
- void USART_Send(u8* arr,u16 len);
- void USART_SendStr(u8* str);
- 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; //下降沿觸發(fā)
- EX0= 1;
- }
- void EXTI1_Init(void)
- {
- EA = 1;
- IT1= 1; //下降沿觸發(fā)
- EX1= 1;
- }
- void Timer0_Init(void)
- {
- TMOD |= 0x01;
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- EA = 1;
- ET0 = 1;
- TR0 = 1;
- }
- void USART_Config(u16 BaudRate)
- {
- u8 TH1_Dat;
-
- switch(BaudRate)
- {
- case 1200: TH1_Dat=0xE8; break;
- case 2400: TH1_Dat=0xF4; break;
- case 4800: TH1_Dat=0xFA; break;
- case 9600: TH1_Dat=0xFD; break;
- case 14400: TH1_Dat=0xFE; break;
- }
- TMOD |= 0x20;
- SCON |= 0x50;
- TH1 = TH1_Dat;
- TL1 = TH1;
- PCON |= 0x00;
- EA = 1;
- ES = 1;
- TR1 = 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;
- }
- /*鍵盤剪裁說明:
- 按鍵掃描函數(shù) 8*8 如要改為4*4或其他
- 請把KeyPort_Y 和 KeyPort_X 對應(yīng)的IO口數(shù)量減少,如4*4,則用KeyPort_Y低4位和KeyPort_X高4位
- 鍵盤分布如下:(序號和IO口高低位對應(yīng))
- 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 * * * * * * * * 對應(yīng)按鍵掃描 33 34 35 36 37 38 39 40 仿真文件
- | X4 * * * * * * * * 函數(shù)返回值-> 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()掃描函數(shù)兼容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;
- }
- //鍵值處理函數(shù):當(dāng)鍵盤鍵值需要改動時,請根據(jù)上面的鍵值改動
- void KeyDatHandle(u8 key)
- {
- u8 tempkey;
- if(key==0)
- {
-
- }
- else
- if(((key>0)&&(key<=8))||((key>32)&&(key<=40))) //樓梯內(nèi)的樓層選擇按鍵(使用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;//內(nèi)部按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) //關(guān)門 (使用26 作為按鍵)
- {
- if(DOOR==OPEN)
- {
- DOOR_Close;
- ElevState.FloorTimerCount=0; //計時器清0
- }
- }
- }
- //第待開門
- void WaitDoorOpen(u8 ts)
- {
- DOOR_Open;
- delay_s(ts);
- }
- //第待關(guān)門
- 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
-
- }
- //數(shù)碼管顯示驅(qū)動
- void SEG_Display(u8 segnum)
- {
- HC595_BUFF[0]=SEG_NUM[segnum/10];
- HC595_BUFF[1]=SEG_NUM[segnum%10];
- HC595_Send(HC595_BUFF);
- }
- //LED顯示驅(qū)動
- 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顯示驅(qū)動
- 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);
- }
- //電梯運行狀態(tài)設(shè)置
- 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); //數(shù)碼管顯示
- }
- //調(diào)頭檢測函數(shù)
- void TurnHead_Check(void)
- {
- if(ElevState.CurrentFloor==1)
- {
- ElevState.Direction=UP; //1樓調(diào)頭
- }
- else if(ElevState.CurrentFloor==MaxFloor)
- {
- ElevState.Direction=DOWN; //頂樓調(diào)頭
- }
- }
- //電梯運行函數(shù)
- void Elevator(void)
- {
- if((DOOR==OPEN)||(ElevState.FreeFlag==TRUE)) ElevWorkState(STOP);
- else ElevWorkState(ElevState.Direction);
- TurnHead_Check(); //調(diào)頭檢測
- 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)) //到達(dá)目標(biāo)樓層,停下開門5秒
- {
- LED_OFF(LED_IN_Port,ElevState.CurrentFloor);
- LED_OFF(LED_OUT_UP_Port,ElevState.CurrentFloor);
- ElevState.FloorCallTable[ElevState.CurrentFloor]&=~UP_IN; //到達(dá)相應(yīng)的樓層從向上列表中清除
- ElevState.FloorCallTable[ElevState.CurrentFloor]&=~UP_OUT; //到達(dá)相應(yīng)的樓層從向上列表中清除
- ElevState.FreeFlag=TRUE; //到達(dá)樓層,暫時進(jìn)入空閑狀態(tài)
- ElevWorkState(STOP); //修改電梯狀態(tài)為停止態(tài)
- WaitDoorOpen(DoorStayTime); //延時等待電梯門打開
- delay_s(2*DoorStayTime); //適當(dāng)延時
- WaitDoorClose(DoorStayTime); //等待門關(guān)好
- ElevWorkState(ElevState.Direction);
- ElevState.FreeFlag=FALSE; //離開樓層,退出空閑狀態(tài)
- 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)) //到達(dá)樓層,停下開門5秒
- {
- LED_OFF(LED_IN_Port,ElevState.CurrentFloor);
- LED_OFF(LED_OUT_DOWN_Port,ElevState.CurrentFloor);
- ElevState.FloorCallTable[ElevState.CurrentFloor]&=~DOWN_IN; //到達(dá)相應(yīng)的樓層從向下列表中清除
- ElevState.FloorCallTable[ElevState.CurrentFloor]&=~DOWN_OUT; //到達(dá)相應(yīng)的樓層從向下列表中清除
- ElevState.FreeFlag=TRUE; //到達(dá)樓層,暫時進(jìn)入空閑狀態(tài)
- ElevWorkState(STOP); //修改電梯狀態(tài)為停止態(tài)
- WaitDoorOpen(DoorStayTime); //延時等待電梯門打開
- delay_s(2*DoorStayTime); //保持門開2秒讓人進(jìn)出
- WaitDoorClose(DoorStayTime); //適當(dāng)延時
- ElevWorkState(ElevState.Direction); //等待門關(guān)好
- ElevState.FreeFlag=FALSE; //離開樓層,退出空閑狀態(tài)
- 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[i]&UP_IN)==UP_IN)||((ElevState.FloorCallTable[i]&UP_OUT)==UP_OUT)) //如果掃描到上方樓層有向上的呼叫
- {
- return TRUE;
- }
- }
- return FALSE;
- }
- else
- if(floorside==DOWN)
- {
- for(i=ElevState.CurrentFloor-1;i>=1;i--) //掃描呼叫列表樓下是否有要向上的呼叫
- {
- if(((ElevState.FloorCallTable[i]&UP_IN)==UP_IN)||((ElevState.FloorCallTable[i]&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[i]&DOWN_IN)==DOWN_IN)||((ElevState.FloorCallTable[i]&DOWN_OUT)==DOWN_OUT)) //如果掃描到上方樓層有向下的呼叫
- {
- return TRUE;
- }
- }
- return FALSE;
- }
- else
- if(floorside==DOWN)
- {
- for(i=ElevState.CurrentFloor-1;i>=1;i--) //掃描呼叫列表樓下是否有要向下的呼叫
- {
- if(((ElevState.FloorCallTable[i]&DOWN_IN)==DOWN_IN)||((ElevState.FloorCallTable[i]&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[i]!=Null)
- {
- result=FALSE; //非空閑
- break;
- }
- else if(i==MaxFloor) result=TRUE; //空閑
- }
- return result;
- }
- //樓層呼叫處理函數(shù)(無需修改)
- void FloorCallCheck(void)
- {
- if(DelNullCheck()==FALSE) //非空閑
- {
- ElevState.FreeFlag=FALSE; //退出空閑狀態(tài)
- ElevState.ElevRunning=TRUE;//正在運行標(biāo)志打開
- }
- else ElevState.FreeFlag=TRUE; //進(jìn)入空閑狀態(tài)
- TurnHead_Check();
- if((ElevState.FreeFlag==FALSE)&&(DOOR==CLOSE)) //非空閑下
- {
- if(ElevState.Direction==UP)//方向向上
- {
- if((FloorCall_UP(UP)==TRUE)||(FloorCall_DOWN(UP)==TRUE)) //如果當(dāng)前樓層上方有呼叫向上的 或 如果當(dāng)前樓層上方有呼叫向下的
- {
- #if (USE_MODE==0)
- if(ElevState.FloorTimerCount>FloorStayTime) //檢測是否到達(dá)樓層 如果接收到 到達(dá)樓層的限位開關(guān)信號,則當(dāng)前樓層值+1(這里用定時器來模擬)
- {
- ElevState.FloorTimerCount=0; //計時器清0
- ElevState.CurrentFloor++;//電梯繼續(xù)往上走
- }
- #endif
- #if (USE_MODE==1)
- if(ElevState.ArriveFlag==TRUE) //檢測是否到達(dá)樓層 如果接收到 到達(dá)樓層的限位開關(guān)信號,則當(dāng)前樓層值+1
- {
- ElevState.ArriveFlag=FALSE; //清除標(biāo)志
- ElevState.FloorTimerCount=0; //計時器清0
- ElevState.CurrentFloor++;//電梯繼續(xù)往上走
- }
- #endif
- }
- else ElevState.Direction=DOWN; //調(diào)頭
- }
- else
- if(ElevState.Direction==DOWN)//方向向下
- {
- if((FloorCall_DOWN(DOWN)==TRUE)||(FloorCall_UP(DOWN)==TRUE)) //如果當(dāng)前樓層下方有呼叫向下的 或 如果當(dāng)前樓層下方有呼叫向上的
- {
- #if (USE_MODE==0)
- if(ElevState.FloorTimerCount>FloorStayTime) //檢測是否到達(dá)樓層 如果接收到 到達(dá)樓層的限位開關(guān)信號,則當(dāng)前樓層值+1(這里用定時器來模擬)
- {
- ElevState.FloorTimerCount=0;
- ElevState.CurrentFloor--;//電梯繼續(xù)往下走
- }
- #endif
- #if (USE_MODE==1)
- if(ElevState.ArriveFlag==TRUE) //檢測是否到達(dá)樓層 如果接收到 到達(dá)樓層的限位開關(guān)信號,則當(dāng)前樓層值+1
- {
- ElevState.ArriveFlag=FALSE; //清除標(biāo)志
- ElevState.FloorTimerCount=0;
- ElevState.CurrentFloor--;//電梯繼續(xù)往下走
- }
- #endif
- }
- else ElevState.Direction=UP; //調(diào)頭
- }
- }
- else
- {
- ElevWorkState(STOP); //停止運行
- ElevState.ElevRunning=FALSE;//正在運行標(biāo)志關(guān)閉
- }
- }
- void USART_SendByte(u8 dat)
- {
- SBUF=dat;
- while(!TI); //等待發(fā)送數(shù)據(jù)完成
- TI=0; //清除發(fā)送完成標(biāo)志位
- }
- void USART_Send(u8* arr,u16 len)
- {
- u16 i;
- for(i=0;i<len;i++)
- {
- SBUF=arr[i];
- while(!TI); //等待發(fā)送數(shù)據(jù)完成
- TI=0; //清除發(fā)送完成標(biāo)志位
- }
- }
- void USART_SendStr(u8* str)
- {
- while(1)
- {
- if(*str=='\0') break;
- SBUF=*str++;
- while(!TI); //等待發(fā)送數(shù)據(jù)完成
- TI=0; //清除發(fā)送完成標(biāo)志位
- }
- }
- //系統(tǒng)初使化
- void SYSYEM_INIT(void)
- {
- u8 i;
- ElevState.CurrentFloor=1;
- ElevState.Direction=UP; //初使化方向為向上
- ElevState.FloorTimerCount=0; //定時器版計時清0
- ElevState.FreeFlag=TRUE; //初使化為空閑狀態(tài)
- ElevState.ElevRunning=FALSE; //運行標(biāo)志置FALSE 表示暫停運行
- Usart.RX_COUNT=0; //串口接收計數(shù)清0
- for(i=0;i<=MaxFloor;i++)
- {
- ElevState.FloorCallTable[i]=Null; //初使化呼叫列表為Null
- }
- DOOR_Close; //關(guān)門
- }
- void main(void)
- {
- SYSYEM_INIT();
- EXTI0_Init();
- EXTI1_Init();
- TIMER0_Init();
- USART_Config(9600);
- USART_SendStr("Welcome to use Hailin's elevator program \r\n");
- while(1)
- {
- KeyPort_Y=0x00; //不可刪除
- FloorCallCheck();
- Elevator();
- }
- }
- void EXTI0_IRQHandler(void) interrupt 0 //樓層傳感器中斷
- {
- #if (USE_MODE==1)
- ElevState.ArriveFlag=TRUE;//觸發(fā)中斷后表示到達(dá)樓層,讓到達(dá)樓層標(biāo)志置TRUE
- #endif
- }
- void EXTI1_IRQHandler(void) interrupt 2 //矩陣按鍵中斷
- {
- KeyDatHandle(KeyScan()); //把KeyScan()按鍵掃描函數(shù)返回的按鍵值帶入到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++; //非空閑狀態(tài)計時累加
- else ElevState.FloorTimerCount=0; //空閑狀態(tài)計時清0
- }
- void USART_IRQHandler(void) interrupt 4 //用于電梯之間的通信
- {
- if(RI==1) //判斷是否為接收中斷(串口中斷分為發(fā)送中斷和接收中斷,均用同一個中斷服務(wù)函數(shù)入口)
- {
- RI = 0; //清除RI接收中斷標(biāo)志
- Usart.RX_BUFF[Usart.RX_COUNT++]=SBUF;
- if(Usart.RX_COUNT==USART_RX_LEN) Usart.RX_COUNT=0;
- }
- }
- /*Uart串口發(fā)送函數(shù)示例:
- 1.USART_SendByte(u8 dat) //發(fā)送單字節(jié)數(shù)據(jù)
- 例:USART_SendByte(0x04);
- 2.USART_Send(u8* arr,u16 len) //發(fā)送多字節(jié)數(shù)據(jù)
- 例:
- Usart.TX_BUFF[0]=0xA1;
- Usart.TX_BUFF[1]=0x08;
- Usart.TX_BUFF[2]=0x04;
- Usart.TX_BUFF[3]=0xF9;
- USART_SendByte(Usart.TX_BUFF,4);
- 或
- u8 Arr[16]={0xA1,0x08,0x04,0xF9};
- USART_SendByte(Arr,4);
- 3.USART_SendStr(u8* str) //發(fā)送字符串?dāng)?shù)據(jù)
- USART_SendStr("大吉在利,晚上吃雞!\r\n");
- 4.有關(guān)電梯通信代碼參考:
- <1>發(fā)送電梯當(dāng)前樓層給其他設(shè)備: USART_SendByte(ElevState.CurrentFloor);
- <2>發(fā)送電梯當(dāng)前運行方向給其他設(shè)備: USART_SendByte(ElevState.Direction);
- <3>發(fā)送電梯當(dāng)前所有數(shù)據(jù)給其他設(shè)備: USART_Send((u8*)(&ElevState),sizeof(ElevState));
- */
- /*Uart串口接收函數(shù)示例:
- 1.單字符指令接收:
- #include "reg51.h"
- void main(void)
- {
- USART_Configure(9600);//配置9600波特率(默認(rèn)無奇偶校驗,1位停止位,8位數(shù)據(jù)位)
- while(1)
- {
- if(Usart.RX_COUNT>0) //判斷串口是否有接收
- {
- Usart.RX_COUNT=0;
- if(Usart.RX_BUFF[0]=='A') //如果控制對象比較多請換成switch()
- {
- P1=0x0F;
- }
- if(Usart.RX_BUFF[0]=='B')
- {
- P1=0xF0;
- }
- }
- }
- }
- 2.多字符指令接收:(為了方便,我們用C標(biāo)準(zhǔn)庫自帶的string.h)
- #include "reg51.h"
- #include <string.h>
- void main(void)
- {
- char xbuff[20];
- USART_Configure(9600);//配置9600波特率(默認(rèn)無奇偶校驗,1位停止位,8位數(shù)據(jù)位)
- while(1)
- {
- if(Usart.RX_COUNT>4) //判斷串口是否接收到指令(設(shè)指令格式為:開燈/ 關(guān)燈/ 用/來表示指令結(jié)束符)
- {
- if(Usart.RX_BUFF[4]=='/') //斷判結(jié)束符
- {
- Usart.RX_COUNT=0;
- strncpy(xbuff, Usart.RX_BUFF+0 , 4);//+0表示從接收緩存的第0個字符開始截取4個字符到xbuff判斷指令
- if(strncmp(xbuff,"開燈",4) == 0)
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼
所有資料51hei提供下載:
16層電梯.zip
(102.19 KB, 下載次數(shù): 21)
2020-12-2 20:09 上傳
點擊文件名下載附件
程序 仿真圖 下載積分: 黑幣 -5
|
評分
-
查看全部評分
|