时间日历显示单片机实验

  • 格式: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;

}