目录
4层电梯单片机控制设计 4
- 设计任务 4
- 整体方案设计 5
- 系统硬件电路设计 6
3.1 单片机最小系统电路 6
图3-1 单片机最小系统电路图 6
3.2 开关控制电路 7
图3-2 开关控制电路设计图 7
3.3 显示电路 8
3.3.1 led楼层触发显示灯电路 8
3.3.2 当前楼层显示电路 9
图3-3-2 当前楼层显示电路 9
3.4 8155串行口扩展电路 10
3.5 总设计图 12
图3-5 总设计图 12 - 系统程序设计 12
4.1 主程序流程图 12
系统工作流程:(1)用菊阳仿真器使程序处于连续运行状态 13
4.2 定时器子程序流程图 13
4.3 扫描子程序流程图 13
4.4 显示子程序流程图 14
4.5 延时流程图 15
图4-5 延时程序流程图 15 - 系统调试 15
5.1 Proteus软件仿真调试 15
5.2 硬件调试 16
1上(4键)2上(0键)3上(RG键) 16 - 程序清单 16
7.小结 29 - 设计任务
结合实际情况,基于AT89C52单片机设计一个四层电梯单片机控制系统。该系统应满足的功能要求为:
4层电梯运行控制,轿内外呼叫,运行状态显示。独立键盘、LED显示楼层、指示灯。
(1) 电梯运行控制系统为四层控制系统。
(2) 电梯能够轿内外呼叫,并显示运行的状态。
(3) 设计系统具有独立键盘控制,并有LED显示楼层与指示灯。
主要硬件设备:AT89C52单片机: AT89C52是一个低电压,高性能CMOS 8位单片机,片内含8k bytes的可反复擦写的Flash只读程序存储器和256 bytes的随机存取数据存储器(RAM),器件采用ATMEL公司的高密度、非易失性存储技术生产,兼容标准MCS-51指令系统,片内置通用8位中央处理器和Flash存储单元,AT89C52单片机在电子行业中有着广泛的应用。
AT89C52有40个引脚,32个外部双向输入/输出(I/O)端口,同时内含2个外中断口,3个16位可编程定时计数器,2个全双工串行通信口,2 个读写口线,AT89C52可以按照常规方法进行编程,也可以在线编程。其将通用的微处理器和Flash存储器结合在一起,特别是可反复擦写的 Flash存储器可有效地降低开发成本。
AT89C52有PDIP、PQFP/TQFP及PLCC等三种封装形式,以适应不同产品的需求。 - 整体方案设计
本设计采用AT89C52单片机作为核心,配以适当接口作为输入输出通道。采用三行按键矩阵开关电路作为外呼内选呼叫控制。实际电梯控制系统每层装有一个传感器,从而判断车厢所在位置,本模型由10个独立按键作为楼层到达信号传输给单片机,而后通过内部电路从串口驱动数码管显示楼层数。当电梯到达所选层,电梯开门延时等待进人并选层,然后延时关门执行请求,若无请求则停在本层等待请求。软件部分使用C语言,利用查询方式来检测用户请求的按键信息。
图2-1 基于单片机的四层电梯控制总原理图
本系统硬件主要由复位模块、显示系统、扩展部分、矩阵控制模块几部分组成。各模块的主要功能如下:
(1) 复位的功能其一用于程序初始化,其二也用于摆脱互锁和跑飞。
(2) 显示系统的功能分为显示led灯显示触发楼层数和数码管显示当前楼层数的两个部分,用于显示电梯系统此时正在运行的状态。
(3) 扩展部分:因为单片机芯片的接口有限,故使用8155扩展串行口用以连接更多功能。
(4) 矩阵控制模块:即内呼外叫控制程序,用于控制电梯内外电路。
#include "reg52.h"
#include "absacc.h"
#define uint unsigned int
#define uchar unsigned char
#define COM XBYTE[0xFF20] //定义8155地址
#define PA XBYTE[0xFF21]
#define PB XBYTE[0xFF22]
#define PC XBYTE[0xFF23]
sbit lup1=P1^0; //L1 //定义led控制端口
sbit lup2=P1^1; //L2
sbit ldown2=P1^2; //L3
sbit lup3=P1^3; //L4
sbit ldown3=P1^4; //L5
sbit ldown4=P1^5; //L6
sbit lopen=P1^7; //L8
uchar state; //当前电梯状态
uchar statepre; //之前电梯状态
uchar flag; //电梯上下标志,0下,1上
bit flag1; //定时时间到标志
uchar counter; //计数器
bit in1=0, in2=0, in3=0, in4=0, up1=0, up2=0, up3=0, down2=0, down3=0, down4=0; //KEY
uchar code table[]={0xf9, 0xa4,0xb0,0x99, 0xa1, 0xc1, 0xff}; //楼层显示码表,一共是四层
void delay(uint xms) //简单延时0.1ms
{
uint o,j;
for(o=xms;o>0;o--)
for(j=11;j>0;j--);
}
/***********************************************************/
void display(){
PB=0xff;
PA=0xfe;
PB=table[state-1];
delay(2);
PB=0xff;
PA=0xfd;
PB=table[flag+4];
delay(2);
}
void keyscan(){ //扫描键盘
uchar pctemp;
PB=0xff;
PA=~0x01; //PA0口输出低电平
pctemp=PC;
switch(pctemp&0x0f){ //PC高位置0
case(0x0e):{
in1=1; //被按下后标记,亮灯,下同
break;
}
case(0x0d):{
in2=1;
break;
}
case(0x0b):{
in3=1;
break;
}
case(0x07):{
in4=1;
break;
}
default: break;
}
PA=~0x02; //PA1口低电平扫描第二行
delay(1);
pctemp=PC;
switch(pctemp&0x0f){
case(0x0e):{
up1=1;
lup1=0;
break;
}
case(0x0d):{
up2=1;
lup2=0;
break;
}
case(0x0b):{
up3=1;
lup3=0;
break;
}
default: break;
}
PA=~0x04;
delay(1); //PA2口低电平扫描第三行
pctemp=PC;
switch(pctemp&0x0f){
case(0x0d):{
down2=1;
ldown2=0;
break;
}
case(0x0b):{
down3=1;
ldown3=0;
break;
}
case(0x07):{
down4=1;
ldown4=0;
break;
}
default: break;
}
}
void iniclock() //start clock
{
TH0=60; //TH0=(65536-50000)/256 TL0=(65536-50000)%256 50ms初值
TL0=176;
ET0=1; //开定时器
TR0=1; //启动定时器T0
}
void run(){
iniclock(); //开定时
while(~flag1){ //时间未到扫描键盘
keyscan();
display();
}
flag1=0; //时间到了,清标志位,关定时器
TR0=0;
ET0=0;
}
void main()
{
state=1;
statepre=1;
flag=1;
flag1=0;
COM=0x43; //intialize 8155
TMOD=0x01; //定义定时器0/1为定时器模式
//TH0=(65536-50000)/256;//50ms初值
//TL0=(65536-50000)%256;
//ET0=1; //开定时器
//TR0=1; //启动定时器T0
EA=1; //开中断
while(1){
switch(state){ //扫描电梯所在位置
case(1):{
//up1=0; //一楼的按键灯都熄灭
//in1=0;
//lup1=1;
//lin1=1;
//keyscan;
//display();
if(state!=statepre){ //上次的状态和本次不一样说明电梯 需要开门
lopen=0;
run(); //按键扫描三秒钟
lopen=1;
in1=0; //如果in1和up1被按下则无效
up1=0;
lup1=1;
}
else{
if(up1){
up1=0;
lup1=1;
lopen=0;
run();
lopen=1;
}
}
in1=0;
if(up2|down2|up3|down3|down4|in2|in3|in4){
flag=1; //说明上行
run(); //按键扫描三秒钟
state=2; //更新状态
statepre=1;
}
else{
statepre=state;
flag=2;
keyscan();
display();
}
break;
}
case(2):{ //电梯到2楼
//in2=0; //电梯内部2楼指示灯灭
//lin2=1;
//if(flag==1){ //如果上行,电梯外上行指示灯灭
//up2=0;
//lup2=1;
//}
//else{ //如果下行,电梯外下行指示灯灭
//down2=0;
// ldown2=1;
//}
//keyscan;
//display();
if(state!=statepre)
{ //如果前后两次状态不一样则可能需要开门
if(!(
((flag==1)&&(in3|up3|down3)&&(~up2)&&(~in2)) //去三楼
||((flag==1)&&(in4|down4)&&(~up2)&&(~in2)) //去四楼
||((flag==0)&&(in1||up1)&&(~down2)&&(~in2)) //去一楼
)
)
{
lopen=0;
run(); //按键扫描三秒钟
lopen=1;
in2=0; //如果in2被按下则无效
if(flag==1){ //如果上行,电梯外上行指示灯按下无效
up2=0;
lup2=1;
}
else{ //如果下行,电梯外下行指示灯按下无效
down2=0;
ldown2=1;
}
}
}
else{ //在二楼停
if(down2|up2){
down2=0;
up2=0;
lopen=0;
run();
lopen=1;
ldown2=1;
lup2=1;
}
}
in2=0;
if(flag)
up2=0;
else
down2=0;
if(flag==1){
if(down3|in3|up3|down4|in4){
flag=1;
run();
state=3;
statepre=2;
}
else if(in1|up1){
flag=0;
run();
state=1;
statepre=2;
}
else{
statepre=state;
flag=2;
keyscan();
display();
}
}
else {
if(up1|in1){
flag=0;
run();
state=1;
statepre=2;
}
else if(in3|down3|up3|in4|down4){
flag=1;
run();
state=3;
statepre=2;
}
else{
statepre=state;
flag=2;
keyscan();
display();
}
}
break;
}
case(3):{ //电梯到3楼
//in3=0; //电梯内部3楼指示灯灭
//lin2=1;
//if(flag==1){ //如果上行,电梯外上行指示灯灭
//up3=0;
//lup3=1;
//}
//else{ //如果下行,电梯外下行指示灯灭
//down3=0;
// ldown2=1;
//}
//keyscan;
//display();
if(state!=statepre)
{ //如果前后两次状态不一样则可能需要开门
if(!(
((flag==0)&&(in2|up2|down2)&&(~up3)&&(~in3)) //去二楼
||((flag==1)&&(in4|down4)&&(~up3)&&(~in3)) //去四楼
||((flag==0)&&(in1||up1)&&(~down3)&&(~in2)) //去一楼
)
)
{
lopen=0;
run(); //按键扫描三秒钟
lopen=1;
in3=0; //如果in3被按下则无效
if(flag==1){ //如果上行,电梯外上行指示灯按下无效
up3=0;
lup3=1;
}
else{ //如果下行,电梯外下行指示灯按下无效
down3=0;
ldown2=1;
}
}
}
else{ //在三楼停
if(down3|up3){
down3=0;
up3=0;
lopen=0;
run();
lopen=1;
ldown3=1;
lup3=1;
}
}
in3=0;
if(flag)
up3=0;
else
down3=0;
if(flag==1){
if(down4|in4){
flag=1;
run();
state=4;
statepre=3;
}
else if(in1|up1|in2|up2|down2){
flag=0;
run();
state=2;
statepre=3;
}
else{
statepre=state;
flag=2;
keyscan();
display();
}
}
else {
if(up1|in1|up2|in2|down2){
flag=0;
run();
state=2;
statepre=3;
}
else if(in4|down4){
flag=1;
run();
state=4;
statepre=3;
}
else{
statepre=state;
flag=2;
keyscan();
display();
}
}
break;
}
case(4):{ //case4和case1类似
//down4=0;
//in4=0;
//ldown4=1;
//lin4=1;
keyscan();
display();
if(state!=statepre){
lopen=0;
run();
lopen=1;
in4=0; //如果in4和down4被按下则无效
down4=0;
ldown4=1;
}
else{
if(down4){
down4=0;
ldown4=1;
lopen=0;
run();
lopen=1;
}
}
in4=0;
if(in1|up1|up2|down2|in2|in3|up3|down3){
flag=0; //说明下行
run();
state=3; //更新状态
statepre=4;
}
else{
statepre=state;
flag=2;
keyscan();
display();
}
break;
}
default: break;
}
}
}
void T0_time()interrupt 1
{
TH0=(65536-50000)/256; TL0=(65536-50000)%256; //重赋初值
counter++; //定时器中断次数加1
if(counter==60) //三秒钟执行一次
{
counter=0;
flag1=1; //三秒钟定时到标志
}
}