1.原理图
1302芯片部分

lcd12864部分

2.代码部分
config.h
#ifndef __CONFIG_H
#define __CONFIG_H
#include <reg51.h>
#include "lcd12864.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
#endif
lcd12864.c
#include"lcd12864.h"
void lcdinit(void) //初始化LCD
{
write(0,0x30); //功能设定
write(0,0x0c); //显示开关设置
write(0,0x01); //清除指令
}
void sendbyte(uchar bbyte) //发送一个字节 数据发送函数
{
uchar i;
for(i=0;i<8;i++)
{
if((bbyte&0x80)==0x80)
SID=1; //取高四位 串行数据输入端打开
else
SID=0;
SCLK=1; //取低四位 使能信号发送
NOP();NOP();NOP();NOP();//NOP指令通常用于控制时序的目的,强制内存对齐
SCLK=0;
bbyte<<=1; //左移
NOP();NOP();NOP();NOP();
}
}
void lcd_setwindow(uchar x, uchar y) //x只是定位这一行,具体位置通过+y操作 return pos
{
uchar pos;
if(x == 0) // 第一行的地址是80H
{
x = 0x80;
}
else if(x == 1) //第二行的地址是90H
{
x = 0x90;
}
else if(x == 2) //第三行的地址是88H
{
x = 0x88;
}
else if(x == 3) //第四行地址98H
{
x = 0x98;
}
pos = x + y;
write(0,pos);
}
void lcd_writedata(uchar d) //lcd写指令
{
write(1,d);
}
void write(uchar start, uchar ddata) //写指令或数据
{
uchar start_data,Hdata,Ldata; //Hdata -highdata Ldata-lowdata
if(start==0) start_data=0xf8; //写指令
else start_data=0xfa; //写数据
Hdata=ddata &0xf0; //取高四位highdata
Ldata=(ddata<<4)&0xf0; //取低四位lowdata
sendbyte(start_data); //发送起始信号 指令or数据
delaynms(10); //延时是必须的
sendbyte(Hdata); //发送高四位 控制串口通信输入端
delaynms(5); //延时是必须的
sendbyte(Ldata); //发送低四位
delaynms(5); //延时是必须的
}
void lcd_writechar(uchar a[]) //lcd写字符
{
uchar *p=a;
while(*p!='\0') //判断字符串数组是否结束
{
write(1,*p);
p++;
}
write(1,0x00);
}
void line_disp(uchar str[],int line) //直接把数组显示在这一行 line是行数,第一行就写1
{
lcd_writedata('0');
lcd_setwindow(line-1,0); // pos=x+y;
lcd_writechar(str);
}
lcd12864.h
#ifndef __LCD12864_H
#define __LCD12864_H
#define uchar unsigned char
#define uint unsigned int
#include <reg51.h>
#include "intrins.h"
#define NOP(); _nop_();
//引脚定义
sbit SID=P3^7; //数据
sbit SCLK=P3^6; //时钟
sbit BACK=P2^0; //控制背光 BACK=0 背光不亮
void write(uchar start, uchar ddata);
void sendbyte(uchar bbyte);
void delaynms(uint di);
void lcdinit(void);
void lcd_setwindow(uchar x, uchar y);
void lcd_writedata(uchar d);
void lcd_writechar(uchar dat[]);
void line_disp(uchar str[],int line);
#endif
main.c
#include "config.h"
sbit SCK=P0^5;
sbit SDA=P0^6;
sbit RST=P0^7;
uchar readaddre[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; //“读寄存器的地址”
uchar writeaddre[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //“写”寄存器的地址
uchar time[7]={0x00,0x30,0x19,0x11,0x08,0x04,0x20};//初始时间数组
/*--------------------精准延时函数---------------------*/
void delaynms(unsigned int t) //@11.0592MHZ
{
unsigned int i,j;
for(i=0;i<t;i++)
for(j=0;j<113;j++);
}
/*-------------------------------------------*/
//1302写入数据
void DS1302write(uchar addre,uchar dat)
{
uchar i;
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_();
for (i=0;i<8;i++)
{
SDA=addre&0x01;
addre>>=1;
SCK=1;
_nop_();
SCK=0;
_nop_();
}
for (i=0;i<8;i++)
{
SDA=dat&0x01;
dat>>=1;
SCK=1;
_nop_();
SCK=0;
_nop_();
}
RST=0;
}
//1302读数据
uchar DS1302read(uchar addre)
{
uchar i,dat1,dat;
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_();
for (i=0;i<8;i++)
{
SDA=addre&0x01;
addre>>=1;
SCK=1;
_nop_();
SCK=0;
_nop_();
}
_nop_();
for (i=0;i<8;i++)
{
dat1=SDA;
dat=(dat>>1)|(dat1<<7);
SCK=1;
_nop_();
SCK=0;
_nop_();
}
RST=0;
_nop_();
SCK=1;
_nop_();
SDA=1;
_nop_();
SDA=0;
_nop_();
return dat;
}
//初始化1302
void DS1302init()
{
uchar i;
DS1302write(0x8e,0x00);
for (i=0;i<7;i++)
{
DS1302write(writeaddre[i],time[i]);
}
DS1302write(0x8e,0x80);
}
//读取(初始化后)的1302的时间
void DS1302readtime()
{
uchar i;
for (i=0;i<7;i++)
{
time[i]=DS1302read(readaddre[i]);
}
}
void time_change() //存在time里的时间是BCD码,转换为十进制数,同时拆成两个字符显示在lcd12864
{
uint sec,min,hour,mon,year,day,week;
DS1302readtime();
time[0]=(time[0]/16)*10+time[0]%16;
sec=time[0];
time[1]=(time[1]/16)*10+time[1]%16;
min=time[1];
time[2]=(time[2]/16)*10+time[2]%16;
hour=time[2];
time[3]=(time[3]/16)*10+time[3]%16;
day=time[3];
time[4]=(time[4]/16)*10+time[4]%16;
mon=time[4];
time[5]=(time[5]/16)*10+time[5]%16;
week=time[5];
time[6]=(time[6]/16)*10+time[6]%16;
year=time[6];
lcd_setwindow(1,0);
lcd_writedata('0'+year/10);
lcd_writedata('0'+year%10);
lcd_setwindow(1,2);
lcd_writedata('0'+mon/10);
lcd_writedata('0'+mon%10);
lcd_setwindow(1,4);
lcd_writedata('0'+day/10);
lcd_writedata('0'+day%10);
lcd_setwindow(1,6);
//lcd_writedata('0'+week/10);
lcd_writedata('0'+week%10);
lcd_setwindow(3,0);
lcd_writedata('0'+hour/10);
lcd_writedata('0'+hour%10);
lcd_writechar(":");
lcd_writedata('0'+min/10);
lcd_writedata('0'+min%10);
lcd_writechar(":");
lcd_writedata('0'+sec/10);
lcd_writedata('0'+sec%10);
}
void frame()
{
lcd_setwindow(0,0);
lcd_writechar("今天是:");
lcd_setwindow(1,1);
lcd_writechar("年 月 日");
lcd_setwindow(1,5);
lcd_writechar("周");
lcd_setwindow(2,0);
lcd_writechar("现在时间是:");
}
void main(void)
{
BACK=0;
lcdinit();
//DS1302init();//每一次上电初始化时间,初始化一次即可。
lcd_writedata('0'); // 写指令
frame();
while(1)
{
time_change();//时间转换,将BCD码转换为10进制数
delaynms(100);
}
}