资源描述
物理与电子科学学院
电子电工实验
基于DS1302多功能
数字时钟--万年历
实验报告
实验名称: 基于DS1302多功能数字钟
试验日期: 2014年 01 月 05 日
专 业: 电子信息工程
姓 名: 刘 斌
班 级: 物电 1105 班
学 号: 2011112030560
一、 设计理念:
电子万年历是一个应用非常广泛的实用日常计时工具,带有显示温度,显示世纪,年,月,日,星期,时,分,秒和按键可调时间及其按键设置闹钟的功能,同时具有月末自动更新,闰年补偿功能,整点报时等多种功能。环境温度检测系统在日常生活和工业应用非常广泛,能实时采集周围的温度信息进行显示。
此系统是基于STC89C52单片机设计的,包含液晶显示模块,DS1302实时时钟模块,DS18B20温度采集模块,键盘扫描模块,蜂鸣器报警模块。STC89C52作为控制核心,具有功耗低,功能强等特点,电压可选3到5V电源供电。显示模块采用1602液晶动态显示,相对数码管而言经济实用,占用空间小,对于显示数字、字母最为合适,而且与单片机连线简单,占用IO口相对较少。实时时钟芯片DS1302是一款经济实惠功能强大的较新型产品,该器件提供RTC/日历,可外加器件实现定时闹钟等功能,如果检测到主电源故障,该器件可自动切换到备用电源供电,可以保证在断电情况下精准走时,计时。温度检测显示模块采用数字式温度传感器DS18B20,该芯片具有精度高,测量范围广等优点,易与单片机连接,模块电路组成简单并同时具有温度报警功能。
关键词:STC89C52,DS1302,DS18B20,1602液晶显示,电子万年历,采集设备周围环境温度、整点报时,闹钟时分通过按键设置,时、分、秒、年、月、日、星期通过按键进行调节校准……
二、 设计思路:
核心控制体:STC89C52单片机
实时时钟芯片:DS1302
数字式温度传感器:DS18B20
总共设有四个按键,为节约资源考虑,每个按键都有多种功能。四个按键分别标号为key1,key2,key3,key4。第一次按下key2,key3,key4都没有反应,首先按下key1键可选择指针位置,key2键为加键,key3为减键,key4键为闹钟设置清零键。操作简单,按键灵活。整点报时功能,可以按下key4键终止报警。
主
控
模
块
时钟模块
温度检测显示
1602显示模块
键盘扫描模块
闹钟模块
系统设计框图:
系统硬件需求介绍:
STC89C52单片机一片,DS1302实时时钟芯片一个,DS18B20数字式温度传感器一个,+5V无源蜂鸣器一个,12MHZ、32KHZ晶振各一个,多个按键和开关,常用电容电阻,连接线,三极管,二极管若干,滑动变阻器一个,+3V纽扣电池一个。
三、 实施方案:
1、单片机核心控制模块:
核心控制器件选用STC89C52单片机。STC89C52单片机为40管脚双列直插芯片,它是一种高性能,低功耗的8位CMOS微处理器芯片,市场应用最多。而且价格便宜,控制方便,便于应用有4个I/O口分别为P1,P2,P3,P4。其中每一个管脚都能做独立的输入输出管脚,它的第9脚位复位管脚,接上电容和上拉电阻再带个开关构成复位电路。18,19管脚接外部晶振和两个微调电容构成外部晶振电路。单片机,复位电路,晶振,5V电源构成单片机最小系统。其中与AT89C52单片机管脚连接如下图:
2、实时时钟电路模块:
DS1302引脚排列:如下图
引脚说明:
1)1脚,Vcc2:后备电源,此设计中接+3V纽扣电池;8脚,VCC1:主电源,接+5V。在主电源关闭的情况下,也能保持时钟的连续运行。DS1302由Vcc1或Vcc2两者中的较大者供电。当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。当Vcc2小于Vcc1时,DS1302由Vcc1供电。
2)X1、X2即2脚3脚:振荡源,外接32.768kHz晶振。
3)4脚END,接地端。
4)5脚RST:复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。上电运行时,在Vcc>2.0V之前,RST必须保持低电平。只有在SCLK为低电平时,才能将RST置为高电平。
5)I/O为串行数据输入输出端(双向)。
6)SCLK为时钟输入端。
**特别注意:5,6,7脚在硬件电路实现中,必须接上拉电阻,接+5V.
3、DS18B20 工作模块:
DS18B20 的温度检测与数字数据输出全集成于一个芯片之上,从而抗干扰力更强。其一个工作周期可分为两个部分,即温度检测和数据处理。
DS18B20 的主要特征:
全数字温度转换及输出。
先进的单总线数据通信。
最高 12 位分辨率,精度可达土 0.5摄氏度。
12 位分辨率时的最大工作周期为 750 毫秒。
可选择寄生工作方式。
检测温度范围为–55°C ~+125°C (–67°F ~+257°F)
内置 EEPROM,限温报警功能。
64 位光刻 ROM,内置产品序列号,方便多机挂接。
多样封装形式,适应不同硬件系统。
4、液晶显示模块:
1602字符型液晶显示模块是一种专门用于显示字母、数字、符号等点阵式LCD,本设计采用16列*2行的字符型LCD1602带背光的液晶显示屏。
引脚接口说明:
第1脚:VSS为地电源。
第2脚:VDD接5V正电源。
第3脚:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。
第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。
第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。
第7~14脚:D0~D7为8位双向数据线。
第15脚:背光源正极。
第16脚:背光源负极。
5、蜂鸣器电路模块
本实验设计中蜂鸣器用CS8050三极管驱动,蜂鸣器用5V的无源蜂鸣器,并接一个发光二极管作为指示灯,同时在负极串接一个限流电阻,数据端口接P3^7.
四、 Proteus仿真原理总框图:
五、 硬件电路实现:
六、 源程序:
Shuzizhong.c
#include <reg51.h>
#include"ds18b20.h"
#define uchar unsigned char
#define uint unsigned int
uchar shi,fen,miao,ringshi,ringfen,nian,yue,ri,week,temp,count,m;
sbit rs=P2^2;
sbit rw=P2^3;
sbit en=P2^4;
sbit key1=P3^4; //设置键
sbit key2=P3^5; //加键
sbit key3=P3^6;
sbit key4=P3^7;
sbit IO=P1^1; // DS1302数据线
sbit SCLK=P1^2; //DS1302时钟线
sbit RST=P1^0; //DS1302复位线
sbit beep=P1^4;
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
uchar codetable[]="20 - - ";
uchar codetable1[]=" : : ";
uchar codetone[]={212,212,190,212,159,169,212,212,190,212,142,159,
212,212,106,126,159,169,190,119,119,126,159,142,159,0};
uchar codelon[]={9,3,12,12,12,24,9,3,12,12,12,24,
9,3,12,12,12,12,12,9,3,12,12,12,24,0};
void delay(uint z)
{uint x,y;
for(x=z;x>0;x--)
for(y=120;y>0;y--);
}
void yinyue()
{
uint i,j,k=0,l;
{for(l=0;l<26;l++)
{
for(i=0;i<codelon[k]*20;i++)
{ if(key4==0){beep=0;break;}
beep=~beep;
for(j=0;j<codetone[k]/3;j++);
}
delay(10);
k++;}}}
void write_LCD_com(uchar com)
{rs=0;
rw=0;
P0=com;
delay(5);
en=1;
delay(5);
en=0;
}
void write_LCD_da(uchar data1)
{rs=1;
rw=0;
P0=data1;
delay(5);
en=1;
delay(5);
en=0;
}
void Init_LCD()
{uchar num;
write_LCD_com(0x38); delay(1);
write_LCD_com(0x01); delay(1);
write_LCD_com(0x06); delay(1);
write_LCD_com(0x0c); delay(1);
write_LCD_com(0x80);
for(num=0;num<10;num++)
{write_LCD_da(codetable[num]);
delay(1);}
write_LCD_com(0x80+0x40);
for(num=0;num<8;num++)
{write_LCD_da(codetable1[num]);
delay(1);}}
void write_LCDsfm(uchar add,uchar date)
{uchar ge,shi;
shi=date/10;
ge=date%10;
write_LCD_com(0x80+0x40+add);
write_LCD_da(0x30+shi);
write_LCD_da(0x30+ge); }
void write_LCDnyr(uchar add,uchar date)
{uchar ge,shi;
shi=date/10;
ge=date%10;
write_LCD_com(0x80+add);
write_LCD_da(0x30+shi);
write_LCD_da(0x30+ge);
}
void write_LCDweek(uchar week)
{ write_LCD_com(0x80+0x0b);
switch(week)
{ case 1:write_LCD_da('M');
write_LCD_da('O');
write_LCD_da('N');
break;
case 2:write_LCD_da('T');
write_LCD_da('U');
write_LCD_da('E');
break;
case 3:write_LCD_da('W');
write_LCD_da('E');
write_LCD_da('D');
break;
case 4:write_LCD_da('T');
write_LCD_da('H');
write_LCD_da('U');
break;
case 5:write_LCD_da('F');
write_LCD_da('R');
write_LCD_da('I');
break;
case 6:write_LCD_da('S');
write_LCD_da('T');
write_LCD_da('A');
break;
case 7:write_LCD_da('S');
write_LCD_da('U');
write_LCD_da('N');
break;}}
void write_LCD_Temperature(uchar add,uchar date)
{uchar ge,shi;
shi=date/10;
ge=date%10;
write_LCD_com(0x80+0x40+add);
write_LCD_da(0x30+shi);
write_LCD_da(0x30+ge);
write_LCD_da(0xdf);
write_LCD_da(0x43);
}
void DS1302_write_byte(uchar a)
{ uchar i;
ACC=a;
RST=1;
for(i=8;i>0;i--)
{ IO=ACC0;
SCLK=0;
SCLK=1;
ACC=ACC>>1;
}}
uchar DS1302_read_byte()
{uchar j;
RST=1;
for(j=8;j>0;j--)
{ ACC7=IO;
SCLK=1;
SCLK=0;
ACC=ACC>>1;
}
return(ACC);
}
void DS1302_write_date(uchar addr,uchar dat)//写数据
{RST=0;
SCLK=0;
RST=1;
DS1302_write_byte(addr);
DS1302_write_byte(dat);
SCLK=1;
RST=0;
}
uchar DS1302_read_date(uchar addr)
{uchar dat1,b;
RST=0;
SCLK=0;
RST=1;
DS1302_write_byte(addr);
dat1=DS1302_read_byte();
SCLK=1;
RST=0;
b=dat1/16*10+dat1%16;
return(b);
}
void DS1302_Init()
{SCLK=0;
RST=0;
DS1302_write_date(0x8e,0x00);
DS1302_write_date(0x8e,0x80);
}
void keyscan()
{
if(key1==0)
{
if(key1==0)
{
while(!key1);
count++;
if(count==11) count=1;
switch(count)
{ case 1:TR0=0;
write_LCD_com(0x80+0x40+0x0f);
write_LCD_da('M');
m=miao/10*16+miao%10;
DS1302_write_date(0x8e,0x00);
DS1302_write_date(0x80,0x80|m);
DS1302_write_date(0x8e,0x80);
break;
case 2:write_LCD_com(0x80+0x40+0x0f);
write_LCD_da('F');
break;
case 3:write_LCD_com(0x80+0x40+0x0f);
write_LCD_da('S');
break;
case 4:write_LCD_com(0x80+0x40+0x0f);
write_LCD_da('W');
break;
case 5:write_LCD_com(0x80+0x40+0x0f);
write_LCD_da('R');
break;
case 6:write_LCD_com(0x80+0x40+0x0f);
write_LCD_da('Y');
break;
case 7:write_LCD_com(0x80+0x40+0x0f);
write_LCD_da('N');
break;
case 8:write_LCD_com(0x80+0x40+0x0e);
write_LCD_da('R'); delay(3);
write_LCD_com(0x80+0x40+0x0f);
write_LCD_da('F'); delay(3);
write_LCD_com(0x80+0x40+0x04);
break;
case 9:write_LCD_com(0x80+0x40+0x0e);
write_LCD_da('R'); delay(3);
write_LCD_com(0x80+0x40+0x0f);
write_LCD_da('S'); delay(3);
write_LCD_com(0x80+0x40+0x01);
break;
case 10:write_LCD_com(0x80+0x40+0x0e);
write_LCD_da('\0'); delay(3);
write_LCD_com(0x80+0x40+0x0f);
write_LCD_da('\0'); delay(3);
delay(3);
write_LCD_com(0x0c);
TR0=1;
m=(miao)/10*16+(miao)%10;
DS1302_write_date(0x8e,0x00);
DS1302_write_date(0x80,0x00|m);
DS1302_write_date(0x8e,0x80);
break;
}}}if(count!=0)
{
if(key2==0)
{delay(10);
if(key2==0)
{while(!key2);
switch (count)
{case 1:miao++;
if(miao==60)
miao=0;
write_LCDsfm(0x06,miao);
m=miao/10*16+miao%10;
DS1302_write_date(0x8e,0x00);
DS1302_write_date(0x80,m);
DS1302_write_date(0x8e,0x80);
write_LCD_com(0x80+0x40+0x07);
break;
case 2:fen++;
if(fen==60)
fen=0;
write_LCDsfm(0x03,fen);
m=fen/10*16+fen%10;
DS1302_write_date(0x8e,0x00);
DS1302_write_date(0x82,m);
DS1302_write_date(0x8e,0x80);
write_LCD_com(0x80+0x40+0x04);
break;
case 3:shi++;
if(shi==24)
shi=0;
write_LCDsfm(0x00,shi);
m=shi/10*16+shi%10;
DS1302_write_date(0x8e,0x00);
DS1302_write_date(0x84,m);
DS1302_write_date(0x8e,0x80);
write_LCD_com(0x80+0x40+0x01);
break;
case 4:week++;
if(week==8)
week=0;
write_LCDweek(week);
m=week/10*16+week%10;
DS1302_write_date(0x8e,0x00);
DS1302_write_date(0x8a,m);
DS1302_write_date(0x8e,0x80);
write_LCD_com(0x80+0x0d);
break;
case 5:ri++;
if(ri==32)
ri=0;
write_LCDnyr(0x08,ri);
m=ri/10*16+ri%10;
DS1302_write_date(0x8e,0x00);
DS1302_write_date(0x86,m);
DS1302_write_date(0x8e,0x80);
write_LCD_com(0x80+0x09);
break;
case 6:yue++;
if(yue==13)
yue=1;
write_LCDnyr(0x05,yue);
m=yue/10*16+yue%10;
DS1302_write_date(0x8e,0x00);
DS1302_write_date(0x88,m);
DS1302_write_date(0x8e,0x80);
write_LCD_com(0x80+0x06);
break;
case 7:nian++;
if(nian==51)
nian=0;
write_LCDnyr(0x02,nian);
m=nian/10*16+nian%10;
DS1302_write_date(0x8e,0x00);
DS1302_write_date(0x8c,m);
DS1302_write_date(0x8e,0x80);
write_LCD_com(0x80+0x03);
break;
case 8:ringfen++;
if(ringfen==60)
ringfen=0;
write_LCDsfm(0x03,ringfen);
write_LCD_com(0x80+0x40+0x04);
break;
case 9:ringshi++;
if(ringshi==24)
ringshi=0;
write_LCDsfm(0x00,ringshi);
write_LCD_com(0x80+0x40+0x01);
break; }}}
if(key3==0)
{delay(10);
if(key3==0)
{while(!key3);
switch (count)
{case 1:miao--;
if(miao==-1)
miao=59;
write_LCDsfm(0x06,miao);
m=miao/10*16+miao%10;
DS1302_write_date(0x8e,0x00);
DS1302_write_date(0x80,m);
DS1302_write_date(0x8e,0x80);
write_LCD_com(0x80+0x40+0x07);
break;
case 2:fen--;
if(fen==-1)
fen=59;
write_LCDsfm(0x03,fen);
m=fen/10*16+fen%10;
DS1302_write_date(0x8e,0x00);
DS1302_write_date(0x82,m);
DS1302_write_date(0x8e,0x80);
write_LCD_com(0x80+0x40+0x04);
break;
case 3:shi--;
if(shi==-1)
shi=23;
write_LCDsfm(0x00,shi);
m=shi/10*16+shi%10;
DS1302_write_date(0x8e,0x00);
DS1302_write_date(0x84,m);
DS1302_write_date(0x8e,0x80);
write_LCD_com(0x80+0x40+0x01);
break;
case 4:week--;
if(week==0)
week=7;
write_LCDweek(week);
m=week/10*16+week%10;
DS1302_write_date(0x8e,0x00);
DS1302_write_date(0x8a,m);
DS1302_write_date(0x8e,0x80);
write_LCD_com(0x80+0x0d);
break;
case 5:ri--;
if(ri==0)
ri=31;
write_LCDnyr(0x08,ri);
m=ri/10*16+ri%10;
DS1302_write_date(0x8e,0x00);
DS1302_write_date(0x86,m);
DS1302_write_date(0x8e,0x80);
write_LCD_com(0x80+0x09);
break;
case 6:yue--;
if(yue==0)
yue=12;
write_LCDnyr(0x05,yue);
m=yue/10*16+yue%10;
DS1302_write_date(0x8e,0x00);
DS1302_write_date(0x88,m);
DS1302_write_date(0x8e,0x80);
write_LCD_com(0x80+0x06);
break;
case 7:nian--;
if(nian==-1)
nian=50;
write_LCDnyr(0x02,nian);
m=nian/10*16+nian%10;
DS1302_write_date(0x8e,0x00);
DS1302_write_date(0x8c,m);
DS1302_write_date(0x8e,0x80);
write_LCD_com(0x80+0x03);
break;
case 8:ringfen--;
if(ringfen==-1)
ringfen=59;
write_LCDsfm(0x03,ringfen);
write_LCD_com(0x80+0x40+0x04);
break;
case 9:ringshi--;
if(ringshi==-1)
ringshi=23;
write_LCDsfm(0x00,ringshi);
write_LCD_com(0x80+0x40+0x01);
break;}}}}}
void set_dingshiqi()
{TMOD=0x01;
TH0=64536/256;
TL0=64536%256;
EA=1;
ET0=1;
TR0=1;
}
void gettime()
{ beep=0;
temp=Read_Temperature();
miao=DS1302_read_date(0x81);
fen=DS1302_read_date(0x83);
shi=DS1302_read_date(0x85);
week=DS1302_read_date(0x8b);
ri=DS1302_read_date(0x87);
yue=DS1302_read_date(0x89);
nian=DS1302_read_date(0x8d);
write_LCDsfm(0x00,shi);
write_LCDsfm(0x03,fen);
write_LCDsfm(0x06,miao);
if(miao==0&&fen==0&&shi>8&&shi<21)
{yinyue();
}
if(fen==ringfen&&shi==ringshi)
{yinyue();if(key4==0){ringshi=0;ringfen=0;}
}
write_LCDweek(week);
write_LCDnyr(0x08,ri);
write_LCDnyr(0x05,yue);
write_LCDnyr(0x02,nian);
write_LCD_Temperature(0x09,temp);
}
void main()
{ Init_LCD();
DS1302_Init();
set_dingshiqi();
while(1)
{ keyscan();}
}
void timer0() interrupt 1
{ TH0=64536/256;
TL0=64536%256;
gettime();
keyscan( );}
Ds18b20.h
sbit DQ=P1^7;
//unsigned char wendu;
//unsigned char tempbuf[3];
void delay0(unsigned char z)
{ while(z--); }
void init_ds18b20()
{
unsigned char x=0;
DQ=1; //DQ复位
delay0(8);
DQ=0; //单片机将DQ拉低
delay0(80); //延时480us~960us
DQ=1; //拉高总线
delay0(14); //等待15us~60u。
x=DQ;
delay0(80); //低电平至少要持续60~240us
}
void write_onechar(unsigned char dat)
{
unsigned char i=0;
for(i=0;i<8;i++)
{
DQ=0;
DQ=dat&0x01;
delay0(15);
DQ=1;
dat=dat>>=1;
}
delay0(5);
}
unsigned char read_onechar()
{
unsigned char i=0;unsigned char dat=0;
for(i=0;i<8;i++)
{
DQ=0;
dat>>=1;
DQ=1;
if(DQ) dat
展开阅读全文