/* TSCLK - P10
TIO - P11
TRST - P12 */
#include<reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar a,miao,fen,shi,ri,yue,nian,week,temp,flag,key1n;
#define yh 0x80 //第一行的初始位置
#define er 0x90 //第二行初始位置
#define san 0x88
#define si 0x98
void write_week(uchar week);
/*12864端口定义*/
#define LCD_data P0 //数据口
sbit LCD_RS = P3^5; //寄存器选择输入
sbit LCD_RW = P3^6; //液晶读/写控制
sbit LCD_EN = P3^4; //液晶使能控制
sbit LCD_PSB = P3^7; //串/并方式控制
sbit wela = P2^6;
sbit dula = P2^7;
sbit SCLK=P1^0;
sbit IO=P1^1;
sbit RST=P1^2;
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
sbit key=P3^3;
sbit key1=P3^0;
sbit key2=P3^1;
sbit key3=P3^2;
uchar code dis1[]={"20"} ;
uchar code dis2[]={""};
uchar code dis3[]={" "};
uchar code dis4[]={" "};
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
void delay(int ms)//延时函数(2ms)
{
while(ms--)
{
uchar i;
for(i=0;i<250;i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
bit lcd_busy() //检查LCD忙状态
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
delayNOP();
result = (bit)(P0&0x80);
LCD_EN = 0;
return(result);
}
void lcd_wcmd(uchar cmd) //写指令数据
{
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
void lcd_wdat(uchar dat) //写显示数据
{
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
void lcd_init()//LCD初始化设定
{
LCD_PSB = 1; //并口方式
lcd_wcmd(0x34); //扩充指令操作
delay(5);
lcd_wcmd(0x30); //基本指令操作
delay(5);
lcd_wcmd(0x0C); //显示开,关光标
delay(5);
lcd_wcmd(0x01); //清除LCD的显示内容
delay(5);
}
void lcd_pos(uchar X,uchar Y) /*设定显示位置 */
{
uchar pos;
if (X==0)
{X=0x80;}
else if (X==1)
{X=0x90;}
else if (X==2)
{X=0x88;}
else if (X==3)
{X=0x98;}
pos = X+Y ;
lcd_wcmd(pos); //显示地址
}
/*DS1302*/
void write_byte(uchar dat) //写一个字节
{
ACC=dat;
RST=1;
for(a=8;a>0;a--) //循环8次移位
{
IO=ACC0;
SCLK=0; //先把时钟线拉低
SCLK=1; //把时钟线拉高,锁存数据
ACC=ACC>>1;
}
}
uchar read_byte() //读一个字节
{
RST=1;
for(a=8;a>0;a--)
{
ACC7=IO;
SCLK=1;
SCLK=0;
ACC=ACC>>1;
}
return (ACC);
}
void write_1302(uchar add,uchar dat)//向DS1302写函数,指定写入地址、数据
{
RST=0;
SCLK=0;
RST=1;
write_byte(add);
write_byte(dat);
SCLK=1;
RST=0; //数据传送中止
}
uchar read_1302(uchar add) //从DS1302读取数据函数,指定读取数据来源地址
{
uchar temp;
RST=0; //芯片处于复位状态
SCLK=0; //清零
RST=1; //芯片开始工作
write_byte(add);
temp=read_byte();
SCLK=1;
RST=0;
return(temp);
}
uchar BCD_Decimal(uchar bcd) //BDC码转为十进制函数,输入BCD,返回十进制
{
uchar Decimal;
Decimal=bcd>>4;
return(Decimal=Decimal*10+(bcd&=0x0F));
}
void ds1302a_init()
{
RST=0;
SCLK=0;
//write_1302(0x80,miao|0x00);//允许写
write_1302(0x8e,0x00);
write_1302(0xc0,0xfe);
write_1302(0xc2,0xff);
write_1302(0x80,0x20);
write_1302(0x82,0x10);
write_1302(0x84,0x12);
write_1302(0x86,0x06);
write_1302(0x88,0x06);
write_1302(0x8a,0x18);
write_1302(0x8e,0x80);
}
/*void ds1302b_init()
{
RST=0;
SCLK=0;
write_1302(0x80,ri|0x00);
}*/
void write_sfm(uchar dat)//写时分秒
{
uchar gw,sw;
//lcd_pos(1,0) ;
//lcd_wcmd(er);
gw=dat%10;
sw=dat/10;
lcd_wdat(0x30+sw);
lcd_wdat(0x30+gw);
/*lcd_wdat(0x30+shi/10);
lcd_wdat(0x30+shi%10);
lcd_wdat(':');
lcd_wdat(' ');
lcd_wdat(0x30+fen/10);
lcd_wdat(0x30+fen%10);
lcd_wdat(':');
lcd_wdat(' ');
lcd_wdat(0x30+miao/10);
lcd_wdat(0x30+miao%10);*/
}
void write_nyr(uchar dat) //写年月日
{
uchar gw,sw;
//lcd_pos(0,1);
//lcd_wcmd(yh);
gw=dat%10;
sw=dat/10;
lcd_wdat(0x30+sw);
lcd_wdat(0x30+gw);
/*lcd_wdat(0x30+nian/10);
lcd_wdat(0x30+nian%10);
lcd_wdat('-');
lcd_wdat('-');
lcd_wdat(0x30+yue/10);
lcd_wdat(0x30+yue%10);
lcd_wdat('-');
lcd_wdat('-');
lcd_wdat(0x30+ri/10);
lcd_wdat(0x30+ri%10);*/
}
void write_week(uchar week)//写星期函数
{
lcd_pos(0,6);//lcd_wcmd(yh+0x0b);
lcd_wdat(' ');
switch(week)
{
case 1:lcd_wdat('M');//delay(5);
lcd_wdat('O');//delay(5);
lcd_wdat('N');
break;
case 2:lcd_wdat('T');//delay(5);
lcd_wdat('U');//delay(5);
lcd_wdat('E');
break;
case 3:lcd_wdat('W');//delay(5);
lcd_wdat('E');//delay(5);
lcd_wdat('D');
break;
case 4:lcd_wdat('T');//delay(5);
lcd_wdat('H');//delay(5);
lcd_wdat('U');
break;
case 5:lcd_wdat('F');//delay(5);
lcd_wdat('R');//delay(5);
lcd_wdat('I');
break;
case 6:lcd_wdat('S');//delay(5);
lcd_wdat('T');//delay(5);
lcd_wdat('A');
break;
case 7:lcd_wdat('S');//delay(5);
lcd_wdat('U');//delay(5);
lcd_wdat('N');
break;
}
}
void write_name(uint *s1)//写姓名
{
lcd_pos(2,1);//lcd_wcmd(san);
lcd_wdat(':');
while(*s1!=0)
{
lcd_wdat(*s1);
s1++;
delay(5);
}
}
void write_num(uint *s2)//学号
{
lcd_pos(3,1);//lcd_wcmd(si);
lcd_wdat(':');
while(*s2!=0)
{
lcd_wdat(*s2);
s2++;
delay(5);
}
}
void Clr_Screen()//清屏命令
{
//考虑到前面出现0x34
lcd_wcmd(0x01);
delay(100);
}
void init()//串口初始化
{
TMOD=0x11;//00000001定时计数器0选择方式1,16位定时计数器
TH0=0;
TL0=0;
EA=1; //开全局中断
ET0=1; //定时计数器0中断使能控制位
TR0=1; //定时器T0开始计数
}
void cmg(void)//数码管锁存函数
{
dula=1;
P0=0x00;
dula=0;
wela=1;
P0=0x00;
wela=0;
}
void keyscan()
{
if(key1==0)
{
delay(5);
if(key1==0)
{
while(!key1);
key1n++;
if(key1n==9)
key1n=1;
switch(key1n)
{
case 1: TR0=0; //miao
lcd_wcmd(0x90+4);
lcd_wcmd(0x0f);
temp=(miao)/10*16+(miao)%10 ;
write_1302(0x8e,0x00);
write_1302(0x80,0x80|temp);//miao
write_1302(0x8e,0x80);
break;
case 2: lcd_wcmd(0x90+2); //fen
lcd_wcmd(0x0f);
break;
case 3: lcd_wcmd(0x90); //shi
lcd_wcmd(0x0f);
break;
case 4: lcd_wcmd(0x80+7); //week
lcd_wcmd(0x0f);
break;
case 5: lcd_wcmd(0x80+5); //ri
lcd_wcmd(0x0f);
break;
case 6: lcd_wcmd(0x80+3); //yue
lcd_wcmd(0x0f);
break;
case 7: lcd_wcmd(0x80+1); //nian
lcd_wcmd(0x0f);
break;
case 8: lcd_wcmd(0x0c);
TR0=1;
temp=(miao)/10*16+(miao)%10;//将十进制变成十六进制
write_1302(0x8e,0x00);
write_1302(0x80,0x00|temp);//miao
write_1302(0x8e,0x80);
break;
}
}
}
if(key1n!=0)//当key1按下以下。再按以下键才有效
{
if(key2==0) //上调键
{
delay(5);
if(key2==0)
{
while(!key2);
switch(key1n)
{
case 1: miao++;
if(miao==60)
miao=0;
write_sfm(miao);
lcd_pos(1,4);
temp=(miao)/10*16+(miao)%10;
write_1302(0x8e,0x00);
write_1302(0x80,0x80|temp);
write_1302(0x8e,0x80);
lcd_wcmd(0x90+4);
break;
case 2: fen++;
if(fen==60)
fen=0;
write_sfm(fen);
temp=(fen)/10*16+(fen)%10;
write_1302(0x8e,0x00);
write_1302(0x82,temp);
write_1302(0x8e,0x80);
lcd_wcmd(0x90+2);
break;
case 3: shi++;
if(shi==24)
shi=0;
write_sfm(shi);
temp=(shi)/10*16+(shi)%10;
write_1302(0x8e,0x00);
write_1302(0x84,temp);
write_1302(0x8e,0x80);
lcd_wcmd(0x90);
break;
case 4: week++;
if(week==8)
week=0;
write_week(week);
lcd_wcmd(0x80+7);
lcd_wcmd(0x80+6) ;
break;
case 5: ri++;
if(ri==31)
ri=0;
write_nyr(ri);
temp=(ri)/10*16+(ri)%10;
write_1302(0x8e,0x00);
write_1302(0x86,temp);
write_1302(0x8e,0x80);
lcd_wcmd(0x80+5);
break;
case 6: yue++;
if(yue==13)
yue=0;
write_nyr(yue);
temp=(yue)/10*16+(yue)%10;
write_1302(0x8e,0x00);
write_1302(0x88,temp);
write_1302(0x8e,0x80);
lcd_wcmd(0x80+3);
break;
case 7:
nian++;
if(nian==100)
nian=0;
write_nyr(nian);
temp=(nian)/10*16+(nian)%10;
write_1302(0x8e,0x00);
write_1302(0x8a,temp);
write_1302(0x8e,0x80);
lcd_wcmd(0x80+1);
break;
}
}
}
if(key3==0)
{
delay(5);
if(key3==0)
{
while(!key3);
switch(key1n)
{
case 1: miao--;
if(miao==-1)
miao=59;
write_sfm(miao);
lcd_wcmd(0x90+4);
break;
case 2:fen--;
if(fen==-1)
fen=59;
write_sfm(fen);
temp=(fen)/10*16+(fen)%10;
write_1302(0x8e,0x00);
write_1302(0x82,temp);
write_1302(0x8e,0x80);
lcd_wcmd(0x90+2);
break;
case 3:shi--;
if(shi==-1)
shi=23;
write_sfm(shi);
temp=(shi)/10*16+(shi)%10;
write_1302(0x8e,0x00);
write_1302(0x84,temp);
write_1302(0x8e,0x80);
lcd_wcmd(0x90);
break;
case 4: week--;
if(week==-1)
week=7;
write_week(week);
lcd_wcmd(0x80+7);
lcd_wcmd(0x80+6);
break;
case 5: ri--;
if(ri==-1)
ri=30;
write_nyr(ri);
temp=(ri)/10*16+(ri)%10;
write_1302(0x8e,0x00);
write_1302(0x86,temp);
write_1302(0x8e,0x80);
lcd_wcmd(0x80+5);
break;
case 6: yue--;
if(yue==-1)
yue=12;
write_nyr(yue);
temp=(yue)/10*16+(yue)%10;
write_1302(0x8e,0x00);
write_1302(0x88,temp);
write_1302(0x8e,0x80);
lcd_wcmd(0x80+3);
break;
case 7: nian--;
if(nian==-1)
nian=99;
write_nyr(nian);
temp=(nian)/10*16+(nian)%10;
write_1302(0x8e,0x00);
write_1302(0x8a,temp);
write_1302(0x8e,0x80);
lcd_wcmd(0x80+1);
break;
}
}
}
}
}
main()//主函数
{
uchar i;
delay(10); //延时
wela=0;
dula=0;
cmg();//数码管锁存
ds1302a_init();
//ds1302b_init();
init();
lcd_init(); //初始化LCD
lcd_pos(0,0); //设置显示位置为第一行的第1个字符
i = 0;
while(dis1[i] != '\0')
{ //显示字符
lcd_wdat(dis1[i]);
i++;
}
lcd_pos(1,0); //设置显示位置为第二行的第1个字符
i = 0;
while(dis2[i] != '\0')
{
lcd_wdat(dis2[i]); //显示字符
i++;
}
lcd_pos(2,0); //设置显示位置为第三行的第1个字符
i = 0;
while(dis3[i] != '\0')
{
lcd_wdat(dis3[i]); //显示字符
i++;
}
lcd_pos(3,0); //设置显示位置为第四行的第1个字符
i = 0;
while(dis4[i] != '\0')
{
lcd_wdat(dis4[i]); //显示字符
i++;
}
while(1)
{
keyscan();
}
}
void timer0() interrupt 1 //中断函数
{
miao = BCD_Decimal(read_1302(0x81));
fen = BCD_Decimal(read_1302(0x83));
shi = BCD_Decimal(read_1302(0x85));
ri = BCD_Decimal(read_1302(0x87));
yue = BCD_Decimal(read_1302(0x89));
nian=BCD_Decimal(read_1302(0x8d));
week=BCD_Decimal(read_1302(0x8b));
lcd_pos(1,4);
write_sfm(miao);
lcd_pos(1,3);
lcd_wdat(':');
lcd_pos(1,2);
write_sfm(fen);
lcd_pos(1,1);
lcd_wdat(':');
lcd_pos(1,0);
write_sfm(shi);
lcd_pos(0,5);
write_nyr(ri);
lcd_pos(0,4);
lcd_wdat('-');
lcd_wdat('-');
lcd_pos(0,3);
write_nyr(yue);
lcd_pos(0,2);
lcd_wdat(0x2d);
lcd_wdat(0x2d);
lcd_pos(0,1);
write_nyr(nian);
}
|