多功能数字钟设计报告Word格式文档下载.docx
《多功能数字钟设计报告Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《多功能数字钟设计报告Word格式文档下载.docx(24页珍藏版)》请在冰豆网上搜索。
将单片机的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<
intrins.h>
#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>
y--);
}
voiddelay1(uinti)//延时14us,12MHz
{while(--i);
bitrst_ds18b20()//dq复位;
没有检测从机
{
dq=1;
_nop_();
//稍做延时
dq=0;
//单片机将dq拉低
delay1(60);
//延时480us-960us,主要是此延时要长最好800us以上
//拉高总线
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
delay1
(1);
//主机马上释放总线,并延时至少14us,等待数据送上
if(dq)
dat|=0x80;
delay1(5);
//保持数据至少(60us-15us),等待上拉电阻将dq拉高
}
returndat;
voidwr_byte(uchardat)//数据线由高拉低产生写信号
uchari;
dq=0;
//dq由高拉低后,在15内期间采样dq状态
dq=dat&
0x01;
delay1(8);
//写数据要维持60us-120us
//然后拉高dq
dat>
voidrd_temperature()//读取温度
rst_ds18b20();
wr_byte(0xCC);
//只有一个从机,跳过读序列号的操作
wr_byte(0x44);
//启动温度转换
rst_ds18b20();
//复位
//跳过读序号列号的操作
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表示温度为正
'
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+'
disbuf[4]='
.'
disbuf[5]=t2+'
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个字符)。
reg52.h>
ds18b20.h>
#defineuintunsignedint
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;
voidwdata(uchardat)
lcdrs=1;
PORT=dat;
voidgoxy(ucharx,uchary)
if(x==1)
wcmd(0x80+y);
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;
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
tcnt++;
if(tcnt==20)
tcnt=0;
inc_second();
disp_sfm(2,4,hour);
disp_sfm(2,7,minute);
disp_sfm(2,10,second);
wdata('
);
inc_minute_nop()
minute++;
if(minute==60)
minute=0;
voidinc_second()
second++;
if(second==60)
second=0;
inc_minute();
voidinc_minute()
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+'
ge=dat%10+'
wdata(shi);
wdata(ge);
voidled_apm()
if(hour<
12)
lpm=1;
lam=0;
goxy(2,0);
A'
M'
lam=1;
lpm=0;
P'
voidtzsjfun()
if(nlflag==0)//若闹铃没按下,则可设置时间,否则无效
if(wdnum==0)//若切换温度也没按下,则可设置时间
{if(setsj==0)
{
delay
(2);
while(!
setsj);
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);
if(ts==1)
tzflag=1;
}
if(tf==0)
tf);
if(tf==1)
tzflag=2;
}
if(tzflag)
if(tzflag==1)
tzflag=0;
inc_hour();
disp_sfm(2,4,hour);
if(tzflag==2)
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()
goxy(1,0);
9;
delay
(2);
voidtznlfun()
if(sj==0)//若设置时间没按下,则可设置闹铃,否则无效
{
if(wdnum==0)
{if(setnl==0)
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('
else
goxy(1,0);
delay(5);
if(ts==1)
tznl=1;
tznl=2;
if(tznl)
{
if(tznl==1)
tznl=0;
inc_nlhour();
disp_sfm(1,4,nlhour);
if(tznl==2)
inc_nlminute();
disp_sfm(1,7,nlminute);
voidkgnlfun()
if(knl==0)
while(!
knl);
delay(5);
i