为了实现时钟显示,我们需要运用到时钟芯片。比较常用的时钟芯片为DS1302,在本文中我们采用更好的时钟芯片DS12C887。主要原因是DS1302需要案子后备电池和晶振,而DS12C887自带这两部分,在没有外部电源情况下可以工作10年。关于DS12C887的资料,可见链接:https://github.com/tengweitw/DS12C887
本文主要是通过STC89C52单片机与时钟芯片DS12C887通信,让LCD1602来显示时间,其电路原理图如下:

在图1中,关于单片机和1602液晶部分我们已经在前一篇文章中介绍过了。下面首先给出了时钟芯片DS12C887的实物图,如图2所示:

最后,我们可以根据DS12C887的datasheet来进行程序设计,简单的程序设计如下:
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit lcdrs=P2^5;
sbit lcden=P2^7;
sbit dscs=P1^7;
sbit dsas=P1^6;
sbit dsrw=P1^5;
sbit dsds=P1^4;
uchar count,s1num;
char miao,shi,fen,day,date,month,year;
uchar code week[]=" 2021-05-17 MON";
uchar code time[]=" 00:00:00";
uchar code weeks[]="SUNMONTUEWEDTHUFRISAT";
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
//LCD Write command
void write_com(uchar com)
{
lcdrs=0;
lcden=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
//LCD Write data
void write_date(uchar date)
{
lcdrs=1;
lcden=0;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
// LCD Initialization
void lcdInit()
{
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
}
//DS12C887 Write
void write_ds(uchar add, uchar date)
{
dscs=0;
dsas=1;
dsds=1;
dsrw=1;
P0=add;
dsas=0;
dsrw=0;
P0=date;
dsrw=1;
dsas=1;
dscs=1;
}
//DS12C887 Read
uchar read_ds(uchar add)
{
uchar ds_date;
dsas=1;
dsds=1;
dsrw=1;
dscs=0;
P0=add;
dsas=0;
dsds=0;
P0=0xff;
ds_date=P0;
dsds=1;
dsas=1;
dscs=1;
return ds_date;
}
//Write Time
void write_sfm(uchar add, uchar date)
{
uchar shi, ge;
shi=date/10;
ge=date%10;
write_com(0x80+0x40+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
//Write Calendar
void write_calendar(uchar add, uchar shu)
{
uchar shi,ge;
shi=shu/10;
ge=shu%10;
write_com(0x80+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
//Write week
void write_week(uchar date)
{
write_com(0x80+12);
write_date(weeks[3*date]);
write_date(weeks[3*date+1]);
write_date(weeks[3*date+2]);
}
void set_time()//设置日期和时间
{
// write_ds(4,15);//时
// write_ds(2,44);//分
// write_ds(0,0);//秒
write_ds(6,4);//星期
write_ds(7,20);//日
write_ds(8,5);//月
write_ds(9,21);//年
}
void init()
{
uchar num;
set_time();//只在第一次初始化时钟芯片时用
lcden=0;
// fen=59;
// miao=53;
// shi=23;
write_ds(0x0B,0x26);
read_ds(0x0c);
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
for(num=0;num<15;num++)
{
write_date(week[num]);
delay(5);
}
write_com(0x80+0x40);
for(num=0;num<12;num++)
{
write_date(time[num]);
delay(5);
}
miao=read_ds(0);
fen=read_ds(2);
shi=read_ds(4);
day=read_ds(6);
date=read_ds(7);
month=read_ds(8);
year=read_ds(9);
write_sfm(10,miao);
write_sfm(7,fen);
write_sfm(4,shi);
write_week(day);
write_calendar(9,date);
write_calendar(6,month);
write_calendar(3,year);
}
void main()
{
init();
while(1)
{
miao=read_ds(0);
fen=read_ds(2);
shi=read_ds(4);
write_sfm(10,miao);
write_sfm(7,fen);
write_sfm(4,shi);
}
}
效果图如下:
