单片机多电梯控制系统

单片机多电梯控制系统
​​​​​​​​
写在前面:
前段时间单片机的课设题目,难度为5,算是选题1~5最难的一类。之前也没怎么学过,这次算是从头开始学习51单片机。此篇所写代码是基于我自己理解能让小白容易弄懂的代码,其中难免出现一些纰漏,所写不足之处,望指正(下载地址在我的公众号 For My Future对应文章文末)。
这篇文章是是从我公众号复制的,没有排版,想看美观排版及下载源代码,请关注我的公众号,找到对应的历史文章
单片机多电梯控制系统_第1张图片

​一.应用场景
二.主要模块介绍
三.详细编写步骤

​一.应用场景

​​​​先放图,心里有个大概认识(步进电机没拍到​,后面有详细说明图)​

模拟电梯系统,4层,两部电梯,用步进电机顺逆时针模拟电梯上下行,矩阵键盘模拟电梯内外层呼叫,数码管显示楼层数,蜂鸣器模拟故障警报,并且有多电梯中最近电梯响应的逻辑,板子是福讯的stc89c52​。

最近电梯响应解释:我们正常坐电梯,一般一栋楼有两座电梯,我住在三楼,我按下呼叫按钮,这时​A电梯在1层,​​B电梯在18层,假设都是空闲状态,那么A电梯离我最近,A电梯​会下来接我。

二.主要模块介绍

单片机多电梯控制系统_第2张图片

​​1.电梯步进电机模块:
(1)步进电机正反转代表电梯上下行
(2)电梯每变化一层,步进电机转半圈

2.数码管显示模块
(1)选用两个数码管分别显示一号电梯,二号电梯的楼层数
(2)动态实时显示楼层数,楼层变化数码管数字变化

3.警报器模块
(1)当电梯发生故障时,按下按钮,蜂鸣器发出警报

4.电梯响应呼叫模块(​​难点​)
(1)矩阵键盘模拟一,二号电梯内外呼叫
(2)一号电梯内部四个键盘代表四层,二号电梯同理,外呼叫四个按钮代表电梯外每层的呼叫按钮
(3)即时呼叫,按钮按下电梯工作
(4)判断最近电梯逻辑离呼叫层数最近的电梯响应

矩阵键盘按下所实现的任务:
4×4的键盘,编号为1~16。
14即第一行按键代表电梯14外层呼叫,通俗来讲就是我按下按键电梯要来接我。
5~8即第二行按键代表A电梯​内部层数按钮,我进入A电梯​内部,会有4个按钮,我想上4楼,就按下对应按钮即单片机键盘的8号按键,想去2楼,就按下单片机键盘的6号按键。
9~12即第三行按键代表B电梯​内部层数按钮同上。
16号是报警按键,按下蜂鸣器就会响。

三.详细编写步骤

​​​1.编写电梯步进电机模块:

步进电机无非是控制正转倒转以及控制圈数,
步进电机的方向是用脉冲来控制的

图示为三种方法,这里采用第一种写法,正转代码:
​​void cw(){
uchar o;
for(o=0;o<250;o++){
a=0;b=0;c=0;d=1;
delaydj(500); //改变这个参数可以调整电机转速 ,数字越小,转速越大
a=0;b=0;c=1;d=0;
delaydj(500);
a=0;b=1;c=0;d=0;
delaydj(500);
a=1;b=0;c=0;d=0;
delaydj(500);
}
}

​倒转反着写就可以了。

编写此模块出现的问题:
在我测试的时候还发现了一个问题,就是要多加一个电压源,否则步进电机无法转动 ,这是个小问题,但当时我对电机原理不了解,耗了很长时间才发现原因所在。

2.数码管显示模块

首先要明确单片机是单线程的,要实现两位数字的显示,则切换的时间要短,达到视觉暂留的效应,这样看起来才是同时显示的。
首先我们来写一号电梯的显示函数
​​void display1(){
uchar i;
for(i=0;i<=100;i++){
P0=0X00;//关掉数码管的位选信号。阻止数码管受到P0口信号的影响。
delay(1);
wela=1;
delay(1);
wela=0;

dula=0;
P0 = table[floor2-1]; /显示数字 i/
dula=1;
dula=0;
wela=0;
P0=0x10; //数码管位选
wela=1;
wela=0;
delay(10);
P0=0X00;//关掉数码管的位选信号。阻止数码管受到P0口信号的影响。
delay(1);
wela=1;
delay(1);
wela=0;

dula=0;
P0 = table[floor1-1]; /显示数字 i/
dula=1;
dula=0;
wela=0;
P0=0x01; //数码管位选
wela=1;
wela=0;
delay(10);}}

​上面的代码意思就是选数码管的一位,然后把数组table[]的值显示出来,table​​里面放的就是1~4这四个数字,代码写的是table[floor1-1]​,这个floor1就是我所设的全局变量,用来实时记录一号电梯当前的楼层数,比如我在三楼呼叫,此时一号电梯在一层,floor1=1,接着它会上来,从1变成2再到3,同理floor2​表示的就是二号电梯的实时楼层数。接着数码管再选第二位,显示另一部电梯的楼层数,这是一次显示,要想长时间的显示,外面再套个for循环100次即可。

这里我写了两个display函数display1(),display2()​,就是显示的顺序不一样,display1()是先显示第二位后显示第一位,那么循环完最后锁存的是第一位,也就是说display1()​执行完后,再执行其它任务时数码管第一位是亮的,第二位是熄灭的,而
display2()执行完第一位是熄灭的,第二位是亮的。​(不重要,不理解也没事,实操就明白了)

3.警报器模块

警报器编写较为简单
void fengming(){
feng=0;
delayms(1000);
feng=1;
delayms(1000);
}

4.电梯响应呼叫模块

在这之前,还要编写键盘扫描模块​,去识别到
底是哪个按键按下
uchar KeyScan()
{ uchar temp; //用于存储 P3 口的状态
uchar key_value = 0; //键值的定义
P3 = 0x0f; //设置P3高四位为0,第四位为1
temp = P3; //用一个变量存储P3口的状态,以免外界影响P3口,从而造成扫描有误
if(temp != 0x0f)
{
delayms(10);
if(temp!= 0x0f) //确定有键按下
{
switch(temp) //查看P3(temp)的状态
{
case 0x0e :key_value = 1; break; //按下的为第一行
case 0x0d :key_value = 5; break;
case 0x0b :key_value = 9; break;
case 0x07 :key_value = 13;break; //按下的为第四行
}
}
P3 = 0xf0; //再将 P3 口重新赋值,高四位为1,第四位为0
temp = P3;
if(temp != 0xf0)
{
switch(temp)
{
case 0xe0 : key_value +=3 ; break; //按下的是第四列,键值key_value加3
case 0xd0 : key_value +=2 ; break;
case 0xb0 : key_value +=1 ; break;
case 0x70 : key_value +=0 ; break; //按下的是第一列,键值key_value加0
}
}
while(P3 != 0xf0); //松手检测,因为最近的一次赋值是P3 = 0xf0
}
return(key_value);
}
KeyScan()函数返回的就是按键按下的编号,5号按键按下就会返回5。

我把电梯的响应呼叫的编写分为两部分
(1)电梯外部按钮响应事件
(2)电梯内部电梯响应事件

(1)电梯外部按钮响应

即编写对应按键1~4按下所触发的事件,这里编写dotask()​函数

void dotask(){
if((floor1-floor0)(floor1-floor0)<=(floor2-floor0)(floor2-floor0)){ flag=0;
if(floor0>=floor1) up1(floor0-floor1); else if(floor0 }
else if((floor1-floor0)(floor1-floor0)>(floor2-floor0)(floor2-floor0)){ flag=1;
if(floor0>=floor2) up2(floor0-floor2) ; else if(floor0 }

这里面有一个全局变量floor0,记录的是电梯将要执行的任务,也就是说我在四楼呼叫,floor0​就被赋值为4。dotask()函数先判断哪个电梯最近,然后再去选择是上升还是下降,一号电梯对应up1(),down1()​​

void up1(uchar m){
state1=0;
flag=0;
display1();
MotorCW(m);​
display1();
state1=1;
}

参数m是上升还是下降m层的意思,up1(2)​就表示一号电梯上升两层,state1​代表一号电梯的状态,0是忙碌,1是空闲。flag=0表示现在是一号电梯执行任务,flag=1​就表示二号电梯执行任务,MotorCW(m)​表示正转m个半圈。

二号电梯up2()及down2()同理。

编写当中出现的问题:
一开始用的是 if else语句,会出现错误,换成 if elseif变得正常,现在想想可能是有一些情况没有考虑到,毕竟这个逻辑还是挺多的。

(2)电梯内部按钮响应

​​​即编写一号电梯对应58,二号电梯对应912按键所触发事件。
这里用switch case来编写,举两个例子:

case 8: floor0=4; if(floor0>=floor1) up1(floor0-floor1) ;else down1(floor1-floor0);break;
case 12: floor0=4; if(floor0>=floor2) up2(floor0-floor2) ;else down2(floor2-floor0);break;

应该很容易理解,按下8号按键,即一号电梯内部4楼按钮,此时要执行的任务是一号电梯到4楼,floor0=4​,然后根据当前电梯所在位置判断是上升还是下降。其它按键事件同理。

最后外部套个while(true)循环检测扫描按键是否按下就可以了,这样一个简易的多电梯控制系统就完成了。

(我的单片机还回去了,忘录视频了,不好意思)

代码下载在公众号对应文章文末
单片机多电梯控制系统_第3张图片

你可能感兴趣的:(笔记)