Project combat: SCM layer 16 can lift with serial communication source code + Proteus simulation design (in-kind has passed) C language source code and source code PROTEUS

Number of floors optional hardware can be removed. Set within any 16-story maximum number of floors, floor less than the hardware can be deleted without affecting the program. Provide serial communications, baud rate can be set up in the main of the early years. Updated versions of detailed notes, please pay attention to learn friend.

Elevator simulation method is as follows

Here Insert Picture Description
C language source code for screenshot

Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
In C language source code

/ * Uart serial transmission function example:
1.USART_SendByte (U8 DAT) transmits the data byte //
Example: USART_SendByte (0x04);

2.USART_Send (u8 * arr, u16 len ) // send multiple byte data
Example:
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);
or
U8 Arr [16] = {} 0xA1,0x08,0x04,0xF9;
USART_SendByte (Arr,. 4);

3.USART_SendStr (u8 * str) // send data string
USART_SendStr ( "Tetra down, chicken \ r \ n evening!");

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

*/

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

#include “reg51.h”
#include “intrins.h”

/程序选择*******/
#define USE_MODE 0 //0-定时模拟 1-传感器
/*********************************************************/
/平台移植部分代码
/
//定时器模拟版接口:
#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路与门可用芯片: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路的与门芯片组合
//8路与门:用8路与非门CD4068或74LS30+输出端接一个三极管反向电平。
/****************************************************************/
/楼梯参数设置******/
#define MaxFloor 16 //电梯总楼层(最大16)

#define FloorStayTime 40 //单位:50ms, 楼层停留时间:4050ms=2S
#define DoorStayTime 2 //单位:S , 电梯门停留时间
#define SEG_Num 2 //数码管数量(为1时请删除第一个数码管的595)
/
***************************************************************/
#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
#define UP_OUT 0x02
#define DOWN_IN 0x04
#define DOWN_OUT 0x08

#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

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 RIOver_Flag=0;
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]; //发送缓存
u16 RX_COUNT;
}USART;
USART Usart;

void delay_ms(u16 xms);
void delay_s(u8 xs);
void EXTI0_Init(void);
void Timer0_Init(void);
void USART_Configure(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 DlevWorkState(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; //下降沿触发
EX0= 1;
}

void EXTI1_Init(void)
{
EA = 1;
IT1= 1; //下降沿触发
EX1= 1;
}

else
if(((key>0)&&(key<=8))||((key>32)&&(key<=40))) //楼梯内的楼层选择按键(使用第1行和第5行作为电梯内部16个按键,每行8个键)
{
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))||(tempkey1)) 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))) //每个楼层门口外的向下按键(底楼按向下无效),第2行和第6行
{
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))) //每个楼层门口外的向上按键(顶楼按向上无效),第2行和第7行
{
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(key25) //开门
{
if(ElevState.ElevRunning
FALSE)
{
if(DOORCLOSE) DOOR_Open;
}
}
else
if(key
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_MODE0)
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);
}
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);
}
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(stateUP)
{
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.CurrentFloor1)
{
ElevState.Direction=UP; //1楼调头
}
else if(ElevState.CurrentFloor
MaxFloor)
{
ElevState.Direction=DOWN; //顶楼调头
}
}
void Elevator(void)
{
if((DOOROPEN)||(ElevState.FreeFlagTRUE)) 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
}
}
}

}

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

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

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

void FloorCallCheck(void)
{
if(DelNullCheck()FALSE) //非空闲
{
ElevState.FreeFlag=FALSE; //退出空闲状态
ElevState.ElevRunning=TRUE;//正在运行标志打开
}
else ElevState.FreeFlag=TRUE; //进入空闲状态
TurnHead_Check();
if((ElevState.FreeFlag
FALSE)&&(DOORCLOSE)) //非空闲下
{
if(ElevState.Direction
UP)//方向向上
{
if((FloorCall_UP(UP)TRUE)||(FloorCall_DOWN(UP)TRUE)) //如果当前楼层上方有呼叫向上的 或 如果当前楼层上方有呼叫向下的
{
#if (USE_MODE
0)
if(ElevState.FloorTimerCount>FloorStayTime) //检测是否到达楼层 如果接收到 到达楼层的限位开关信号,则当前楼层值+1(这里用定时器来模拟)
{
ElevState.FloorTimerCount=0; //计时器清0
ElevState.CurrentFloor++;//电梯继续往上走
}
#endif
#if (USE_MODE
1)
if(ElevState.ArriveFlagTRUE) //检测是否到达楼层 如果接收到 到达楼层的限位开关信号,则当前楼层值+1
{
ElevState.ArriveFlag=FALSE; //清除标志
ElevState.FloorTimerCount=0; //计时器清0
ElevState.CurrentFloor++;//电梯继续往上走
}
#endif
}
else ElevState.Direction=DOWN; //调头
}
else
if(ElevState.Direction
DOWN)//方向向下
{
if((FloorCall_DOWN(DOWN)TRUE)||(FloorCall_UP(DOWN)TRUE)) //如果当前楼层下方有呼叫向下的 或 如果当前楼层下方有呼叫向上的
{
#if (USE_MODE
0)
if(ElevState.FloorTimerCount>FloorStayTime) //检测是否到达楼层 如果接收到 到达楼层的限位开关信号,则当前楼层值+1(这里用定时器来模拟)
{
ElevState.FloorTimerCount=0;
ElevState.CurrentFloor–;//电梯继续往下走
}
#endif
#if (USE_MODE
1)
if(ElevState.ArriveFlag==TRUE) //检测是否到达楼层 如果接收到 到达楼层的限位开关信号,则当前楼层值+1
{
ElevState.ArriveFlag=FALSE; //清除标志
ElevState.FloorTimerCount=0;
ElevState.CurrentFloor–;//电梯继续往下走
}
#endif
}
else ElevState.Direction=UP; //调头
}
}
else
{
ElevWorkState(STOP); //停止运行
ElevState.ElevRunning=FALSE;//正在运行标志关闭
}
}

void USART_SendByte(u8 dat)
{
SBUF=dat;
while(!TI); //等待发送数据完成
TI=0; //清除发送完成标志位
}
void USART_Send(u8* arr,u16 len)
{
u16 i;
for(i=0;i<len;i++)
{
SBUF=arr[i];
while(!TI); //等待发送数据完成
TI=0; //清除发送完成标志位
}
}
void USART_SendStr(u8* str)
{
while(1)
{
if(*str==’\0’) break;
SBUF=*str++;
while(!TI); //等待发送数据完成
TI=0; //清除发送完成标志位
}
}

void SYSYEM_INIT(void)
{
u8 i;
ElevState.CurrentFloor=1;
ElevState.Direction=UP; //初使化方向为向上
ElevState.FloorTimerCount=0;
ElevState.FreeFlag=TRUE; //初使化为空闲状态
ElevState.ElevRunning=FALSE;
RIOver_Flag=FALSE;
Usart.RX_COUNT=0;
for(i=0;i<=MaxFloor;i++)
{
ElevState.FloorCallTable[i]=Null; //初使化呼叫列表为Null

     ……………………

void EXTI0_IRQHandler(void) interrupt 0
{
#if (USE_MODE==1)
ElevState.ArriveFlag=TRUE;
#endif
}
void EXTI1_IRQHandler(void) interrupt 2 //矩阵按键中断
{
KeyDatHandle(KeyScan());
}
void TIM0_IRQHandler(void) interrupt 1 //定时模拟电梯上升和下降
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;

TimerCount++;
if(TimerCount==20) //1秒
{
TimerCount=0;
Timer_Second++;
}
if(DelNullCheck()==FALSE) ElevState.FloorTimerCount++; //非空闲状态计时累加
else ElevState.FloorTimerCount=0; //空闲状态计时清0
}

void USART_IRQHandler (void) interrupt 4 // used for communication between the elevator
{
IF (the RI ==. 1) // determines whether an interrupt is received (and serial port interrupt transmit interrupt into the interrupt reception, we are using the same interrupt service routine entry )
{
........................
view of space reasons, only the reference code writing section.

Finally, if you have any comments or suggestions welcome message to me, let's learn together and progress together,
if you need the full code or design documents, please leave a message below or private letter I, after seeing will be the first time reply.

Thank you!

Published 74 original articles · won praise 159 · views 70000 +

Guess you like

Origin blog.csdn.net/weixin_44212493/article/details/104334379