程序初始化为系统时间,显示于LCD1602,可以使用按钮修改时间,并与系统同步。
程序可能有一点点缺陷,感兴趣的朋友可以继续完善。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include<reg51.h>
- typedef unsigned char uchar;
- typedef unsigned int uint;
- uchar code table[]= " 2019/07/17/Tue ";
- uchar code table1[]=" 12/05/10 ";
- uchar code table2[]={"Tus"};
- sbit RS=P2^0;
- sbit RW=P2^1;
- sbit E=P2^2;
- sbit K1=P1^0;
- sbit K2=P1^1;
- sbit K3=P1^2;
- sbit K4=P1^3;
- sbit RST=P2^5;
- sbit SCK=P2^6;
- sbit IO=P2^7;
- char shi,fen,miao,flag,dat,ri,yue,nian,xingqi;
- void write_ds(uchar add,uchar date);
- //延迟
- void delay(uchar z)
- {
- uchar x,y;
- for(x=z;x>0;x--)
- for(y=10;y>0;y--);
- }
- //P0口写操作,先写地址,再写数据
- void write_com(uchar com)
- {
- RS=0;
- RW=0;
- P0=com;
- E=1;
- delay(3);
- E=0;
- }
- void write_date(uchar date)
- {
- RS=1;
- RW=0;
- P0=date;
- E=1;
- delay(3);
- E=0;
- }
- //LCD显示初始化
- void init_lcd()
- {
- uchar num;
- write_com(0X38);
- write_com(0X0C);
- write_com(0X06);
- write_com(0X80);
- for(num=0;num<16;num++)
- {
- write_date(table[num]);
- delay(5);
- }
- write_com(0x80+0x40);
- for(num=0;num<20;num++)
- {
- write_date(table1[num]);
- delay(5);
- }
- }
- //LCD显示
- void display1(uchar add,uchar date) //第一行显示
- {
- uchar temp,shi,ge;
- temp=date;
- shi=temp/16;
- ge=temp%16;
- write_com(0x80+add);
- write_date(0x30+shi); //这里要注意,显示的是ASCII码!
- write_date(0x30+ge);
- }
- void display(uchar add,uchar date) //第二行显示
- {
- uchar temp,shi,ge;
- temp=date;
- shi=temp/16;
- ge=temp%16;
- write_com(0x80+0x40+add);
- write_date(0x30+shi); //这里要注意,显示的是ASCII码!
- write_date(0x30+ge);
- }
- //键盘扫描
- void keyscan()
- {
- static unsigned char num;
- K1=0;
- //光标移动(入口地址)
- if(K2==0)
- {
- delay(5);
- if(K2==0)
- {
- while(!K2);
- delay(5);
- while(!K2);
- num++;
- flag=1;
- }//异常重要!!!!
- if(num==1)
- {
- write_com(0X80+0X40+11);
- write_com(0X0F);
- }
- if(num==2)
- {
- write_com(0X80+0X40+8);
- write_com(0X0F);
- }
- if(num==3)
- {
- write_com(0X80+0X40+5);
- write_com(0X0F);
- }
- if(num==4)
- {
- write_com(0x80+10);
- write_com(0x0f);
- }
- if(num==5)
- {
- write_com(0x80+7);
- write_com(0x0f);
- }
- if(num==6)
- {
- write_com(0x80+4);
- write_com(0x0f);
- }
- if(num==7)
- {
- num=0;
- write_com(0X0C);
- write_ds(0x80,miao); //要在最后一次性写入,时分和分针定时的时候秒针还在走。
- write_ds(0x82,fen);
- write_ds(0x84,shi);
- write_ds(0x86,ri);
- write_ds(0x88,yue);
- write_ds(0x8A,nian);
- flag=0;
- }
- }
- //修改时间,增加1
- if(K3==0)
- {
- delay(5);
- if(K3==0)
- {
- while(!K3);
- delay(5);
- while(!K3);
- //修改秒
- if(num==1)
- {
- uchar ge,shi;
- miao++;
- shi=miao/16;
- ge=miao%16;
- //秒的修整
- if(ge>=10)
- {
- ge=0;
- shi++;
- if(shi==6){shi=0;}
- }
- //显示修整值
- miao=shi*16+ge;
- display(10,miao);
- write_com(0x80+0x40+11);//把光标位置移回来。
- write_ds(0x80,miao);
- }
- //修改分钟
- if(num==2)
- {
- uchar ge,shi;
- fen++;
- shi=fen/16;
- ge=fen%16;
- if(ge>=10)
- {
- ge=0;
- shi++;
- if(shi==6){shi=0;}
- }
- fen=shi*16+ge;
- display(7,fen);
- write_com(0x80+0x40+8);
- write_ds(0x82,fen);
- }
- //修改小时
- if(num==3)
- {
- uchar ge,shi1;
- shi++;
- shi1=shi/16;
- ge=shi%16;
- if(ge>=10)
- {
- ge=0;
- shi1++;
- }
- if((shi1==2)&&(ge==4))
- {
- shi1=0;
- ge=0;
- }
- shi=shi1*16+ge;
- display(4,shi);
- write_com(0x80+0x40+5);
- write_ds(0x84,shi);
- }
- }
- }
- //修改时间,减少1
- if(K4==0)
- {
- delay(5);
- if(K4==0)
- {
- while(!K4);
- delay(5);
- while(!K4);
- //修改秒
- if(num==1)
- {
- uchar ge,shi;
- miao--;
- shi=miao/16;
- ge=miao%16;
- //减法0之后应该是9,而不是“?”
- if(ge==0x0f){ge=9;}
- //修改时间,当到达0后,再减的话是-1
- if(ge==-1)
- {
- shi=5;
- ge=9;
- }
- miao=shi*16+ge;
- display(10,miao);
- write_com(0x80+0x40+11);
- write_ds(0x80,miao);
- }
- //修改分钟
- if(num==2)
- {
- uchar ge,shi;
- fen--;
- shi=fen/16;
- ge=fen%16;
- if(ge==0x0f){ge=9;}
- if(ge==-1)
- {
- shi=5;
- ge=9;
- }
- fen=shi*16+ge;
- display(7,fen);
- write_com(0x80+0x40+8);
- write_ds(0x82,fen);
- }
- //修改小时
- if(num==3)
- {
- uchar ge,shi1;
- shi--;
- shi1=shi/16;
- ge=shi%16;
- if(ge==0x0f){ge=9;}
- if(ge==-1)
- {
- shi1=2;
- ge=3;
- }
- shi=shi1*16+ge;
- display(4,shi);
- write_com(0x80+0x40+5);
- write_ds(0x84,shi);
- }
- }
- }
- }
- //DS1302
- void write_ds(uchar add,uchar date)
- {
- uchar num;
- RST=0;//复位
- delay(1);
- SCK=0;
- delay(1);
- RST=1;//关闭复位,开始传输
- delay(1);
- for(num=0;num<8;num++)
- {
- IO=add&0x01;//地址从低位开始传送
- add>>=1;
- //date=date<<1;
- //IO=CY;
- SCK=1;
- delay(1);
- SCK=0;
- delay(1);
- }
- for(num=0;num<8;num++)
- {
- IO=date&0x01;//数据从低位开始传送
- date>>=1;
- //date=date<<1;
- //IO=CY;
- SCK=1;
- delay(1);
- SCK=0;
- delay(1);
- }
- RST=0;//传输结束,复位
- delay(5);
- }
- uchar read_ds(uchar add)
- {
- uchar num,temp,date;
- RST=0;//复位
- delay(1);
- SCK=0;
- delay(1);
- RST=1;
- delay(1);
- for(num=0;num<8;num++)//先写入地址
- {
- IO=add&0x01;//数据从低位开始传送
- add>>=1;
- //date=date<<1;
- //IO=CY;
- SCK=1;
- delay(1);
- SCK=0;
- delay(1);
- }
- delay(2);
- for(num=0;num<8;num++)
- {
- temp=IO;
- date=(date>>1)|(temp<<7);
- SCK=1;
- delay(1);
- SCK=0;
- delay(1);
- }
- RST=0;
- delay(1);
- SCK=1;
- delay(1);
- IO=0;
- delay(1);
- IO=1;
- delay(1);
- return date;
- }
- //LCD初始更新为系统时间
- void init_ds()
- {
- miao=read_ds(0x81);
- display(10,miao);
- fen=read_ds(0x83);
- display(7,fen);
- shi=read_ds(0x85);
- display(4,shi);
- ri=read_ds(0x87);
- display1(9,ri);
- yue=read_ds(0x89);
- display1(6,yue);
- //xingqi=read_ds(0x8B);
- //display(12,table2[]);
- nian=read_ds(0x8D);
- display1(3,nian);
- }
- void set_time()
- {
- write_ds(0x80,0x10);//设置初始时间秒;
- write_ds(0x82,0x10);//设置初始时间分;
- write_ds(0x84,0x14);//设置初始时间时;
- write_ds(0x86,0x22);//设置初始时间日;
- write_ds(0x88,0x03);//设置初始时间月;
- write_ds(0x8a,0x03);//设置初始时间星期;
- write_ds(0x8c,0x15);//设置初始时间年;
- }
- void main()
- {
- flag=0;
- write_ds(0x8e,0x00);
- init_lcd();
- while(1)
- {
- keyscan();
- if(flag==0){init_ds();}
- }
- }
复制代码
全部资料51hei下载地址:
智能电子钟.zip
(323.42 KB, 下载次数: 125)
|