时间日历显示单片机实验
- 格式:doc
- 大小:107.50 KB
- 文档页数:15
机电0902 李刚 学号38
时间日程显示设计程序实验
一 设计目标:万年历实现以下三个功能:
(1)具有年、月、日、星期、时、分、秒等功能;
(2)具备年、月、日、星期、时、分、秒校准功能,具备自动调节闰年的功能;
(3)具有与即时时间同步的功能。
本电路是以STC89C51单片机为控制核心, 时钟芯片采用DS1302, 具有掉电自动保存功能。可自动对秒、分、时、日、周、月、年进行计数, 显示模块采用1602显示屏,它内置192种字符,可显示32个符号或数字,清晰可见,而且功率消耗小寿命长抗干扰能力强。其工作电压为5v。
一个典型的单片机最小系统一般由时钟电路、复位电路、电源指示灯和外部扩展接口等部分组成。
1时钟电路模块的设计
DS1302内含有一个实时时钟/日历和31字节静态RAM,通过简单的串行接口与单片机进行通信。图中VCC1为后备电源,VCC2为主电源。DS1302由VCC1或VCC2两者中的较大者供电。所以在主电源关闭的情况下,也能保持时钟的连续运行。X1和X2是振荡源,外接32.768KHz晶振用来为芯片提供计时脉冲。RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。DS1302
的硬件接线图如图2所示:
VCC2X1X2GNDRSTI/OSLCKVCC1U1DS1302VCC12Y1C12012P1Header 2C220P1.2P1.1P1.032.768KHZ 图2
时钟芯片DS1302的工作原理:
(1) DS1302的控制字节:DS1302控制字节的高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出
(2) 数据输入输出(I/O):在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
(3) DS1302的寄存器:DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式。“CH”是时钟暂停标志位,当该位为1时,时钟振荡器停止,DS1302处于低功耗状态;当该位为0时,时钟开始运行。“WP”是写保护位,在任何的对时钟和RAM的写操作之前,“WP”必须为0。当“WP”为1时,写保护位防止对任一寄存器的写操作。
2 独立式键盘设计
独立式键盘每个键单独占用一根I/O口线。键盘的工作方式可分为编程控制方式和中断控制方式。CPU在一个工作周期内,利用完成其他任务的空余时间,调用键盘扫描子程序,经程序查询,若无键操作,则返回;若有键操作,则进而判断是哪个键,并执行相应的键处理程序。这种方式为编程扫描方式。由于单片机在正常应用过程中,可能会经常进行键操作,因而编程控制方式使CPU经常处于工作状态, 在进行本次设计中,只涉及到了选择、加、减、确定四个功能。因此采用独立式键盘。
3 显示模块的设计
本设计中 对时间、温度进行显示,液晶显示屏1602模块作为输出。1602字符型LCD通常有14条引脚线或16条引脚线的LCD,多出来的2条线是背光电源线。它可以显示两行,每行16个字符,采用单+5V电源供电,外围电路配置简单。1602液晶模块内部的字符发生存储器已经存储了160个不同的点阵字符图形,每一个 字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。LCD1602引脚功能:
1 VSS 一般接地
2 VDD 接电源(+5V)
3 V0 液晶显示器对比度调整端。
4 RS RS为寄存器选择。
5 R/W R/W为读写信号线。
6 E E(或EN)端为使能(enable)端,下降沿使能。
1602主要管脚介绍:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高,对比度过高时会产生鬼影使用时可以通过一个10K的电位器调整对比度。RS为寄存器选择端,高电平时选择数据寄存器,低电平时选择指令寄存器。R/W为读写信号线端,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址;当RS为高电平R/W 为低电平时可以写入数据。E为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。将L1602的RS端和P2.0,R/W端和P2.1, E 端和P2.2相连,当RS=0时,对LCD1602写入指令;当RS=1时,对LCD1602写入数据。当R/W端接高电平时芯片处于读数据状态,反之处于写数据状态,E端为使能信号端。当R/W为高电平,E端也为高电平,RS为低电平时,液晶显示屏显示需要显示的示数。显示模块电路图如图3所示: VSS1VDD2V03RS4RW5E6DB07DB18DB29DB310DB411DB512DB613DB714E115E216J1LCD1602P1.0(T2)1P1.1(T2EX)2P1.23P1.34P1.45P1.56P1.67P1.78P0.039P0.138P0.237P0.336P0.435P0.534P0.633P0.732P2.021P2.122P2.223P2.324P2.425P2.526P2.627P2.728P3.3(INT1)13P3.2(INT0)12P3.5(T1)15P3.4(T0)14EA/VPP31XTAL119XTAL018RESET9P3.7(RD)17P3.6(WR)16VSS20VCC40(RXD)P3.010(TXD)P3.111ALE/PROG30PSEN29U1ST8C9C52VCCVCC10KVCC
功能仿真
图10 电路图
图11 键盘调节
图12 调节键盘后
主程序
// 名称:用DS1302与1602LCD设计的可调式电子日历与时钟
// 说明:本例会自动调节合法日期时间,对于星期的调节会在
// 调整年月日时自动完成,闰年问题也会自动判断。
//-------------------------------------------------------
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit SDA=P1^0; //DS1302数据线
sbit CLK=P1^1; //DSB1302时钟线
sbit RST=P1^2; //DS1302复位线
sbit RS=P2^0; //LCD寄存器选择
sbit RW=P2^1; //LCD读/写控制
sbit EN=P2^2; //LCD启用
sbit K1=P3^4; //选择 sbit K2=P3^5; //加
sbit K3=P3^6; //减
sbit K4=P3^7; //确定
uchar tCount=0;
//一年中每个月的天数,二月的天数由年份决定
uchar MonthsDays[]={0,31,0,31,30,31,30,31,31,30,31,30,31};
//周日,周一到周六{0,1-6} [读取DS1302时分别是1-7]
uchar *WEEK[]={"SUN","MON","TUS","WEN","THU","FRI","SAT"};
//LCD显示缓冲
uchar LCD_DSY_BUFFER1[]={"DATE 00-00-00 "};
uchar LCD_DSY_BUFFER2[]={"TIME 00:00:00 "};
uchar DateTime[7]; //所读取的日期时间
char Adjust_Index=-1; //当前调节的时间对象:秒,分,时,日,月,年(0,1,2,3,4,6)
uchar Change_Flag[]="-MHDM-Y"; //(分,时,日,月,年)(不调节秒周)
//延时,向DS1302写、读一字节以及从DS1302指定位置度、写数据的程序
//延时----------------------------------------------------
void DelayMS(uint x)
{
uchar i;
while(x--) for(i=0;i<120;i++);
}
//向DS1302写入一个字节
void Write_A_Byte_TO_DS1302(uchar x)
{
uchar i;
for(i=0;i<8;i++)
{
SDA=x&1; CLK=1; CLK=0; x>>=1;
} }
//从DA1302读取一字节----------------------------------------
uchar Get_A_Byte_FROM_DS1302()
{
uchar i,b,t;
for(i=0;i<8;i++)
{
b>>=1;t=SDA;b|=t<<7;CLK=1;CLK=0;
}
//BCD码转换
return b/16*10+b%16;
}
//从DS1302指定的位置读数据---------------------------------------
uchar Read_Data(uchar addr)
{
uchar dat;
RST=0;CLK=0;RST=1;
Write_A_Byte_TO_DS1302(addr);
dat=Get_A_Byte_FROM_DS1302();
CLK=1;RST=0;
return dat;
}
//向DS1302某地址写入数据--------------------------------------------
void Write_DS1302(uchar addr,uchar dat)
{
CLK=0;RST=1;
Write_A_Byte_TO_DS1302(addr);
Write_A_Byte_TO_DS1302(dat);
CLK=0;RST=0;
}