- /*********************************************************************************
- 8位数码管显示实时时钟
- 仿真 实物都通过. 11.0592MHz晶振,两片74HC573做段选、位选
- 调时的时候,key2键短按加1,长按连加;key3键短按减一,长按连减;按键消抖不用delay
- **********************************************************************************/
- #include<reg52.h>
- #include<intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- /***********写时分秒地址************/
- #define write_shi 0x84
- #define write_fen 0x82
- #define write_miao 0x80
- /***********读时分秒地址************/
- #define read_shi 0x85
- #define read_fen 0x83
- #define read_miao 0x81
- sbit sclk = P1^0; //控制数据时钟
- sbit dio = P1^1; //数据口
- sbit ce = P1^2; //使能端、复位端
- sbit wela = P2^7; //位选
- sbit dula = P2^6; //段选
- //sbit IO=P1^1; //数据口
- //sbit SCLK=P1^0; //控制数据时钟
- //sbit RST=P1^2; //使能端、复位端
- sbit key1=P3^0; //按键 选择
- sbit key2=P3^1; //按键 加
- sbit key3=P3^2; //按键 减
- uchar knum=0,snum,fnum,ss;
- char shi,fen,miao;
- // 0 1 2 3 4 5 6 7 8 9
- uchar code d[]={ 0x3F,0x06,0x5B,0x4F,0x66, 0x6D,0x7D,0x07,0x7F,0x6F}; //共阴不带小数点
- uchar code dd[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};// 共阴带小数点
- //uchar dd[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //共阳带小数点
- //uchar d[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xd8,0x80,0x90}; //共阳不带小数点
- void delay(uint z)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=120;y>0;y--);
- }
- void t0_init() //定时50ms一个中断
- {
-
- TMOD=0X01;
- TH0=(65536-46080)/256;
- TL0=(65536-46080)%256;
- // TH1=(65536-46080)/256;
- // TL1=(65536-46080)%256;
- EA=1;
- ET0=1;
- TR0=1;
- // ET1=1;
- // TR1=1;
- }
- void display(uchar shi,uchar fen,uchar miao) //显示函数
- {
- if(knum==0)
- {
- snum=30;
- fnum=30;
- }
-
- if(knum==1)
- {
- fnum++;
- snum=30;
- }
-
- if(knum==2)
- {
- snum++;
- fnum=30;
- }
-
-
- if(snum>=30)
- {
- if((shi/10)<1) //如果小时十位小于1,
- {
- wela=1;
- P0=0xfe; //第1位
- wela=0;
-
- dula = 1;
- P0=0xff; // 小时十位就不显示
- dula = 0;
- }
-
- else
- {
- wela=1;
- P0=0xfe; //第1位
- wela=0;
-
- dula=1;
- P0=d[shi/10];
- dula=0;
- P0=0xff;
- delay(2);
- }
- wela=1;
- P0=0xfd; //第2位
- wela=0;
- dula=1;
- P0=d[shi%10]; //时的个位,P0=d[shi%10]时的个位小数点闪烁
- dula=0; // 时的个位,P0=dd[shi%10]时的个位小数点不闪烁
- P0=0xff;
- delay(2);
-
- if(snum==60)
- snum=0;
- }
- // if(miao%2==0) //if(miao%2==0) 1秒闪烁1次
- if(ss>=10) // 这里写为ss>=10,闪烁频率可调
- {
- wela=1;
- P0=0xfb; //第3位
- wela=0;
-
- dula=1;
- P0=0x40; //第三位数码管显示“— ”
-
- // P0=0x09; //第三位数码管显示“= ”
- dula=0;
- P0=0xff;
- delay(2);
- }
- else
- {
- wela=1;
- P0=0xfb; //第3位
- wela=0;
-
- dula=1;
- P0=0; //第三位数码管不显示
- dula=0;
- P0=0xff;
- delay(2);
- }
-
-
- if(fnum>=30)
- {
- wela=1;
- P0=0xf7; //第4位
- wela=0;
- dula=1;
- P0=d[fen/10];
- dula=0;
- P0=0xff;
- delay(2);
-
-
- wela=1;
- P0=0xef; //第5位
- wela=0;
- dula=1;
- P0=d[fen%10];
- dula=0;
- P0=0xff;
- delay(2);
-
-
- if(fnum==60)
- fnum=0;
- }
-
- // if(miao%2==0) //if(miao%2==0) 1秒闪烁1次
- if(ss>=10) //if(ss>=10)闪烁频率可调
- {
- wela=1;
- P0=0xdf; //第6位
- wela=0;
- dula=1;
- P0=0x40; //第六位数码管显示“— ”
- dula=0;
- P0=0xff;
-
- delay(2);
- }
- else
- {
- wela=1;
- P0=0xdf; //第6位
- wela=0;
- dula=1;
- P0=0; //第六位数码管不显示
- dula=0;
- P0=0xff;
-
- delay(2);
- }
-
-
- wela=1;
- P0=0xbf; //第7位
- wela=0;
- dula=1;
- P0=d[miao/10]; //秒十位
- dula=0;
- P0=0xff;
- delay(2);
-
- wela=1;
- P0=0x7f; //第8位
- wela=0;
- dula=1;
- P0=d[miao%10]; //秒个位
- dula=0;
- P0=0xff;
- delay(2);
- }
- void write_1302(uchar add,dat) //写函数 qx
- {
- uchar i,temp;
- temp=add;
- ce=0;
- _nop_();
- sclk=0;
- _nop_();
- ce=1;
- _nop_();
- for(i=0;i<8;i++)
- {
- sclk=0;
- _nop_();
- if((temp&0x01)==0x01)
- dio=1;
- else
- dio=0;
- temp>>=1;
- sclk=1;
- _nop_();
- }
- temp=dat;
- for(i=0;i<8;i++)
- {
- sclk=0;
- _nop_();
- if((temp&0x01)==0x01)
- dio=1;
- else
- dio=0;
- temp>>=1;
- sclk=1;
- _nop_();
- }
- ce=0;
- sclk=0;
- }
- uchar read_1302(uchar add) //读函数 qx
- {
- uchar dat,dat1,i,temp;
- temp=add;
- ce=0;
- _nop_();
- sclk=0;
- _nop_();
- ce=1;
- for(i=0;i<8;i++)
- {
- sclk=0;
- _nop_();
- if((temp&0x01)==0x01)
- dio=1;
- else
- dio=0;
- temp>>=1;
- sclk=1;
- _nop_();
- }
- for(i=0;i<8;i++)
- {
- sclk=0;
- _nop_();
- if(dio)
- dat|=0x80;
- if(i<7)
- dat>>=1;
- sclk=1;
- }
- dat1=dat/16;
- dat=dat%16;
- dat=dat1*10+dat;
- ce=0;
- sclk=0;
- return dat;
- }
- /*
- uchar read_1302(uchar add) //读函数
- {
- uchar i,date;
- RST=0; //禁止读写数据
- for(i=0;i<8;i++)
- {
- RST=1;
- SCLK=0;
- IO=add&0x01;
- add>>=1;
- SCLK=1;
- }
- for(i=0;i<8;i++)
- {
- if(IO)
- date=date|0x80;
- else
- date=date|0x00;
- SCLK=1;
- date>>=1;
- SCLK=0;
- }
- RST=0;
- date=date/16*10+date%16; //进制转换 16转10进制
- IO=0; //数据读完后,IO口必须为0,不然小时一直显示85
- return date;
- }
- void write_1302(uchar add,uchar dat) //写函数
- {
- uchar i;
- RST=0; //禁止读写数据
- SCLK=0;
- for(i=0;i<8;i++) //写地址
- {
- RST=1; //允许读写数据
- SCLK=0;
- IO=add&0x01;
- add>>=1;
- SCLK=1;
- }
- for(i=0;i<8;i++) //写数据
- {
- RST=1; //允许读写数据
- SCLK=0;
- IO=dat&0x01;
- dat>>=1;
- SCLK=1;
- }
- RST=0;
- } */
- void init_1302() //初始化函数 设置第一次上电时显示的时间值
- {
- write_1302(0x8e,0x00); //保护取消,可以进行写操作
- write_1302(write_miao,0x57); //写秒57
- write_1302(write_fen,0x55); //写分55
- write_1302(write_shi,0x15); //写时15
- write_1302(0x8e,0x80); //保护启动,不能进行写操作
- }
- void read_sf() //读时分秒并显示
- {
- shi=read_1302(read_shi);
- fen=read_1302(read_fen);
- miao=read_1302(read_miao);
- display(shi,fen,miao);
- }
- void keyscan() //按键扫描函数
- {
- static uchar count; //这里要定义为静态变量
- if(key1==0) //按键按下
- {
- count++; //消抖,也是连加一次的间隔时间
- if(key1==0 && count>10)//按键按下,计数变量加到12,
- {
- while(!key1) //这里不需要连加,就加一句松手检测
- display(shi,fen,miao);
- count=0;
- TR0=0;
- knum++;
- if(knum==1)
- {
- write_1302(0x8e,0x00); //DS1302写保护取消
- write_1302(write_miao,0x80); //写秒80,时钟停止走时;
- }
-
- if(knum==3) //调时完毕,时钟启动
- {
- TR0=1;
- knum=0;
- write_1302(write_miao,0x00); //写秒0,时钟启动走时
- write_1302(0x8e,0x80); //保护启动
- }
- }
- }
- if(knum==1) //分钟调节
- {
- if(key2==0) //加
- {
- count++;
- if(key2==0 && count>12)//短按加1,长按连加
- {
- count=0;
- fen++;
- fen=fen/10*16+fen%10; //转为16进制
- if(fen==0x60)
- fen=0x00;
- write_1302(write_fen,fen); //写入1302
- }
- }
-
- if(key3==0) //减
- {
- count++;
- if(key3==0 && count>12)//短按减1,长按连减
- {
- count=0;
- fen--;
- fen=fen/10*16+fen%10; //转为16进制
- if(fen==-1)
- fen=0x59;
- write_1302(write_fen,fen);
- }
- }
- }
-
-
- if(knum==2) //小时调节
- {
- if(key2==0)
- {
- count++;
- if(key2==0 && count>12 )//短按加1,长按连加
- {
- count=0;
- shi++;
- shi=shi/10*16+shi%10; //转为16进制
- if(shi==0x24)
- shi=0x00;
- write_1302(write_shi,shi);
- }
- }
-
-
- if(key3==0)
- {
- count++;
- if(key3==0 && count>12 )//短按减1,长按连减
- {
- count=0;
- shi--;
- shi=shi/10*16+shi%10; //转为16进制
- if(shi==-1)
- shi=0x23;
- write_1302(write_shi,shi);
- }
- }
- }
- }
- void main()
- {// uchar i;
- t0_init();
- init_1302();
- while(1)
- {
- // for(i=0;i<4;i++)
- // display(shi,fen,miao);
- read_sf();
- keyscan();
- }
- }
- void temer1() interrupt 1
- {
- TH0=(65536-46080)/256;
- TL0=(65536-46080)%256;
- ss++;
- if(ss==20)
- ss=0;
- }
- //void temer2() interrupt 3
- //{
- // TH1=(65536-46080)/256;
- // TL1=(65536-46080)%256;
- // ss1++;
- // if(ss1==20) //1秒
- // {
- // ss1=0;
- //// zs++;
- // zs1--;
- // }
- //}
复制代码 |