基于单片机的16病床呼叫系统1.docx
《基于单片机的16病床呼叫系统1.docx》由会员分享,可在线阅读,更多相关《基于单片机的16病床呼叫系统1.docx(22页珍藏版)》请在冰点文库上搜索。
基于单片机的16病床呼叫系统1
基于单片机的病床呼叫系统
作者qiqi
指导教师wangwang
摘要系统是基于51系列的单片机设计的病床呼叫系统。
该系统以AT89C51单片机为核心辅以矩阵键盘、LED点阵显示电路和部分简单模拟和数字电路组成的能够实现病人和医护人员之间信息的传递。
在该设计中每个病房都有一个按键,当患者有需要时,按下按键,此时值班室的显示屏可显示此患者的床位号,多人使用时可实现循环显示,医护人员按下“响应”键取消当前呼叫。
此系统能够为医院提供一个成本低、效率高、操作方便和易于安装维护的快捷系统。
关键词:
单片机;矩阵键盘;点阵;LED显示;呼叫系统
目录
引言1
151系列单片机的简介1
1.1单片机的发展介绍1
1.2单片机的结构特点2
1.3单片机的实际应用2
1.4控制器AT89C513
2接口技术4
2.1键盘接口4
2.2显示器接口5
3程序设计语言9
3.1机器语言9
3.2汇编语言9
3.3高级语言9
4基于单片机的病床呼叫系统的设计实现10
4.1系统总体设计10
4.2系统硬件设计11
4.3系统软件设计15
4.4系统的调试与结果19
结论20
致谢20
参考文献21
附录22
附录A:
原理图22
附录B:
源程序22
图2.4显示屏系统框图
4基于单片机的病床呼叫系统的设计实现
4.1系统总体设计
4.1.1功能要求
本课题主攻方向是使系统实现以下目的:
①任一病房(共16张)呼叫,医护值班室马上能响应并显示病房号;
②显示病房床号;
③若有多个病床呼叫就循环显示;
④处理完毕后清除记录;
⑤显示器不重复显示按一次以上的病床号
4.1.2设计方案
用8051自身接口实现数码管静态显示和键盘扫描,使用8051单片微机外加作地址锁存用的四块三态锁存器74LS373芯片和一块74LS138芯片可构成一个完整的最小微机电路。
以此为基础,在智能装置中若要配置多位数码管显示器,以及m行n列矩阵键盘的话,可以不扩展I/O芯片而由8051自身I/O口,实现上述功能,即用P0口的八个端口作为LED的段选,用P2口的高三位连接一个三八译码器74LS138作为四个LED的片选.用P1口和P2口的低五位做键盘电路的接口。
4.1.3总体结构框图
本设计是基于AT89C51单片机设计的病房呼叫系统设计,该系统就是以Atmel公司的AT89C51单片机作为主控器,包括键盘输入电路,显示电路,以及晶振复位电路等来实现病房呼叫系统。
图4.1病房呼叫系统结构框图
4.2系统硬件设计
4.2.1硬件构成示意图
图4.2硬件构成示意图
4.2.2外围电路设计
4.2.2.1控制器AT89C51
复位电路:
RST引脚是复位信号输入端,高电平有效。
采用上电加按钮复位,因为本系统设计考虑到该系统比较重要,所以除了采用上电复位的方式外,应该还有按钮复位备用复位方式以防止系统死机时能。
如下图4.3所示:
图4.3上电复位和按键复位
时钟电路:
时钟是时序的基础,AT89C51核片内由一个反相放大器构成振荡器,可以由它产生时钟,时钟可以由两种方式产生内部方式和外部方式。
本系统采用内部方式,在XTAL1和XTAL2端外接石英晶体作为定时元件,内部反相放大器自激振荡,产生时钟。
时钟发生器对振荡脉冲二分频。
电容采用30pF电容。
如下图4.4所示:
图4.4内部时钟电路
4.2.2.2键盘电路设计
1、键的识别
为了识别键盘上的闭合键,通常采用两种方法,一种称为行扫描法,另一种称为行反转法。
行扫描法的原理:
行扫描法识别闭合键的原理如下:
先使第0行接地,其余行为高电平,然后看第0行是否有键闭合,这是通过检查列线电位来实现的,即在第0行接地时,看是否有条列线变成低电平。
如果有某条列线变为低电平,则表示第0行和此列线相交位置上的键被按下;如果没有任何一条列线为低电平,则说明第0行上没有键被按下。
此后,再将第1行接地,,然后检测列线中是否有变为低电平的线。
如此往下逐行扫描,直到最后一行。
在扫描过程中,当发现某一行有键闭合时,也就是列线输入中有一位为0时,便在扫描中途退出,而将输入值进行移位,从而确定闭合键所在的列线位置。
根据行线位置和列线位置便能再扫描法来确定具体位置。
将行线和一个并行接口相接,CPU每次使并行输出接口的某一位为0,便相当于将某一行线接地,而其他位为1,则相当于使其他行线处于高电平。
为了检查列线上的电位,将列线和一个并行输入输出口相接,CPU只要读取输入输出口中的数据,就可以设法判别出第几号键被按下[11]。
从上面的原理中知道,程控扫描法是由程序控制键扫描的方法。
程控扫描的任务是:
①首先判断是否有键按下。
其方法是使所有的行输出均为低电平,然后从端口A读入列值。
如果没有键按下,则读入的列值为FFH;如果有键按下,则读入的列值不为FFH。
②去除键抖动。
若有键按下,则延时5~10ms,再一次判断有无键按下,如果此时仍有键按下,则认为键盘上有一个键处于稳定闭合期。
③若有键闭合,则求出闭合键的键值.求键值的方法是对键盘逐行扫描。
如图4.5是行扫描法:
N
图4.5行扫描法的流程图
(2)行反转法的原理[12]。
行反转法也是识别闭合键的常用方法,它的原理如下所述。
这了叙述方便,以4×4=16键的键盘为例。
图4.6是行反转法的工作示意图:
图4.6行反转法连接图
从图中可以看到,用行反转法识别闭合键时,要将行线接一个并行口,先让它工作为输出方式,将列线接到一个并行口,先让它工作在输出方式。
程序使CPU通过输出端口往各行线上全部送低电平,然后读入列线的值。
如果此时有某一个键被按下,则必定会使某一列线值为0,然后,程序再对两个并行端口进行方式设置,使接行线的并行端口工作在输出方式,而使接列线的并行端口工作在输出方式,并且将刚才读得的列线值从所接的并行端口输出,再读取行线的输入值,那么,在闭合键所在的行线上的值必定为0。
这样,当一个键被按下时,必定可以读得一对惟一的行值和列值。
在键盘设计时,除了以键码的识别以外,还有抖动问题需要解决[13]。
有软件方法可以很容易解决抖动问题,这就是通过延迟来等待抖动消失,这之后,再读入键码。
4.2.2.3显示电路设计
在LED的点阵显示中,已经详细介绍了显示的原理,此外还需要知道显示驱动程序。
显示驱动程序在进入中断后首先要对定时器T0重新赋初值,以保证显示屏刷新率的稳定,1/16扫描显示屏的刷新率(帧频)计算公式如下:
刷频率(帧频)=1/16×T0溢出率
=1/16×f/12(65536-t)
其中f位晶振频率,t为定时器T0初值(工作在16位定时器模式)。
然后显示驱动程序查询当前燃亮的行号,从显示缓存区内读取下一行的显示数据,并通过串口发送给移位寄存器。
为消除在切换行显示数据的时候产生拖尾现象,驱动程序先要关闭显示屏,即消隐,等显示数据打入输出锁存器并锁存,然后再输出新的行号,重新打开显示。
图4.7为显示驱动程序(显示屏扫描函数)流程图:
图4.7显示驱动流程图图4.8控制按键
4.2.2.4控制电路设计
三个控制按键分别接p3.2,p3.3,p3.4口(如图4.8所示),当有呼叫发出时,值班室人员收到相应信息后,可按下“响应按钮”,单片机执行中断程序。
4.2.2.5示警电路
报警电路由一个led灯与p3.1口相接,当有键按下时,有信号输入,灯亮示警,提醒值班人员有病人出现紧急情况。
4.3.2系统程序设计
4.3.2.1系统主程序设计的流程如图4.11所示:
_______________________________________________________________________________________________________________________________
图4.11系统主程序设计的流程
主程序程序描述:
首先对各存储单元初始化,设定定时初值,接着判断清零键,看是否按下,若按下,则清零,然后继续扫描键盘,如扫描到键盘有键按下,则调用计数显示子程序,循环显示病床号时,要判断标志位是否为1,若为1,则表示已经按下,则不响应,如为0,则调用循环显示病床号子程序,循环显示病床号,接着定时一秒。
最后,清除定时一秒,准备下一次的定时。
4.3.2.2显示电路流程图
N
N
图4.12按键总数显示程序流程图图4.13按键循环显示子程序
显示程序描述
(1)按下键总数显示子程序描述(图4.12按键总数显示程序流程图)
把按键数存储单总元(COUNTER)的值经过BCD调整后十位和个位分别送(7AH)(7BH),调用显示子程序显示按键总数。
(2)循环显示病床号子程序描述(图4.13按键循环显示子程序)
首先判断标志位是否为0,若为0,则表对示应的存储单元里没有值存入,则再检测下一个存储单元标志位是否为0,直到检测到为1.如为1,则把值存入(BED_BOUNTER)中,接着进行BCD调整为十进制,把十位和个位分别送入(BEDCODE_1)和(BEDCODE_2)中,然后调用显示子程序,循环显示病床号。
4.4.2结果分析
启动电源,显示屏显示0000,在按下8号键时,界下部分显示病床(即8号病床呼叫);界面上部分代表共有一个病床按下,在起始位置显示(循环显示);如果现在不按清零键,再按下3号键时,按键号循环显示,可以看出该系统具有记忆功能,以至于不会忽略之前按下的按键;图5.4反映了控制电路的可行性,按up键向后选一房间(呼叫病房),down向前选一房间(呼叫病房),ok则去房间.。
综上所述,本系统实现了主要功能:
显示病床号,亮报警提醒值班人员,若有多个病床同时呼叫,则循环显示病床号,确保性息不丢失,待值班人员处理呼叫信息。
通过PROTEUS软件仿真,能达到上述结论,满足课题目目的,达到要求。
结论
至此,此系统的详细设计及过程已经结束。
在设计的过程中遇到了很多问题,发现了自己的不足之处,有很多没有学习,如Proteus仿真知识及操作,还有单片机的C语言编程;有些软件掌握得不够牢固,比如说wave仿真不熟练;通过此次学习,进一步加强了我的理解,同时提高了我独立自学的能力。
整个设计过程中,老师详细的指导,同学的帮助,以及校图书馆的资料给了我很大的帮助。
此次设计让我从中学到很多东西。
虽然中间遇到很多困难,但都对于我是一次很好的锻炼。
设计以后,才更加深刻感受到自己的学习只是理论部分,而且很多时候不能付诸实践。
这次设计能够让我从实践中重新学习理论知识,对我今后的工作和学习有了很多提高。
但是由于本人水平有限,整个设计仍有很多不足之处,如程序不够完善、灵活,显示可以采用液晶LCD模块,还有可以采用无线NRF2401射频模块及其无线扩展功能等等。
完善后将会进一步提高设计的稳定性和普适性。
最后,在指导老师和同组同学的身上我学得到很多实用的知识,特别感谢指导老师给予的帮助,还用同学之间的资源共享。
再次表示感谢!
致谢
时光匆匆,大学三年已经接近尾声。
这三年给我留下很多美好的记忆,同时接受很多优秀老师的教育,和很多同学的帮助。
在此论文完成之际,我要向这三年来帮助我的老师、同学表示由衷的感谢!
这几个月的毕业设计,充满了忙碌,也感到学习的充实。
从拿到毕业设计的题目,之后便开始整理材料,这期间,在图书馆里找到很多有关书籍。
然后开始了一系列的整体方案的设计,并投入选择器材和方案的制定。
最后开始整体的实验,虽然其中经历很多的失败。
在老师、同学的帮助下,我很快克服了困难。
设计的系统虽不是那么完善,但也是从知识到实践的转换。
我从中学到了怎样独立地思考发现问题、解决问题和进一步完善提高的能力。
时光短暂,但给我留下很多深刻的印象,这是第一次独立自主的做设计。
以前只注重理论的学习,却忽略了实践。
通过此次设计,对我今后的学习和工作必将有很大的帮助。
在此,谨向所有帮助我的老师、同学表示衷心的感谢和敬意!
附录B:
源程序
#include//51系统端口定义h文件
#include"dianzhen.h"//点阵h文件
#include"keyboard.h"//键盘处理h文件
ucharys=0,num=0,N=0,d=0,q=0;//num为当前显示值,N为总显示值
/******************************主函数**********************************/
voidmain()
{ucharj;
TMOD=0x10;
TH0=(65536-45000)/256;//设置50毫秒定时
TL0=(65536-45000)%256;
TR0=1;
ET0=1;
EA=1;
P3_1=0;
while
(1)
{
if(P3_2==0)
{
if(N>q)q++;
while(P3_2==0);
P3_1=1;//当P3_2按键弹起的后,P3_1口赋高电平
delay10ms(10);//延时子程序
P3_1=0;//返回原始界面
}
if(P3_3==0)//当P3_3按键按下就执行病房号的显示
{
if(q>0)q--;
while(P3_3==0);
P3_1=1;
delay10ms(10);
P3_1=0;
}
if(P3_4==0)
{
N--;
if(N>0)
{
for(j=q;jb[j]=b[j+1];
b[N]=0;
}
Else
b[0]=0;
while(P3_4==0);
q=0;
P3_1=1;
delay10ms(10);
P3_1=0;
}
keyboard();
if(m!
=key)
{m=key;
b[N]=key;
N++;
P3_1=1;
delay10ms(10);
P3_1=0;
}
}
}
/************************中断服务子程序******************************/
voidtimer0()interrupt1using1//T0中断
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
if(d==0)
display1(N,b[num],b[q]);
ys++;
if(ys==100)
{
num++;
d=1;
}
elseif(ys>105)
{
d=0;
ys=0;
}
if(num>N)
num=0;//病房号数清零
}
/*********************************点阵子程序***************************/
#include
#include
#include"zimo.h"
ucharb[10];
/****************************延时子程序********************************/
voiddelay10ms(uchard)
{unsignedchari,j,k;
for(k=d;k>0;k--)
{for(i=20;i>0;i--)
For(j=248;j>0;j--);
}
}
/******************************点阵显示子程序**************************/
voiddisplay1(ucharx,uchars,ucharp)
{uchari,j=0,k,m=0,n=0,w[2],y[2],z[2];
w[0]=s/10;w[1]=s%10;
y[0]=x/10;y[1]=x%10;
z[0]=p/10;z[1]=p%10;
if(s<=0|s>16)
{for(i=0;i<16;i++,n++)
{
lie=i;
if(n==8){m=1;j=0;}
for(k=0;k<1;k++)
{hang0=shuzi2[y[m]][j];
hang1=shuzi2[y[m]][j+1];
hang2=shuzi2[z[m]][j];
hang3=shuzi2[z[m]][j+1];
hang0=0x00;//清屏
hang1=0x00;
hang2=0x00;
hang3=0x00;
}
j+=2;
}
j=0;
for(i=16;i<64;i++)
{
lie=i;
for(k=0;k<1;k++)
{hang0=ziku1[j];//第0行赋值
hang1=ziku1[j+1];//第1行赋值
hang2=ziku2[j];///第2行赋值
hang3=ziku2[j+1];///第3行赋值
hang0=0x00;//清屏
hang1=0x00;
hang2=0x00;//清屏
hang3=0x00;
}
j+=2;
}
}
else{for(i=0;i<16;i++,n++)
{lie=i;
if(n==8){m=1;j=0;}
for(k=0;k<1;k++)
{
hang0=shuzi2[w[m]][j];
hang1=shuzi2[w[m]][j+1];
hang2=shuzi2[z[m]][j];
hang3=shuzi2[z[m]][j+1];
hang0=0x00;//清屏
hang1=0x00;
hang2=0x00;//清屏
hang3=0x00;
}
j+=2;
}
j=0;
for(i=16;i<64;i++)
{lie=i;
for(k=0;k<1;k++)
{hang0=ziku2[j];
hang1=ziku2[j+1];
hang2=ziku2[j];
hang3=ziku2[j+1];
hang0=0x00;//清屏
hang1=0x00;
hang2=0x00;//清屏
hang3=0x00;
}
j+=2;
}
}
}