1302数字时钟设计之欧阳育创编.docx
《1302数字时钟设计之欧阳育创编.docx》由会员分享,可在线阅读,更多相关《1302数字时钟设计之欧阳育创编.docx(24页珍藏版)》请在冰豆网上搜索。
1302数字时钟设计之欧阳育创编
基于DS1302的数字时钟的设计
时间:
2021.02.04
创作:
欧阳育
姓名:
学号:
专业:
电子信息科学与技术
指定老师:
一,实验目的
时表作为一种定时工具被广泛的使用在生产生活的各方面。
而电子钟又具有价格便宜,质量轻,定时误差小等优点,被广泛的应用在生产,生活的各个方面。
本次课程设计,我利用单片机和DS1302实现数字时钟。
并在设计过程中体验学习单片机设计的基本流程,提高对单片机的认识。
为毕业工作打下坚实的基础。
二,实验内容
以AT89S52为核心,结合DS1302和LCD1602,设计一个数字时钟。
在液晶上实现年,月,日,时,分,秒和星期的显示,并且日期和时间都可以通过按键选择进行调整。
给DS1302设置初始化的时间。
当选择CHG键时,可以跳转到年月日时分秒和星期处的位置,此时,通过INC键可以进行增加调整,DEC可以进行减小调整。
三,实验器件介绍
1,AT89S52
AT89S52是一种低功耗、高性能CMOS8位微控制器,具有8K在系统可编程Flash存储器。
使用Atmel公司高密度非易失性存储器技术制造,与工业80C51产品指令和引脚完全兼容。
片上Flash允许程序存储器在系统可编程,亦适于常规编程器。
在单芯片上,拥有灵巧的8位CPU和在系统可编程Flash,使得AT89S52在众多嵌入式控制应用系统中得到广泛应用。
AT89S52是一种低功耗、高性能CMOS8位微控制器,具有8K在系统可编程Flash存储器。
使用Atmel公司高密度非易失性存储器技术制造,与工业80C51产品指令和引脚完全兼容。
片上Flash允许程序存储器在系统可编程,亦适于常规编程器。
在单芯片上,拥有灵巧的8位CPU和在系统可编程Flash,使得AT89S52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
AT89S52具有以下标准功能:
8k字节Flash,256字节RAM,32位I/O口线,看门狗定时器,2个数据指针,三个16位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。
另外,AT89S52可降至0Hz静态逻辑操作,支持2种软件可选择节电模式。
空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。
掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。
AT89S52管脚图
2,DS1302
DS1302是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。
采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。
DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。
DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后备电源双电源引脚,同时提供了对后备电源进行涓细电流充电的能力。
DS1302的引脚排列,其中Vcc1为后备电源,VCC2为主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302由Vcc1或Vcc2两者中的较大者供电。
当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。
当Vcc2小于Vcc1时,DS1302由Vcc1供电。
X1和X2是振荡源,外接32.768kHz晶振。
RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。
RST输入有两种功能:
首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。
当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。
上电运行时,在Vcc>2.0V之前,RST必须保持低电平。
只有在SCLK为低电平时,才能将RST置为高电平。
I/O为串行数据输入输出端(双向),后面有详细说明。
SCLK为时钟输入端。
DS1302的管脚图
3,LCD1602
1602液晶也叫1602字符型液晶它是一种专门用来显示字母、数字、符号等的点阵型液晶模块它有若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符。
每位之间有一个点距的间隔每行之间也有间隔起到了字符间距和行间距的作用,正因为如此所以他不能显示图形。
四,实验的硬件设计
这次数字时钟设计主要由四个模块组成,分别是数据处理模块,DS1302模块,键盘输入模块和液晶显示模块。
通过DS1302提供时间数据,单片机处理数据并且通过液晶显示时间。
修改时间时,通过键盘来选择修改位置和执行增加或者减小的数量。
原理图:
五,实验的软件设计
在系统设计中,除了硬件设计之外,软件设计也是很重要的,它是系统工作的指挥者,因此系统软件设计时要遵循结构合理、操作性能好、具有一定的保护措施、兼容性好的设计原则来开发设计。
数字时钟软件设计主要包括主程序模块、LCD1602模块、DS1302模块,键盘扫描模块和修改时间模块。
系统的流程图:
实物图:
1,整体结构图
2,正常的日期显示结果
3,关掉电源再打开,时间不会失去
4,修改时间的演示图
程序清单:
#include
#include
#include
sbita0=ACC^0;
sbita1=ACC^1;
sbita2=ACC^2;
sbita3=ACC^3;
sbita4=ACC^4;
sbita5=ACC^5;
sbita6=ACC^6;
sbita7=ACC^7;
sbitspeaker=P3^6;//蜂鸣器
sbitINC=P1^5;//增加键
sbitDEC=P1^6;//减少键
sbitCHG=P1^7;//修改键
sbitRS=P2^0;//指令OR数据寄存器选择
sbitRW=P2^1;//读写控制
sbitEN=P2^2;//使能控制
sbitSCLK=P1^0;//1302时钟线
sbitIO=P1^1;//1302数据线
sbitRST=P1^2;//1302复位线
#defineLCLR0x01//清屏
#defineMODE0x38//8位数据,双列显示,5*7字形
#defineDATAP0//8位数据并行口
#defineON0x0c//开显示,关光标,光标不闪烁
#defineADDR_MODE0x06
volatileunsignedchardatatimedata[7];//时间值
unsignedchardisplay_buffer1[16];//显示缓冲区1
unsignedchardisplay_buffer2[16];//显示缓冲区2
volatileunsignedintself_pos=0;//自定义三角形标志显示位置变量
volatiledataWZ=0;//修改的位置值
volatiledataZENG=0;//增加的值
volatiledataJIAN=0;//减小的值
unsignedcharcodeself_table1[]={
0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,//年
0x1f,0x11,0x1f,0x11,0x1f,0x11,0x15,0x17,//月
0x00,0x1f,0x11,0x1f,0x11,0x11,0x1f,0x00,//日
};
voiddelay_ms(unsignedcharcount)//延时时间
{unsignedchari;
for(;count>0;count--)
{
for(i=0;i<110;i++)
{
_nop_();
}
}
}
voidspeakers(unsignedcharspeak_count)//蜂鸣器
{
for(;speak_count>0;speak_count--)
{
speaker=0;
delay_ms
(1);
speaker=1;
delay_ms(3);
}
}
/***********************************************************
忙检测
************************************************************/
voidLCD1602_check_busy(void)
{
DATA=0xff;
RS=0;
RW=1;
EN=1;
while(DATA&0x80);
EN=0;
}
/**********************************************************
写指令
************************************************************/
voidLCD1602_write_cmd(unsignedcharcmd)
{
LCD1602_check_busy();
RS=0;
RW=0;
DATA=cmd;
EN=1;
EN=0;
}
/***********************************************************
写数据
*************************************************************/
voidLCD1602_write_data(unsignedchardat)
{
LCD1602_check_busy();
RS=1;
RW=0;
DATA=dat;
EN=1;
EN=0;
}
voidLCD1602_init(void)
{
unsignedchari;
LCD1602_write_cmd(0x40);//CGRAM起始地址
for(i=0;i<40;i++)
LCD1602_write_data(self_table1[i]);//写入自定义字符
LCD1602_write_cmd(MODE);
LCD1602_write_cmd(ON);
LCD1602_write_cmd(ADDR_MODE);
LCD1602_write_cmd(LCLR);
}
voidLCD1602_set_postion(unsignedcharx,unsignedchary)
{
if(y<2)
{
y&=0x01;//y值限定在0~1之间
x&=0x0f;//x值限定在0~15之间
if(y==0)
x|=0x40;//如果显示是在第二行,则x的值加0x40
x|=0x80;//获得x的值
LCD1602_write_cmd(x);//写入坐标值到LCD
}
}
voidLCD1602_write_char(unsignedcharx,unsignedchary,unsignedcharchardata)
{
LCD1602_set_postion(x,y);
LCD1602_write_data(chardata);
}
voidLCD1602_write_string(unsignedcharx,unsignedchary,unsignedchar*string)
{
LCD1602_set_postion(x,y);
while((*string)!
='\0')
{
LCD1602_write_data(*string);
string++;
}
}
voidinput(unsignedcharinputdata)//输入函数
{
ACC=inputdata;
IO=a0;SCLK=1;SCLK=0;
IO=a1;SCLK=1;SCLK=0;
IO=a2;SCLK=1;SCLK=0;
IO=a3;SCLK=1;SCLK=0;
IO=a4;SCLK=1;SCLK=0;
IO=a5;SCLK=1;SCLK=0;
IO=a6;SCLK=1;SCLK=0;
IO=a7;SCLK=1;SCLK=0;
}
unsignedcharoutput(void)//输出函数
{
IO=1;
a0=IO;
SCLK=1;SCLK=0;a1=IO;
SCLK=1;SCLK=0;a2=IO;
SCLK=1;SCLK=0;a3=IO;
SCLK=1;SCLK=0;a4=IO;
SCLK=1;SCLK=0;a5=IO;
SCLK=1;SCLK=0;a6=IO;
SCLK=1;SCLK=0;a7=IO;
return(ACC);
}
voidDS1302_write_byte(unsignedcharcmd,unsignedchardat)//指定位置写数据
{
SCLK=0;
RST=0;
RST=1;
input(cmd);
input(dat);
RST=0;
SCLK=1;
}
unsignedcharDS1302_read_byte(unsignedcharcmd)//指定位置读取数据
{
unsignedcharreceivedata=0;
SCLK=0;
RST=0;
RST=1;
input(cmd);
receivedata=output();
RST=0;
SCLK=1;
return(receivedata);
}
voidDS1302_init()//设置1302的时间
{
if(DS1302_read_byte(0xc9)!
=0xf0)
{
DS1302_write_byte(0x8e,0x00);//允许写操作
DS1302_write_byte(0xc8,0xf0);//写入初始化标志,系统上电后检测此标志,即此子函数只会在第一次初始化一次。
DS1302_write_byte(0x8c,0x08);//年
DS1302_write_byte(0x8a,0x05);//星期
DS1302_write_byte(0x88,0x09);//月
DS1302_write_byte(0x86,0x19);//日
DS1302_write_byte(0x84,0x12);//时
DS1302_write_byte(0x82,0x00);//分
DS1302_write_byte(0x80,0x00);//秒
DS1302_write_byte(0x90,0xa5);//充电
DS1302_write_byte(0x8e,0x80);//禁止写操作
}
}
voidreadDS1302()//读取时间到timedata
{
timedata[0]=DS1302_read_byte(0x8d);//年
timedata[1]=DS1302_read_byte(0x89);//月
timedata[2]=DS1302_read_byte(0x87);//日
timedata[3]=DS1302_read_byte(0x85);//时
timedata[4]=DS1302_read_byte(0x83);//分
timedata[5]=DS1302_read_byte(0x81);//秒
timedata[6]=DS1302_read_byte(0x8b);//星期
}
voidupdata_buffer(void)//更新缓冲区的时间
{unsignedchari;
display_buffer1[0]='2';
display_buffer1[1]='0';
display_buffer1[2]=timedata[0]/16+0x30;
display_buffer1[3]=timedata[0]%16+0x30;
display_buffer1[4]=0;
display_buffer1[5]=timedata[1]/16+0x30;
display_buffer1[6]=timedata[1]%16+0x30;
display_buffer1[7]=1;
display_buffer1[8]=timedata[2]/16+0x30;
display_buffer1[9]=timedata[2]%16+0x30;
display_buffer1[10]=2;
display_buffer1[11]='';
switch(timedata[6]%16)
{
case1:
{display_buffer1[12]='M';
display_buffer1[13]='o';
display_buffer1[14]='n';}break;
case2:
{display_buffer1[12]='T';
display_buffer1[13]='u';
display_buffer1[14]='e';}break;
case3:
{display_buffer1[12]='W';
display_buffer1[13]='e';
display_buffer1[14]='d';}break;
case4:
{display_buffer1[12]='T';
display_buffer1[13]='h';
display_buffer1[14]='u';}break;
case5:
{display_buffer1[12]='F';
display_buffer1[13]='r';
display_buffer1[14]='i';}break;
case6:
{display_buffer1[12]='S';
display_buffer1[13]='a';
display_buffer1[14]='t';}break;
case7:
{display_buffer1[12]='S';
display_buffer1[13]='u';
display_buffer1[14]='n';}break;
default:
break;
}
display_buffer1[15]='';
display_buffer2[0]=timedata[3]/16+0x30;
display_buffer2[1]=timedata[3]%16+0x30;
display_buffer2[2]=':
';
display_buffer2[3]=timedata[4]/16+0x30;
display_buffer2[4]=timedata[4]%16+0x30;
display_buffer2[5]=':
';
display_buffer2[6]=timedata[5]/16+0x30;
display_buffer2[7]=timedata[5]%16+0x30;
for(i=0;i<8;i++)
display_buffer2[8+i]='';
}
voiddisplay_buffer(void)
{
unsignedchari;
LCD1602_write_cmd(0x80);
for(i=0;i<16;i++)
LCD1602_write_data(display_buffer1[i]);
LCD1602_write_cmd(0xc0);
for(i=0;i<16;i++)
LCD1602_write_data(display_buffer2[i]);
}
voidkey_sm(void)
{
if(CHG==0){
delay_ms(20);
if(CHG==0){
speakers(5);
WZ++;
if(WZ==8)WZ=1;
while(!
CHG);
}
}
if(DEC==0)
{
delay_ms(20);
while(!
DEC);
speakers(5);
ZENG++;
}
if(INC==0)
{
delay_ms(20);
while(!
INC);
speakers(5);
JIAN++;
}
}
voidchange(void)
{
unsignedchari,j;
if
(1)
{
LCD1602_write_cmd(0x0f);//开光标
LCD1602_write_cmd(0x80);//地址码
for(i=0;i<15;i++)
LCD1602_write_data(display_buffer1[i]);
LCD1602_write_cmd(0xc0);
for(j=0;j<8;j++)
LCD1602_write_data(display_buffer2[j]);
if(WZ==1)
{
unsignedcharitem;
LCD1602_write_cmd(0x83);
if(ZENG!
=0)
{
item=DS1302_read_byte(0x8d);
item=(item/16)*10+item%16;
item++;
if(item==100)item=0;
item=(item/10)*16+item%10;
DS1302_write_byte(0x8e,0x00);//允许写操作
DS1302_write_byte(0x8c,item);
ZENG=0;
}
if(JIAN!
=0)
{
item=DS1302_read_byte(0x8d);
item=(item/16)*10+item%16;
item--;
if(item<0)item=99;
item=(item/10)*16+item%10;
DS1302_write_byte(0x8e,0x00);//允许写操作
DS1302_writ