#include<reg52.h>
#include<intrins.h>
#include<string.h> //字符串操作函数
//宏定义
#define uchar unsigned char
#define uint unsigned char
//定义全局变量
#define lcddata P2 //液晶8位并口数据
uchar hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year;
sbit lcd_rs=P0^7;
sbit lcd_rw=P0^6;
sbit lcd_e=P0^5;
sbit lcd_psw=P0^4;
sbit lcd_rst=P0^3;
uchar week_value[3];
sbit DS1302_RST=P1^0;
sbit DS1302_SCLK=P1^2;
sbit DS1302_DATA=P1^1;
void show_all();//定义特殊位
void delaynms(uint aa)
{
uchar bb;
while(aa--)
{
for(bb=0;bb<115;bb++) //1ms基准延时程序
{
;
}
}
}
void chkbusy_lcd(void)
{
lcddata=0xff; //把忙碌标志位BF置1
lcd_rs=0; //指令操作
lcd_rw=1; //读操作
lcd_e=1; //拉高使能,读取数据
_nop_(); //判断忙碌位是否为0,若果为1,液晶忙,一直等待(BF=1,状态忙)
lcd_e=0; //拉低使能
}
void wr_lcd(uchar dat_comm,uchar content)
{
chkbusy_lcd();
if(dat_comm==1)
{
lcd_rs=1; //data
lcd_rw=0; //write
}
else
{
lcd_rs=0; //command
lcd_rw=0; //write
}
lcd_e=1; //拉高使能
lcddata=content;//放上数据
_nop_(); //等待
lcd_e=0; //拉低使能,使数据写入
}
void init_lcd(void)
{
wr_lcd(0,0x30); //基本指令集
delaynms(1); //等待
wr_lcd(0,0x30); //再设置一次为基本指令集,因为ST7920中有2个寄存器用来设置使用哪个指令集
delaynms(1); //等待
wr_lcd(0,0x0c); //开显示,关游标,关游标位置
delaynms(1); //等待
wr_lcd(0,0x01); //清屏,地址指针指向00H
delaynms(20); //等待>10ms
wr_lcd(0,0x06); //光标右移,整体不移
}
void lcd_clr(void)
{
wr_lcd(0,0x30); //基本指令集
wr_lcd(0,0x01); //清除显示
delaynms(1);
}
void gotoxy(unsigned char y, unsigned char x)
{
if(y==1)
wr_lcd(0,0x80|x); //Line 1
if(y==2)
wr_lcd(0,0x90|x); //Line 2
if(y==3)
wr_lcd(0,((0x80|x)+8)); //Line 3
if(y==4)
wr_lcd(0,((0x90|x)+8)); //Line 4
}
void print(uchar *str)
{
while(*str!='\0') //检查是否到字符串尾
{
wr_lcd(1,*str++); //输入*str后str++
}
}
void DS1302InputByte(uchar d)
{
uchar i;
DS1302_SCLK=0; //拉低SCLK,为上升沿写入数据做好准备
for(i=0;i<8;i++) //连续写入8个二进制数据
{
DS1302_DATA=d&0x01; //取出d的第0位,写入1302, 低位在前,高位在后
_nop_(); //等待
DS1302_SCLK=1; // 拉高SCLK,上升沿写入数据
_nop_(); // 等待
DS1302_SCLK=0; //拉低SCLK形成脉冲
d>>=1; //将d的数据向右移一位,准备写入下一个二进制数据
}
}
uchar DS1302OutputByte(void)
{
uchar i;
uchar dat;
for(i=0;i<8;i++) //连续读出8个二进制数
{
dat>>=1; //向右移一位
if(DS1302_DATA==1) //如果读出数据是1,(上一个写入控制字结束后,保存一个读出数据)
{
dat|=0x80;
}
DS1302_SCLK=1; //拉高SCLK
_nop_();
DS1302_SCLK=0; //拉低SCLK,读取数据
}
return dat; //将读出的数据返回
}
void Write1302(uchar ADDRorCOMM,uchar DATA)
{
DS1302_RST=0; //禁止数据传输
DS1302_SCLK=0; //确保写写之前SCLK被拉低
DS1302_RST=1; //启动数据传输
DS1302InputByte(ADDRorCOMM); //写入命令或地址
DS1302InputByte(DATA); //
DS1302_SCLK=1; //将时钟电平置于高电平状态 $$ 置高是为了让下次写的时候 能准确的被拉低 保证电平
//状态的正确性
DS1302_RST=0; //禁止数据传输
}
uchar Read1302(uchar ADDRorCOMM)
{
uchar dat;
DS1302_RST=0; //禁止数据传输
DS1302_SCLK=0; //确保写写之前SCLK被拉低
DS1302_RST=1; //启动数据传输
DS1302InputByte(ADDRorCOMM); //写入命令或地址
dat=DS1302OutputByte(); // 读出数据
DS1302_SCLK=1; //将时钟电平置于高电平状态置高是为了让下次写的时候 能准确的被拉低 保证电平
//状态的正确性
DS1302_RST=0; //禁止数据传输
return(dat);
}
void Init_1302(void) //(2008年7月12日12时00分00秒星期六)
{
uchar flag;
flag=Read1302(0x81); //读秒寄存器
if(flag&0x80) //CH为0(flag最高位是0),时钟走动,不用初始化 。
{
Write1302(0x8e,0x00); //允许写操作
Write1302(0x8c,((14/10)<<4|(14%10))); //YEAR
Write1302(0x8a,0x01); //DAY
Write1302(0x88,((4/10)<<4|(4%10))); //MONTH
Write1302(0x86,((29/10)<<4|(29%10))); //DATE
Write1302(0x84,((11/10)<<4|(11%10))); //HR
Write1302(0x82,((0/10)<<4|(7%10))); //MIN
Write1302(0x80,((0/10)<<4|(0%10))); //SEC
Write1302(0x90,0xa5); //打开充电功能
Write1302(0x8e,0x80); //禁止写操作
}
}
typedef struct _SYSTEMTIME_
{
uchar Second;
uchar Minute;
uchar Hour;
uchar Week;
uchar Day;
uchar Month;
uchar Year;
uchar DateString[11];
uchar TimeString[9];
}SYSTEMTIME;
SYSTEMTIME CurrentTime;
void DS1302_GetTime(SYSTEMTIME *Time)
{
uchar ReadValue;
ReadValue=Read1302(0x81); //从秒寄存器里读数据
Time->Second=((ReadValue&0x70)>>4)*10+(ReadValue&0x0f); //把读出的数据转换成BCD码
ReadValue=Read1302(0x83); //从分寄存器里读数据
Time->Minute=((ReadValue&0x70)>>4)*10+(ReadValue&0x0f); //把读出的数据转换成BCD码
ReadValue=Read1302(0x85); //从小时寄存器里读数据
Time->Hour=((ReadValue&0x70)>>4)*10+(ReadValue&0x0f); //把读出的数据转换成BCD码
ReadValue=Read1302(0x8b); //从星期寄存器里读数据
Time->Week=((ReadValue&0x70)>>4)*10+(ReadValue&0x0f); //把读出的数据转换成BCD码
ReadValue=Read1302(0x87); //从日寄存器里读数据
Time->Day=((ReadValue&0x70)>>4)*10+(ReadValue&0x0f); //把读出的数据转换成BCD码
ReadValue=Read1302(0x89); //从月寄存器里读数据
Time->Month=((ReadValue&0x70)>>4)*10+(ReadValue&0x0f); //把读出的数据转换成BCD码
ReadValue=Read1302(0x8d); //从年寄存器里读数据
Time->Year=((ReadValue&0xf0)>>4)*10+(ReadValue&0x0f); //把读出的数据转换成BCD码 //注意是0xF0
}
void Date2Str(SYSTEMTIME *Time)
{
// uchar tab[]={0xc8,0xd5,0xbb6,0xfe,0xc8,0xfd,0xcb,0xc4,0xce,0xe5,0xc1,0xf9,0xd2,0xbb};
uchar tab[]={"一二三四五六日"};
if(hide_year<2) ////这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,
{
Time->DateString[0]='2';
Time->DateString[1]='0';
Time->DateString[2]=Time->Year/10+'0';
Time->DateString[3]=Time->Year%10+'0';
}
else
{
Time->DateString[0]=' ';
Time->DateString[1]=' ';
Time->DateString[2]=' ';
Time->DateString[3]=' ';
}
Time->DateString[4]='-';
if(hide_month<2)
{
Time->DateString[5]=Time->Month/10+'0';
Time->DateString[6]=Time->Month%10+'0';
}
else
{
Time->DateString[5]=' ';
Time->DateString[6]=' ';
}
Time->DateString[7]='-';
if(hide_day<2)
{
Time->DateString[8]=Time->Day/10+'0';
Time->DateString[9]=Time->Day%10+'0';
}
else
{
Time->DateString[8]=' ';
Time->DateString[9]=' ';
}
if(hide_week<2)
{
week_value[0]=tab[2*(Time->Week%10)-2]; //星期的数据另外放到 week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示
week_value[1]=tab[2*(Time->Week%10)-1];
}
else
{
week_value[0]=' ';
week_value[1]=' ';
}
week_value[2]='\0';
Time->DateString[10]='\0'; //字符串末尾加 '\0' ,判断结束字符
}
void Time2Str(SYSTEMTIME *Time)
{
if(hide_hour<2)
{
Time->TimeString[0]=Time->Hour/10+'0';
Time->TimeString[1]=Time->Hour%10+'0';
}
else
{
Time->TimeString[0]=' ';
Time->TimeString[1]=' ';
}
Time->TimeString[2]=':';
if(hide_min<2)
{
Time->TimeString[3]=Time->Minute/10+'0';
Time->TimeString[4]=Time->Minute%10+'0';
}
else
{
Time->TimeString[3]=' ';
Time->TimeString[4]=' ';
}
Time->TimeString[5]=':';
if(hide_sec<2)
{
Time->TimeString[6]=Time->Second/10+'0';
Time->TimeString[7]=Time->Second%10+'0';
}
else
{
Time->TimeString[6]=' ';
Time->TimeString[7]=' ';
}
Time->TimeString[8]='\0';
}
//********************************************************************************************
//
// 液晶显示主程序模块
//*********************************************************************************************
void show_all(void)
{
DS1302_GetTime(&CurrentTime); //获取时钟芯片数据
Time2Str(&CurrentTime); //日期数据转化为液晶字符,放在TimeString[9]里,“12:00:00”
Date2Str(&CurrentTime); //时间数据转化为液晶字符,放在DateString[11]里,“2008-07-12”
//星期数据放在week_value[3]里
gotoxy(1,0); //第一行显示
print("【xx的万年历】");
gotoxy(2,0); //
print(CurrentTime.DateString);
gotoxy(2,5); //
print("星期");
gotoxy(2,7);
print(week_value);
gotoxy(3,0); //
print("时间:");
gotoxy(3,3); //
print(CurrentTime.TimeString);
gotoxy(4,0); //
print("制作");
// gotoxy(4,2); //
// print(TempBuffer);
// gotoxy(4,6);
// print("℃");
delaynms(500); //扫描延时
}
void main(void)
{
Init_1302();
while(1)
{
init_lcd(); //液晶初始化
lcd_clr(); //清屏
show_all();
}
}