多功能数字钟设计报告.docx
《多功能数字钟设计报告.docx》由会员分享,可在线阅读,更多相关《多功能数字钟设计报告.docx(24页珍藏版)》请在冰豆网上搜索。
![多功能数字钟设计报告.docx](https://file1.bdocx.com/fileroot1/2022-11/23/c0ad7c71-598f-419d-aed9-73ccc8cf1be4/c0ad7c71-598f-419d-aed9-73ccc8cf1be41.gif)
多功能数字钟设计报告
多功能数字钟设计报告
摘要
本设计采用一块单片机(AT89S52)作为多功能数字钟的控制核心,加以温度传感器、红外接收管、蜂鸣器、液晶显示器(LCD1602)、电源电路及其他电路构成。
实现了时间设置、闹铃设置、闹铃开和关的功能;LCD显示小时、分钟,有AM、PM指示灯,闹钟就绪灯,闹钟到点蜂鸣器报警,220V供电基本功能。
另外,本设计还实现了通过切换键盘显示现场温度,红外停止闹铃的功能。
Abstract
Thisdesignusesasinglechip(AT89S52)asthecorecontrollerofamulti-functionaldigitalclock,complementedbytemperaturesensor,infraredreceiver,buzzer,liquidcrystaldisplay(LCD1602),powercircuitandothercircuit.Itimplementestimesetting,alarmsetting,andalarmon/offfunctions.Moreover,ithassomebasicfunctionssuchasdisplayinghourandminute,AM/PMindicatorlight,alarmclockreadylight,buzzeralarmand220Vpowersupply.Intheend,thisdesignalsocanshowthescenetemperaturethroughswitchingthekeyboards,andstopthealarmbyinfraredcircuit.
一、方案比较与设计
1、数字时钟显示器的选择与控制
方案一:
采用5只7段共阴极数码管,分别显示小时、’—’及分钟(如23-30),P0口连接数码管的段选端(a、b、c、d、e、f、g),P2口(0-4端)控制数码管位选端(cs1-cs5)。
方案二:
采用一块液晶显示器(LCD1602),显示内容多,可以显示AM(PM)、小时、“:
”、分钟及秒钟(如PM23:
30:
30),另外控制也较为方便,只用两个控制线(lcdrs、lcden)。
方案一编程较简单,但硬件电路较乱;方案二编程与硬件电路实现都较为方便。
考虑到本设计的需要,采用方案二。
2、按键的选择与控制
方案一:
采用4只轻触按键完成各项功能的设置,分别为功能键、增加键、减少键、开关闹铃键,采用按键复用的设计思路。
此种方案硬件简单,软件实现困难。
方案二:
采用6只轻触按键完成各项功能的设置,分别为设置时间、设置闹铃、调整小时、调整分钟、开闹铃、关闹铃,采用分模块的设计思路。
此种方案必第一种只多2只按键,软件实现较为方便。
所以采用方案二。
二、系统设计
1、系统框图
电路说明:
ØAM、PM、闹铃就绪LED指示灯部分,三只LED发光二极管分别作为AM、PM、闹铃就绪指示灯。
ØLCD1602液晶显示器部分,作为本系统的显示器,显示时间、闹钟与温度。
Ø蜂鸣器、温度传感器、红外接收部分,分别用来闹铃到点报警,显示现场温度及非接触时停止闹铃。
Ø键盘部分,作为本系统的控制部分,用来设置时间、闹铃与显示温度。
2、方案实现
1)电源电路
本系统采用5V直流电源作为整个电路的供电模块,电路如下:
电容滤波,LED电源指示灯。
2)系统电路图。
除电源模块外,由单片机复位电路,单片机晶振电路,LED指示灯电路,温度传感器(DS18B20),蜂鸣器,LCD1602,红外接收电路,键盘接口电路组成。
系统整体电路如下图所示
3)系统电路说明:
ØLED指示灯电路:
分别用3只发光二极管作为AM、PM和闹铃就绪的指示的灯。
ØLCD1602液晶显示器接口电路:
将单片机的P2.7和P2.6分别连接LCD的RS和EN端,P0口接LCD的数据端(DB0-DB7)。
LCD1602显示时间、闹铃、温度。
Ø温度传感器接口电路:
将单片机的P1.5与温度传感器的数据口相连。
用单片机控制温度传感器,采集实时温度,并通过LCD显示。
Ø蜂鸣器接口电路:
通过一个PNP三极管放大电路,将单片机的P3.6与三极管的基极相接,实现单片机控制蜂鸣器发声。
Ø键盘接口电路:
本系统共用6只接触式按键,分别与单片机的P2.0-P2.5相连,实现单片机控制键盘。
Ø红外接口电路:
红外接收管的数据端与单片机的P3.2相连,通过中断实现单片机对红外的控制,进而实现非接触式停止闹铃功能。
4)键盘功能说明:
Ø本系统共用到6只按键,分别用来设置时间、设置闹铃、调整小时、调整分钟、开闹铃、关闹铃。
Ø实时时间显示在LCD的第二行,闹钟时间与温度显示在第一行。
Ø设置时间与设置闹铃处于同一优先级,不可同时有效。
当设置完闹铃时,闹钟时间在第一行消隐掉。
Ø调整小时与调整分钟必须在设置时间或设置闹铃按下时才有效。
Ø开闹铃与关闹铃相对独立,不受其他按键的影响。
Ø调整小时的按键作为切换显示温度的开关,当他作为第二功能用时,设置时间与设置闹铃的功能无效。
三、理论分析与计算
1、时间的控制与计算。
用定时器实现单片机的时间走动,定时器0定时50ms,经20次中断就过了1s,每过1s在中断服务程序中,通过软件编程让秒、分、时显示在LCD上。
单片机不停的扫描键盘,当有按键按下时,就进入相应的服务程序。
如:
当设置时间键按下时,时间停止,进入调整时间状态,通过调时与调分两个按键可调整时间,再按下设置时间键就推出设置,时间继续。
2、温度的采集与计算。
通过温度传感器采集实时温度,由于室温大于0度小于100度,本系统对温度不要求特别精确,故保留两位整数,一位小数显示在LCD上。
通过调时按键的第二功能,可切换键盘将温度显示在LCD的第一行。
3、蜂鸣器报警的设计。
当闹铃到点时,蜂鸣器就发出“滴滴”的声音以报时。
软件实现方法就是:
当闹钟的时间与实施时间对应相等就代表闹铃到点。
若不打开闹铃,蜂鸣器就不发声;在蜂鸣器发声的过程中,若关掉闹铃,蜂鸣器就停止发声。
4、红外止闹的设计。
本系统只利用红外接收管,通过单片机的外部中断0作为红外的控制入口。
在蜂鸣器发声过程中,按下遥控器的任意一个键,单片机就可控制蜂鸣器使其停止发声。
软件实现方法就是:
在外部中断0的服务程序中,关闭蜂鸣器。
四、测试方法与调试
本系统为多功能数字钟,一切功能的测试均通过6只按键来完成。
可分别设置时间、设置闹铃、调整小时、调整分钟、开闹铃、关闹铃。
本程序较大,采用C51语言编写。
先调试各功能模块,在调试整个系统。
具体电路见附件。
程序见附页。
程序:
//DS18B20.h
#include
#defineuintunsignedint
#defineucharunsignedchar
ucharlsb,msb;
uchardisbuf[7];
uchart1,t2;
sbitdq=P1^5;
bitpresence;
voiddelay(uintz)
{
uintx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
voiddelay1(uinti)//延时14us,12MHz
{while(--i);}
bitrst_ds18b20()//dq复位;没有检测从机
{
dq=1;
_nop_();//稍做延时
dq=0;//单片机将dq拉低
delay1(60);//延时480us-960us,主要是此延时要长最好800us以上
dq=1;//拉高总线
delay1(5);//延时16-60us,等待从机发存在信号
presence=dq;//从机发送60-240us的低脉冲作为存在脉冲
delay(30);//至少延时(480us-720us),等待dq拉为高电平(自动的)
returnpresence;
}
ucharrd_byte()//读时,先拉低数据线至少1us,再释放。
每两次读至少有1us的间隔
{
uchari,dat;
dq=1;
for(i=0;i<8;i++)
{
dq=0;//给脉冲信号
dat>>=1;//该句4us
dq=1;//给脉冲信号
delay1
(1);//主机马上释放总线,并延时至少14us,等待数据送上
if(dq)
dat|=0x80;
delay1(5);//保持数据至少(60us-15us),等待上拉电阻将dq拉高
}
returndat;
}
voidwr_byte(uchardat)//数据线由高拉低产生写信号
{
uchari;
dq=1;
for(i=0;i<8;i++)
{
dq=0;//dq由高拉低后,在15内期间采样dq状态
dq=dat&0x01;
delay1(8);//写数据要维持60us-120us
dq=1;//然后拉高dq
dat>>=1;
}
}
voidrd_temperature()//读取温度
{
rst_ds18b20();
wr_byte(0xCC);//只有一个从机,跳过读序列号的操作
wr_byte(0x44);//启动温度转换
rst_ds18b20();//复位
wr_byte(0xCC);//跳过读序号列号的操作
wr_byte(0xBE);//读取温度寄存器
lsb=rd_byte();//温度低8位
msb=rd_byte();//温度高8位
}
voidprocess_temperature()//处理温度
{
ucharflagdat,flag;
if(msb&0xf0)
{
flag=1;
msb=~msb;
lsb=~lsb+1;
flagdat='-';
}
else
{
flag=0;//0表示温度为正
flagdat='';
}
t1=msb<<4;
t1|=(lsb>>4);
t2=(lsb&0x0f)*0.0625*10;
disbuf[0]='T';
disbuf[1]=':
';
disbuf[2]=t1%100/10+'0';
disbuf[3]=t1%10+'0';
disbuf[4]='.';
disbuf[5]=t2+'0';
disbuf[6]='\0';
if(disbuf[2]==0x30)
{
disbuf[2]='';
if(disbuf[3]==0x30)
disbuf[3]='';
}
}
//main.c
//开闹铃时显示闹铃符号,关时不显示
//设置闹铃按1下进入设置状态;按2下,退出设置状态;
//设置时间按1下进入设置状态,并停止计时;按2下,推出设置状态,并开始计时
//当设置闹铃、时间没按下时,调时、调分不起作用
//不可以在设置时间的过程中设置闹铃,不可以在设置闹铃的过程中设置时间
//设置闹铃后,闹铃时间在第一行显示
//切换温度用到了调时键,为避免冲突,看温度与设置时间、设置闹铃不可同时有效
//每当设置闹铃时,闹铃都初始化为00:
00,设置完后,闹铃消失
//lcd1602有64B的CGRAM,可用来写入自定义字符,5*8点阵的可写8个(每个占8字节),5*11点阵的可写4个(每个占16字节)
//写命令wcmd(0x40),显示所写入字符,送入数据0x00-0x07(对应显示8个字符)。
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
voidinc_second();
voidinc_minute();
voidinc_hour();
voidbeep();
voidwdscan();
voiddisp_sfm(ucharx,uchary,uchardat);
#definePORTP0
sbitlcdrs=P2^7;//LCD数据命令选择端
sbitlcden=P2^6;//LCD使能端
sbitsetsj=P2^0;//设置时间
sbitsetnl=P2^1;//设置闹铃
sbitts=P2^2;//调整小时
sbittf=P2^3;//调整分钟
sbitknl=P2^4;//开闹铃
sbitgnl=P2^5;//关闹铃
sbitlam=P1^0;//AM指示灯
sbitlpm=P1^1;//PM指示灯
sbitlnl=P1^2;//闹铃就绪指示灯
sbitfm=P3^6;//蜂鸣器端口
//sj为设置时间按下的标志,nlflag为闹铃键按下的标志;tzflag为调时
(1)、分按下
(2)的标志
ucharsj,tzflag,nlflag,tznl,wdnum;
ucharhour,minute,second,tcnt,nlhour,nlminute,nldk;
ucharcodetable[]="23:
59:
50";
ucharcodebmp[]={0x0e,0x11,0x1f,0x00,0x0a,0x00,0x00,0x00,
0x0C,0x12,0x12,0x0C,0x00,0x00,0x00,0x00};//闹铃符号与温度符号;
voidwcmd(ucharcmd)
{
lcden=0;
lcdrs=0;
PORT=cmd;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
voidwdata(uchardat)
{
lcden=0;
lcdrs=1;
PORT=dat;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
voidgoxy(ucharx,uchary)
{
if(x==1)
wcmd(0x80+y);
else
wcmd(0x80+0x40+y);
}
voiddisp_str(uchar*str)
{
while(*str)
{
wdata(*str);
str++;
}
}
voiddisp_bmp(ucharx,uchary,uchardat)
{
goxy(x,y);
wdata(dat);
}
voidlcd_init()
{
uchari;
wcmd(0x38);//显示模式设置:
16*2,5*7,8位数据接口
wcmd(0x0c);//开显示,不显光标,光标不闪烁
wcmd(0x06);//地址自动加1
wcmd(0x01);//清屏
wcmd(0x40);//写CGRAM
for(i=0;i<16;i++)
wdata(bmp[i]);
goxy(2,0);
disp_str(table);
}
voidtimer0_init()
{
TMOD=0X01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
}
voidtimer0()interrupt1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
tcnt++;
if(tcnt==20)
{
tcnt=0;
inc_second();
disp_sfm(2,4,hour);
disp_sfm(2,7,minute);
disp_sfm(2,10,second);
wdata('');
wdata('');
wdata('');
wdata('');
wdata('');
}
}
inc_minute_nop()
{
minute++;
if(minute==60)
minute=0;
}
voidinc_second()
{
second++;
if(second==60)
{
second=0;
inc_minute();
}
}
voidinc_minute()
{
minute++;
if(minute==60)
{
minute=0;
inc_hour();
}
}
voidinc_hour()
{
hour++;
if(hour==24)
hour=0;
}
voidinc_nlminute()
{
nlminute++;
if(nlminute==60)
nlminute=0;
}
voidinc_nlhour()
{
nlhour++;
if(nlhour==24)
nlhour=0;
}
voiddisp_sfm(ucharx,uchary,uchardat)
{
ucharshi,ge;
shi=dat/10+'0';
ge=dat%10+'0';
goxy(x,y);
wdata(shi);
wdata(ge);
}
voidled_apm()
{
if(hour<12)
{
lpm=1;
lam=0;
goxy(2,0);
wdata('A');
wdata('M');
}
else
{
lam=1;
lpm=0;
goxy(2,0);
wdata('P');
wdata('M');
}
}
voidtzsjfun()
{
if(nlflag==0)//若闹铃没按下,则可设置时间,否则无效
{
if(wdnum==0)//若切换温度也没按下,则可设置时间
{if(setsj==0)
{
delay
(2);
while(!
setsj);
delay
(2);
if(setsj==1)//表示按下了设置时间,且已经消抖
{
sj++;
if(sj==1)
TR0=0;//按下1次停止计时
if(sj==2)//第2次按下表示设置完毕
{
TR0=1;
sj=0;
}
}
}
if(sj)//要调整时间
{
if(ts==0)
{
delay
(2);
while(!
ts);
delay
(2);
if(ts==1)
tzflag=1;
}
if(tf==0)
{
delay
(2);
while(!
tf);
delay
(2);
if(tf==1)
tzflag=2;
}
}
if(tzflag)
{
if(tzflag==1)
{
tzflag=0;
inc_hour();
disp_sfm(2,4,hour);
}
if(tzflag==2)
{
tzflag=0;
inc_minute_nop();
disp_sfm(2,7,minute);
}
}
}
}
}
voidnl0()
{
nlhour=0;
nlminute=0;
disp_sfm(1,4,nlhour);
wdata(':
');
disp_sfm(1,7,nlminute);
}
voidnldisappear()
{
uchari;
goxy(1,0);
for(i=0;i<9;i++)
wdata('');
delay
(2);
}
voidtznlfun()
{
if(sj==0)//若设置时间没按下,则可设置闹铃,否则无效
{
if(wdnum==0)
{if(setnl==0)
{
while(!
setnl);
delay(5);
if(setnl==1)
{
nlflag++;
if(nlflag==1)
nl0();
if(nlflag==2)//按下1次闹铃键,设置闹铃;按下2次,设置完毕;
{nlflag=0;
nldisappear();
}
}
}
if(nlflag)//要设置闹铃
{
if(nlhour<12)
{goxy(1,0);
wdata('A');
wdata('M');
}
else
{
goxy(1,0);
wdata('P');
wdata('M');
}
if(ts==0)
{
while(!
ts);
delay(5);
if(ts==1)
tznl=1;
}
if(tf==0)
{
while(!
tf);
delay(5);
if(tf==1)
tznl=2;
}
}
if(tznl)
{
if(tznl==1)
{
tznl=0;
inc_nlhour();
disp_sfm(1,4,nlhour);
}
if(tznl==2)
{
tznl=0;
inc_nlminute();
disp_sfm(1,7,nlminute);
}
}
}
}
}
voidkgnlfun()
{
if(knl==0)
{
while(!
knl);
delay(5);
i