完整电路图:
完整代码:
#include <reg51.h>
#include <intrins.h> //包含_nop_( )空函数指令的头文件
#define uchar unsigned char
#define uint unsigned int
#define out P2
sbit RS=P3^0;
sbit RW=P3^1;
sbit E=P3^2;
sbit RST=P1^7 ;
sbit SCLK =P1^6;
sbit DSIO=P1^5;
void lcd1602_initial(void); //lcd1602初始化函数
void lcd1602_write_command(uchar com); //lcd1602写命令函数
void lcd1602_write_data(uchar dat); //lcd1602写数据函数
void lcd1602_string(uchar ad ,uchar *s);//lcd1602写字符串
void delay(uint); //延时函数
void Ds1302Write(uchar add,uchar dat);
uchar Ds1302Read(uchar add);
void Ds1302Readtime_data();
uchar bcd_decimal(uchar bcd);
void write_time();
void xinshi_time();
uchar code table1[]={"2021-01-24"};
uchar code table2[]={"23:59:50"};
uchar nian,zhou,yue,ri,shi,fen,miao;
//---DS1302写入和读取时分秒的地址命令---//
//---秒分时日月周年 最低位读写位;-------//
uchar code read_add[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
uchar code write_add[7]= {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
//---DS1302时钟初始化2013年1月1日星期二12点00分00秒。---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
uchar code time_data[7]= {0x58, 0x40, 0x14, 0x29, 0x01, 0x01, 0x21};
uchar code xingqi1[]={"MON"};
uchar code xingqi2[]={"TUE"};
uchar code xingqi3[]={"WED"};
uchar code xingqi4[]={"THU"};
uchar code xingqi5[]={"FRI"};
uchar code xingqi6[]={"SAT"};
uchar code xingqi7[]={"SUN"};
/**************************************************************
*函数名 :delay
*函数功能 :延时函数
*函数参数 :需要延时的毫秒数:uint j
*函数返回值 :无
****************************************************************/
void delay(uint j){ //1ms延时子程序
uchar i=250;
for(;j>0;j--){
while(--i);
i=249;
while(--i);
i=250;
}
}
/**************************** ds1302的驱动程序*********************************/
/*******************************************************************************
*函数名 :Ds1302Read
*函数功能 :读取ds1302中的数据
*函数参数 :所需写入的地址:ucahr addr
*函数返回值 :返回写入的数据:ucahr dat
*******************************************************************************/
uchar Ds1302Read(uchar addr){
uchar n,dat,dat1;
RST = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RST = 1;//然后将RST(CE)置高电平。
_nop_();
for(n=0; n<8; n++){ //开始传送八位地址命令
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
_nop_();
for(n=0; n<8; n++){ //读取8位数据
dat1 = DSIO;//从最低位开始接收
dat = (dat>>1) | (dat1<<7);
SCLK = 1;
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
RST = 0;
_nop_(); //以下为DS1302复位的稳定时间,必须的。
SCLK = 1;
_nop_();
DSIO = 0;
_nop_();
DSIO = 1;
_nop_();
return dat;
}
/*******************************************************************************
*函数名 : Ds1302Write
*函数功能 : 写入设置的时间
*函数参数 : 地址:ucahr addr,数据:ucahr dat
*函数返回值 : 无
*******************************************************************************/
void Ds1302Write(uchar addr, uchar dat){
uchar n;
RST = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RST = 1; //然后将RST(CE)置高电平。
_nop_();
for (n=0; n<8; n++){ //开始传送八位地址命令
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
for (n=0; n<8; n++){ //写入8位数据
DSIO = dat & 0x01;
dat >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
RST = 0;//传送数据结束
_nop_();
}
/*******************************************************************************
*函数名 :Ds1302Init
*函数功能 :ds1302的初始化
*函数参数 :无
*函数返回值 :无
*******************************************************************************/
void Ds1302Init(){
uchar n;
Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能
for (n=0; n<7; n++){ //写入7个字节的时钟信号:分秒时日月周年
Ds1302Write(write_add[n],time_data[n]);
}
Ds1302Write(0x8E,0x80); //打开写保护功能
}
/*******************************************************************************
*函数名 :bcd_decimal
*函数功能 :将BCD吗转成10进制数
*函数参数 :需要转化的bcd:ucahr bcd
*函数返回值 : 转化完成的十进制数:ucahr decimal
*******************************************************************************/
uchar bcd_decimal(uchar bcd){
uchar decimal;
decimal = bcd>>4;
decimal = decimal*10+(bcd&=0x0f);
return decimal;
}
/*******************************************************************************
*函数名 :write_time
*函数功能 :将时间显示在lcd上
*函数参数 :地址:ucahr add, 时间:uchar date
*函数返回值 :无
*******************************************************************************/
void write_time(uchar add,uchar date){
uchar shi,ge;
shi = date/10;
ge = date%10;
lcd1602_write_command(0x80+add);
lcd1602_write_data(0x30+shi);
lcd1602_write_data(0x30+ge);
}
/*******************************************************************************
*函数名 :write_week
*函数功能 :将星期显示在lcd上
*函数参数 :星期的表示值:0-6,分别对应周一到周日:uchar dat
*函数返回值 :无
*******************************************************************************/
void write_week(uchar dat){
switch(dat){
case 1: lcd1602_string(0x80+13,xingqi1); break;
case 2: lcd1602_string(0x80+13,xingqi2); break;
case 3: lcd1602_string(0x80+13,xingqi3); break;
case 4: lcd1602_string(0x80+13,xingqi4); break;
case 5: lcd1602_string(0x80+13,xingqi5); break;
case 6: lcd1602_string(0x80+13,xingqi6); break;
case 7: lcd1602_string(0x80+13,xingqi7); break;
}
}
/*******************************************************************************
*函数名 : xianshi_time
*函数功能 : 显示时间
*函数参数 : 无
*函数返回值 : 无
*******************************************************************************/
void xianshi_time(){
//Ds1302Readtime_data();
miao = bcd_decimal(Ds1302Read(0x81));
fen = bcd_decimal(Ds1302Read(0x83));
shi = bcd_decimal(Ds1302Read(0x85));
ri = bcd_decimal(Ds1302Read(0x87));
yue = bcd_decimal(Ds1302Read(0x89));
zhou = bcd_decimal(Ds1302Read(0x8b));
nian = bcd_decimal(Ds1302Read(0x8d));
write_time(0,nian);
lcd1602_write_command(0x80+2);
lcd1602_write_data(0x2d);
write_time(3,yue);
lcd1602_write_command(0x80+5);
lcd1602_write_data(0x2d);
write_time(6,ri);
write_week(zhou);
write_time(0x40+0,shi);
lcd1602_write_command(0xc0+2);
lcd1602_write_data(0x3a);
write_time(0x40+3,fen);
lcd1602_write_command(0xc0+5);
lcd1602_write_data(0x3a);
write_time(0x40+6,miao);
}
/**************************** lcd1602的驱动程序**********************/
/**************************************************************
*函数名 :lcd1602_write_command
*函数功能 :lcd1602的写命令函数
*函数参数 :所要设置的命令:uchar command
*函数返回值 :无
****************************************************************/
void lcd1602_write_command(uchar command) {
E=0;
RS=0;
RW=0;
out=command;
E=1;
_nop_( );
E=0;
delay(1);
}
/**************************************************************
*函数名 :lcd1602_write_data
*函数功能 :lcd1602的写数据函数
*函数参数 :要写入的数据:uchar dat
*函数返回值 :无
****************************************************************/
void lcd1602_write_data(uchar dat){
E=0;
RS=1;
RW=0;
out=dat;
E=1;
_nop_();
E=0;
delay(1);
}
/**************************************************************
*函数名 : lcd1602_initial
*函数功能 : lcd1602的初始化
*函数参数 : 无
*函数返回值 : 无
****************************************************************/
void lcd1602_initial(void){
lcd1602_write_command(0x38); //写入命令0x38:8位两行显示,5×7点阵字符
lcd1602_write_command(0x0C); //写入命令0x0C:开整体显示,光标关,无黑块
lcd1602_write_command(0x06); //写入命令0x06:光标右移
lcd1602_write_command(0x01); //写入命令0x01:清屏
delay(1);
}
/**************************************************************
*函数名 :lcd1602_string
*函数功能 :将字符串写入对应的地址上
*函数参数 :地址:uchar ad 字符串:uchar *s
*函数返回值 :无
****************************************************************/
void lcd1602_string(uchar ad,uchar *s){
lcd1602_write_command(ad);
while(*s>0){
lcd1602_write_data(*s++); //输出字符串,且指针增1
delay(100);
}
}
/*********************************主函数************************/
/**************************************************************
*函数名 : 主函数
*函数功能 : 驱动程序
*函数参数 : 无
*函数返回值: 无
****************************************************************/
void main(void){
lcd1602_initial( ); //调用对LCD初始化函数
Ds1302Init();
while(1)
{
// lcd1602_string(0x80,table1); //显示的第1行数据
// lcd1602_string(0x80+0x40,table2); //显示第2行数据
xianshi_time();
delay(300); //延时
}
}
效果展示: