设计并实现可编倒计时装置.docx
《设计并实现可编倒计时装置.docx》由会员分享,可在线阅读,更多相关《设计并实现可编倒计时装置.docx(36页珍藏版)》请在冰豆网上搜索。
设计并实现可编倒计时装置
目录
1设计原理或方法1
1.1MCS-51单片机简介1
2硬件电路及主要模块设计原理3
2.1单片机最小系统3
2.2震荡电路模块和原理3
2.3复位电路模块和原理3
2.4按键电路及原理4
2.5LED模块和显示原理5
2.6蜂鸣器电路和原理7
2.7设计总电路和原理7
3程序框图9
4资源分配9
5源程序10
6性能分析22
6.1系统调试工具keiluvision422
6.2系统调试工具PROTEUS23
6.3仿真与分析24
7总结与心得25
8.参考文献27
具体源程序发邮件至xiaopoyu@
1设计原理或方法
1.1MCS-51单片机简介
单片机它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。
作为嵌入式系统控制核心的单片机具有其体积小、功能全、性价比高等诸多优点。
51系列单片机是国内目前应用最广泛的单片机之一,随着嵌入式系统、片上系统等概念的提出和普遍接受及应用,51系列单片机的发展又进入了一个新的阶段。
在今后很长一段时间内51系列单片机仍将占据嵌入式系统产品的中低端市场。
C语言是本设计的程序设计语言,它比低级语言更通俗易懂,设计更为方便,故采用它来设计程序。
单片机全称为单片微型计算机(SingleChipMicrocomputer)。
因为单片机主要用于控制系统中,所以又称微控制器(MicrocontrollerUnit,MCU)或嵌入式控制器(EmbeddedController)。
它具有嵌入式应用系统所要求的体系结构,微处理器,指令系统,总线方式,管理模式等。
他把计算机的基本部件都微型化集成到一块芯片上了,通常片内部都含有中央处理部件(CPU),数据存储器(RAM),程序存储器(ROM,EPROM,FlshROM),定时器/计数器和各种输入/输出(I/O)接口他们之间的相互连接结构如图1-1所示。
图1-1单片机结构
8051是MCS-51系列单片机的典型产品,我们以这一代表性的机型进行系统的讲解。
8051单片机包含中央处理器、程序存储器(ROM)、数据存储器(RAM)、定时/计数器、并行接口、串行接口和中断系统等几大单元及数据总线、地址总线和控制总线等三大总线,现在我们分别加以说明:
1)中央处理器:
中央处理器(CPU)是整个单片机的核心部件,是8位数据宽度的处理器,能处理8位二进制数据或代码,CPU负责控制、指挥和调度整个单元系统协调的工作,完成运算和控制输入输出功能等操作。
2)数据存储器(RAM):
8051内部有128个8位用户数据存储单元和128个专用寄存器单元,它们是统一编址的,专用寄存器只能用于存放控制指令数据,用户只能访问,而不能用于存放用户数据,所以,用户能使用的RAM只有128个,可存放读写的数据,运算的中间结果或用户定义的字型表。
3)程序存储器(ROM):
8051共有4096个8位掩膜ROM,用于存放用户程序,原始数据或表格。
4)定时/计数器(ROM):
8051有两个16位的可编程定时/计数器,以实现定时或计数产生中断用于控制程序转向。
5)并行输入输出(I/O)口:
8051共有4组8位I/O口(P0、P1、P2或P3),用于对外部数据的传输。
6)全双工串行口:
8051内置一个全双工串行通信口,用于与其它设备间的串行数据传送,该串行口既可以用作异步通信收发器,也可以当同步移位器使用。
7)中断系统:
8051具备较完善的中断功能,有两个外中断、两个定时/计数器中断和一个串行中断,可满足不同的控制要求,并具有2级的优先级别选择。
8)时钟电路:
8051内置最高频率达12MHz的时钟电路,用于产生整个单片机运行的脉冲时序,但8051单片机需外置振荡电容。
单片机的结构有两种类型,一种是程序存储器和数据存储器分开的形式,即哈佛(Harvard)结构,另一种是采用通用计算机广泛使用的程序存储器与数据存储器合二为一的结构,即普林斯顿(Princeton)结构。
INTEL的MCS-51系列单片机采用的是哈佛结构的形式,而后续产品16位的MCS-96系列单片机则采用普林斯顿结构。
2硬件电路及主要模块设计原理
2.1单片机最小系统
最小系统就是单片机在发挥具体测控功能时所必须的组成部分。
图2-1最小系统方框图
2.2震荡电路模块和原理
本次设计要使用到AT89C51单片机的时钟振荡功能。
AT89C51中有一个用于构成内部震荡器的高增益反相放大器,引脚XTAL1和XTAL2分别是该放大器的输入和输出端。
这个放大器与作为反馈元件的片外石英晶体或者陶瓷谐振器一起构成自激振荡器。
2.3复位电路模块和原理
8051的复位方式可以是自动复位,也可以是手动复位,见下图2-2。
此外,RESET/Vpd还是一复用脚,Vcc掉电其间,此脚可接上备用电源,以保证单片机内部RAM的数据不丢失。
图2-2复位电路图
复位电路虽然简单,但其作用非常重要。
一个单片机系统能复正常运行,首先要检查是否能复位成功,其中手动复位开关比较常用,手动开关未按下之前,电容正极处于充电状态,当按键按下去后,VCC与GND导通,电容放电,从而实现放电。
2.4按键电路及原理
采用矩阵键盘方式输入设计键盘控制电路部分,其中用到5个按键,分别是时分秒的置数控制位,启动和报警控制位。
其键盘结构图如下所示:
图2-3键盘结构
图2-4上拉电阻结构
那么在什么时候使用上拉电阻呢?
总结如下:
(1)当TTL电路驱动CMOS电路时,如果TTL电路输出的高电平低于CMOS电路的最低高电平(一般为3.5V),这时就需要在TTL的输出端接上拉电阻,以提高输出高电平的值。
(2)OC门电路必须加上拉电阻,以提高输出的搞电平值。
(3)为加大输出引脚的驱动能力,有的单片机管脚上也常使用上拉电阻。
(4)在CMOS芯片上,为了防止静电造成损坏,不用的管脚不能悬空,一般接上拉电阻降低输入阻抗,提供泄荷通路。
(5)芯片的管脚加上拉电阻来提高输出电平,从而提高芯片输入信号的噪声容限,增强抗干扰能力。
(6)提高总线的抗电磁干扰能力。
管脚悬空就比较容易接受外界的电磁干扰。
(7)长线传输中电阻不匹配容易引起反射波干扰,加上拉电阻使电阻匹配,有效的抑制反射波干扰。
另外,上拉电阻阻值的选择原则包括:
(1)从节约功耗及芯片的灌电流能力考虑应当足够大;电阻大,电流小。
(2)从确保足够的驱动电流考虑应当足够小;电阻小,电流大。
(3)对于高速电路,过大的上拉电阻可能边沿变平缓。
综合考虑以上三点,上拉电阻阻值通常在1k到10k之间选取。
根据以上原则,本设计所选择的是10K的电阻。
2.5LED模块和显示原理
LED显示器又称为数码管,LED显示器由8个发光二极管组成。
中7个长条形的发光管排列成“日”字形,另一个贺点形的发光管在显示器的右下角作为显示小数点用,它能显示各种数字及部份英文字母。
LEDD显示器有两种不同的形式:
一种是8个发光二极管的阳极都连在一起的,称之为共阳极LED显示器;另一种是8个发光二极管的阴极都连在一起的,称之为共阴极LED显示器
数码管的分类:
数码管按段数分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管单元(多一个小数点显示);按能显示多少个“8”可分为1位、2位、4位等等数码管;按发光二极管单元连接方式分为共阳极数码管和共阴极数码管。
共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管。
共阳数码管在应用时应将公共极COM接到+5V,当某一字段发光二极管的阴极为低电平时,相应字段就点亮。
当某一字段的阴极为高电平时,相应字段就不亮。
共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM)的数码管。
共阴数码管在应用时应将公共极COM接到地线GND上,当某一字段发光二极管的阳极为高电平时,相应字段就点亮。
当某一字段的阳极为低电平时,相应字段就不亮。
数码管的驱动方式:
数码管要正常显示,就要用驱动电路来驱动数码管的各个段码,从而显示出我们要的数字,因此根据数码管的驱动方式的不同,可以分为静态式和动态式两类。
1)静态显示驱动:
静态驱动也称直流驱动。
静态驱动是指每个数码管的每一个段码都由一个单片机的I/O端口进行驱动,或者使用如BCD码二-十进制译码器译码进行驱动。
静态驱动的优点是编程简单,显示亮度高,缺点是占用I/O端口多,如驱动5个数码管静态显示则需要5×8=40根I/O端口来驱动,实际应用时必须增加译码驱动器进行驱动,增加了硬件电路的复杂性。
2)动态显示驱动:
动态驱动是将所有数码管的8个显示笔划"a,b,c,d,e,f,g,dp"的同名端连在一起,另外为每个数码管的公共极COM增加位选通控制电路,位选通由各自独立的I/O线控制,当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是那个数码管会显示出字形,取决于单片机对位选通COM端电路的控制,所以我们只要将需要显示的数码管的选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。
通过分时轮流控制各个数码管的的COM端,就使各个数码管轮流受控显示,这就是动态驱动。
在轮流显示过程中,每位数码管的点亮时间为1~2ms,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感,动态显示的效果和静态显示是一样的,能够节省大量的I/O端口,而且功耗更低。
本次电路设计采用的是共阴极数码管,通过动态扫描方式驱动,其电路模块如下:
图2-5数码管结构
2.6蜂鸣器电路和原理
蜂鸣器部分采用IO口输出,单片机P1端口驱动蜂鸣器。
蜂鸣器有两类三大品种。
一类是压电式,一类是电磁式,电磁式又有两大品种,铁振膜式和动圈式,二者原理一样只是结构不同。
所有蜂鸣器都有两种类型:
纯蜂鸣器和带驱动的蜂鸣器,蜂鸣器都是用音频信号驱动的,都是交流驱动。
报警器的种类很多,比如:
扬声器,蜂鸣器等,本次设计采用的是电磁式蜂鸣器作为报警器。
电磁式蜂鸣器由振荡器、电磁线圈、磁铁、震动膜片以及外壳等组成。
接通电源后,振荡器产生的音频信号通过电磁线圈,使得电磁线圈产生了一个磁场。
振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。
蜂鸣器电路图如图所示:
图2-6蜂鸣器结构
2.7设计总电路和原理
本课设使用AT89C51加上少许的外围电路就可做成一个时分秒倒计时器,并在达到设定计数时输出一音频信号。
系统由主单片机和外围电路构成,系统整体硬件电路包括,显示部分、按键调整部分以及单片机主板部分。
主机包括定时输入电路,按键控制电路,LED显示电路等,从机包括LED显示电路,扬声器输出电路等。
其中主机的时分秒定时值由P0和P3口进行选择输入,有矩阵键盘选择控制,时分秒分别控制置数,启动置数,报警控制;主机LED采用7段共阴极数码管,从机LED采用多个发光二极管阵列组成字形段码,以满足较远距离清晰显示。
74LS245是常用用来驱动LED或者其他的设备的芯片,它是8路同相三态双向总线收发器,可双向传输数据当8051单片机的P0口总线负载达到或超过P0最大负载能力时,必须接入74LS245等总线驱动器。
当片选端/CE低电平有效时,DIR=“0”,信号由B向A传输(接收)。
图2-7总体电路图
3程序框图
4资源分配
编程之前,应先将可用资源和需要资源列举出来,一一分配后就能清楚的了解整个设计结构,不易出错。
AT89C51单片机IO口有P0、P1、P2、P3,中断源有外部中断0、1两个,定时器中断0、1两个,一个串口中断。
外围电路为8位数码管,8个上拉电阻,1个蜂鸣器,5个轻触式按键,并要求能够计时1秒。
现分配如下:
8位数码管的数据端连接在一起,然后接入AT89C51P0端口;其8个共阴极引脚接入P3口作为选通。
P1为标准双向IO口,因而将5个按键接到P1上。
蜂鸣器则接到P1.7口上。
为了计时1秒以及动态扫描数码管,使用一个定时器0作为时钟。
5源程序
1)主程序:
#include"Key.h"
#include"led.h"
uchartimeSetBuff[8]={'0','0',LED_MODE_COUNT,'0','0',LED_MODE_COUNT,'0','0'};//时钟数据缓冲区
ucharalarmSetBuff[8]={'0','0',LED_MODE_ALARM,'0','0',LED_MODE_ALARM,'0','0'};//闹钟时间数据缓冲区
uchartimeDisMod=0x24;//00100100
ucharsecondTemp,minuteTemp,hourTemp;
ucharsecondAlarm,minuteAlarm,hourAlarm;
uchartimer0Temp;
ucharalarmKeyCount;//闹钟起停键计数
ucharkeyRead;
bitalarm_is_ok;//闹钟起停状态
bittime_is_ok;//时间是否到
bitinterface_mod;//显示界面模式,0为主时间界面,1为设置界面
voidcommand(void);//控制命令
voiddelay_20s(void);//延迟20s
/*******************************************************************************函数名称:
定时器0
*功能:
定时器0初始化
*入口参数:
无
*出口参数:
无
******************************************************************************/
voidinitTimer0(void)//定时10ms
{
TMOD=0x01;//GATE=0,TR=1运行;C/T=1,counter,0,timer;01十六进制
TH0=0xdc;
TL0=0x00;
TR0=1;//timer0控制位,为1时启动timer0
ET0=1;//timer0中断使能
}
/*******************************************************************************函数名称:
时钟比较
*功能:
比较时钟和闹钟的时间缓冲区,只比较时和分
*入口参数:
无
*出口参数:
无
******************************************************************************/
voidtimeCompare(void)
{
if((minuteTemp==minuteAlarm)&&(hourTemp==hourAlarm))
{
time_is_ok=1;
alarm_is_ok=0;
interface_mod=1;
}
}
/*******************************************************************************函数名称:
主函数
*功能:
调用并执行各个子函数
*入口参数:
无
*出口参数:
无
******************************************************************************/
voidmain()
{
init_led();
init_key();
initTimer0();
timer0Temp=0x00;
secondTemp=59;
minuteTemp=59;
hourTemp=23;
secondAlarm=0x00;
minuteAlarm=0x00;
hourAlarm=0x00;
alarmKeyCount=0x02;
alarm_is_ok=0;//默认状态停止
time_is_ok=0;//默认时间未到
interface_mod=0;
sei();
while
(1)
{
if(interface_mod==1)
ledSweepDisplay(alarmSetBuff,timeDisMod);
else
ledSweepDisplay(timeSetBuff,timeDisMod);
if(alarm_is_ok==1)
timeCompare();
keyRead=get_key_value();
while(P1_4==1)
{TR0=0;
if(interface_mod==1)
ledSweepDisplay(alarmSetBuff,timeDisMod);
else
ledSweepDisplay(timeSetBuff,timeDisMod);
if(alarm_is_ok==1)
timeCompare();
keyRead=get_key_value();
command();
}
TR0=1;
command();
}
}
/******************************************************************************
*函数名称:
定时器0中断函数
*功能:
定时器0溢出中断入口处,定时10ms
*入口参数:
无
*出口参数:
无
******************************************************************************/
voidtimer0_overflow(void)interrupt1
{
TH0=0xdc;
TL0=0x00;
if(secondTemp==0&&minuteTemp==0&&hourTemp==0)//报警
time_is_ok=1;
if(time_is_ok==1)//报警
WARN_TRUMPET=~WARN_TRUMPET;
if(timer0Temp<99)//判断1s是否到
timer0Temp++;
else//进中断100次
{
timer0Temp=0x00;
if(secondTemp>0)//判断1min是否到
{
secondTemp--;
}
else
{
secondTemp=59;
if(minuteTemp>0)//判断1hour是否到
minuteTemp--;
else
{
minuteTemp=59;
if(hourTemp>0)
hourTemp--;
else
hourTemp=23;
}
}
}
timeSetBuff[S_L]=secondTemp%10+'0';
timeSetBuff[S_H]=secondTemp/10+'0';
timeSetBuff[M_L]=minuteTemp%10+'0';
timeSetBuff[M_H]=minuteTemp/10+'0';
timeSetBuff[H_L]=hourTemp%10+'0';
timeSetBuff[H_H]=hourTemp/10+'0';
sei();
}
voidcommand(void)
{
if(keyRead==KEY_ALARM)
{
if(alarm_is_ok==1||time_is_ok==1)
{
alarm_is_ok=0;
time_is_ok=0;
interface_mod=0;
alarmKeyCount=0x00;
}
else
{
if(alarmKeyCount<0x02)
alarmKeyCount++;
else
alarmKeyCount=0x00;
if(alarmKeyCount==0x01)
interface_mod=1;
if(alarmKeyCount==0x02)
{
alarm_is_ok=1;
interface_mod=0;
}
}
}
if(keyRead==KEY_SECOND)
{if(interface_mod==1)
{
if(secondAlarm<59)
secondAlarm++;
else
secondAlarm=0x00;
alarmSetBuff[S_L]=secondAlarm%10+'0';
alarmSetBuff[S_H]=secondAlarm/10+'0';
}
else
{
if(secondTemp<59)
secondTemp+=1;
else
secondTemp=0x00;
timeSetBuff[S_L]=secondTemp%10+'0';
timeSetBuff[S_H]=secondTemp/10+'0';
}
}
if(keyRead==KEY_MINUTE)
{if(interface_mod==1)
{
if(minuteAlarm<59)
minuteAlarm++;
else
minuteAlarm=0x00;
alarmSetBuff[M_L]=minuteAlarm%10+'0';
alarmSetBuff[M_H]=minuteAlarm/10+'0';
}
else
{
if(minuteTemp<59)
minuteTemp+=1;
else
minuteTemp=0x00;
timeSetBuff[M_L]=minuteTemp%10+'0';
timeSetBuff[M_H]=minuteTemp/10+'0';
}
}
if(keyRead==KEY_HOUR)
{
if(interface_mod==1)
{
if(hourAlarm<23)
hourAlarm++;
else
hourAlarm=0x00;
alarmSetBuff[H_L]=hourAlarm%10+'0';
alarmSetBuff[H_H]=hourAlarm/10+'0';
}
else
{
if(hourTemp<23)
hourTemp+=1;
else