如图是电路原理图如下:
单片机源程序如下:
- /*********************************************************************************
- * 【外部晶振】: 11.0592mhz
- * 【主控芯片】: STC89C52
- * 【编译环境】: Keil μVisio3
- * 【程序功能】: LCD1602显示DS1302时钟 ,按键可以调
- * 【使用说明】: 液晶1脚接1602黑色排母的1脚 如果是无背光的液晶只有14个脚 排母右边空2个位
- 请把液晶对比度电位器顺时针调制10点钟方向,请勿多调超出极限位置会损坏电位器!
- 使用前是用杜邦线分别把DS1302旁边3个脚的排针与P1口的0~2接相接
- 接线方式是 请看开饭背面有丝印
- TSCLK - P10
- TIO - P11
- TRST - P12
- -------------------------------调节时钟--------------------------------------------
- 按下S2依次选择秒分时、星期日月年,S3 加,S4减
- * 说明:免费开源,不提供源代码分析.
- **********************************************************************************/
- #include<reg52.h>
- #define uint unsigned int
- #define uchar unsigned char
- uchar a,miao,shi,fen,ri,yue,nian,week,flag,temp,key1n;
- uchar ge,shi,bai,qian;
- #define yh 0x80 //第一行的初始位置
- #define er 0x80+0x40 //第二行初始位置
- #define keyport P2
- //sbit dula=P2^6;
- //sbit wela=P2^7;
- bit f_systick_1ms=0;
- bit f_systick_2ms=0;
- uchar cnt_systick_2ms=0;
- bit f_systick_4ms=0;
- uchar cnt_systick_4ms=0;
- bit f_systick_10ms=0;
- uchar cnt_systick_10ms=0;
- uchar cnt_systick_101ms=0;
- bit f_systick_505ms=0;
- uchar cnt_systick_505ms=0;
- bit f_systick_1s=0;
- uchar cnt_systick_1s=0;
- uchar data current_Event = 0;
- bit flag_Alarm_blink;
- bit swatch_Start_Flag = 0; //秒表计时开始标致位
- sbit wr=P1^1;
- sbit rs=P1^0;
- sbit en=P1^2;
- sbit SCLK=P3^5;
- sbit IO=P3^6;
- sbit RST=P3^7;
- sbit ACC0=ACC^0;
- sbit ACC7=ACC^7;
- sbit key=P2^0;
- sbit key1=P2^1;
- sbit key2=P2^2;
- sbit key3=P2^3;
- uchar keyvalue=0;
- uchar code tab1[]={" - - "};
- uchar code tab2[]={" : : "};
- uchar code tab3[]={"SWITCH"};
- void delay(uint xms)//延时函数
- {
- uint x,y;
- for(x=xms;x>0;x--)
- for(y=110;y>0;y--);
- }
- /*************定时器T0的初始化********************/
- void Timer1_Init(void)
- {
- TMOD=0x11; //T1定时器工作方式1
- TH1=0xfc; //1ms初值
- TL1=0x18;
- ET1=1; //开定时器T0中断
- EA=1; //开总中断
- // TR1=1; //启动定时器T0
- }
- /****************T0定时器中断*********************/
- void ISR_T1(void) interrupt 3 //1ms中断
- {
- TH1=0xfc;
- TL1=0x18; //重装1ms中断
- f_systick_1ms=1; //1ms时基标志位
- }
- /*****************时基处理函数**********************/
- void SysTick_intgnd(void)
- {
- if(f_systick_1ms==1)
- {
- f_systick_1ms=0;
- cnt_systick_2ms++;
- if(cnt_systick_2ms==2)
- {
- cnt_systick_2ms=0;
- f_systick_2ms=1; //按键扫描标志位
- }
- cnt_systick_4ms++;
- if(cnt_systick_4ms==4)
- {
- cnt_systick_4ms=0;
- f_systick_4ms=1; //数码管扫描标志位
- }
- cnt_systick_10ms++;
- if(cnt_systick_10ms==10)
- {
- cnt_systick_10ms=0;
- f_systick_10ms=1;
- cnt_systick_1s++;
- if(cnt_systick_1s==100)
- {
- cnt_systick_1s=0;
- f_systick_1s=1; //时钟1s更新一次标志位
- }
- }
- cnt_systick_101ms++;
- if(cnt_systick_101ms==101)
- {
- cnt_systick_101ms=0;
- flag_Alarm_blink = ~ flag_Alarm_blink; //闹钟报警标志位
- cnt_systick_505ms++;
- if(cnt_systick_505ms==5)
- {
- cnt_systick_505ms=0;
- f_systick_505ms=1;
- }
- }
- }
- }
-
- /******************液晶写入************************/
- write_1602com(uchar com)//液晶写入指令函数
- {
- rs=0;//置为写入命令
- P0=com;//送入数据
- delay(1);
- en=1;//拉高使能端
- delay(1);
- en=0;//完成高脉冲
- }
- write_1602dat(uchar dat)
- {
- rs=1;//置为写入数据
- P0=dat;//送入数据
- delay(1);
- en=1;
- delay(1);
- en=0;
- }
- /*********************over***********************/
- /********************ds1302****************************/
- void write_byte(uchar dat)
- {
- ACC=dat;
- RST=1;
- for(a=8;a>0;a--)
- {
- 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)
- {
- RST=0;
- SCLK=0;
- RST=1;
- write_byte(add);
- write_byte(dat);
- SCLK=1;
- RST=0;
- }
- uchar read_1302(uchar add)
- {
- 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)
- {
- uchar Decimal;
- Decimal=bcd>>4;
- return(Decimal=Decimal*10+(bcd&=0x0F));
- }
- void ds1302_init()
- {
- RST=0;
- SCLK=0;
- write_1302(0x80,miao|0x00);//允许写
- }
-
- void write_sfm(uchar add,uchar dat)//写时分秒
- {
- uchar gw,sw;
- gw=dat%10;
- sw=dat/10;
- write_1602com(er+add);
- write_1602dat(0x30+sw);
- write_1602dat(0x30+gw);
-
- }
- void write_nyr(uchar add,uchar dat) //写年月日
- {
- uchar gw,sw;
- gw=dat%10;
- sw=dat/10;
- write_1602com(yh+add);
- write_1602dat(0x30+sw);
- write_1602dat(0x30+gw);
- write_1602com(yh+6);
- }
- void write_week(uchar week)//写星期函数
- {
- write_1602com(yh+0x0d);
- switch(week)
- {
- case 1:write_1602dat('M');//delay(5);
- write_1602dat('O');//delay(5);
- write_1602dat('N');
- break;
-
- case 2:write_1602dat('T');//delay(5);
- write_1602dat('U');//delay(5);
- write_1602dat('E');
- break;
-
- case 3:write_1602dat('W');//delay(5);
- write_1602dat('E');//delay(5);
- write_1602dat('D');
- break;
-
- case 4:write_1602dat('T');//delay(5);
- write_1602dat('H');//delay(5);
- write_1602dat('U');
- break;
-
- case 5:write_1602dat('F');//delay(5);
- write_1602dat('R');//delay(5);
- write_1602dat('I');
- break;
-
- case 6:write_1602dat('S');//delay(5);
- write_1602dat('T');//delay(5);
- write_1602dat('A');
- break;
-
- case 7:write_1602dat('S');//delay(5);
- write_1602dat('U');//delay(5);
- write_1602dat('N');
- break;
- }
- }
- lcd_init()//液晶初始化函数
- { wr=0;
- write_1602com(0x38);//设置液晶工作模式
- write_1602com(0x0c);//开显示不显示光标
- write_1602com(0x06);//整屏不移动,指针加一
- write_1602com(0x01);
- delay(10);
- // write_1602com(yh+2);//字符写入的位置
- // for(a=0;a<14;a++)
- // {
- // write_1602dat(tab1[a]);
- // //delay(3);
- // }
- // write_1602com(er+4);
- // for(a=0;a<8;a++)
- // {
- // write_1602dat(tab2[a]);
- // //delay(3);
- // }
- }
- void keyscan()
- {
- //key=0;
- if(key==0)
- {
- delay(5);
- if(key==0)
- {
- TR0=0;
- TR1=0;
- write_1602com(0x01);
- delay(1);
-
- if(keyvalue==2)
- keyvalue=0;
- keyvalue++; //设置菜单界面
- }
-
- }
-
- switch(keyvalue)
- {
- case 0:
- case 1: //钟表
- {
- TR0=1;TR1=0;
- if(key1==0)//key1为功能键
- {
- delay(5);
-
- if(key1==0)
- {
- TR0=0;
- TR1=0;
- while(!key1);
- key1n++;
- if(key1n==9)
- key1n=1;
- }
- }
- switch(key1n)
- {
-
- case 1:
- {
- TR0=0; //关闭定时器
- TR1=0;
- write_1602com(er+0x0b);//写入光标位置
- delay(5);
- write_1602com(0x0f);//设置光标为闪烁
- delay(5);
- temp=(miao)/10*16+(miao)%10;
- write_1302(0x8e,0x00);
- write_1302(0x80,0x80|temp);//miao
- write_1302(0x8e,0x80);
- }
- break;
- case 2:
- TR0=0; //关闭定时器
- TR1=0;
- write_1602com(er+8);//fen
-
- //write_1602com(0x0f);
- break;
- case 3:
- TR0=0; //关闭定时器
- TR1=0;
- write_1602com(er+5);//shi
- //write_1602com(0x0f);
- break;
- case 4:
- TR0=0; //关闭定时器
- TR1=0;
- write_1602com(yh+0x0f);//week
- //write_1602com(0x0f);
- break;
- case 5:
- TR0=0; //关闭定时器
- TR1=0;
- write_1602com(yh+0x0b);//ri
- //write_1602com(0x0f);
- break;
- case 6:
- TR0=0; //关闭定时器
- TR1=0;
- write_1602com(yh+0x08);//yue
- //write_1602com(0x0f);
- break;
- case 7:
- TR0=0; //关闭定时器
- TR1=0;
- write_1602com(yh+0x05);//nian
- //write_1602com(0x0f);
- break;
- case 8:
- write_1602com(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(0x0a,miao);//写入新的秒数
- temp=(miao)/10*16+(miao)%10;
- write_1302(0x8e,0x00);
- write_1302(0x80,0x80|temp);
- write_1302(0x8e,0x80);
- write_1602com(er+0x0b);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置
- //write_1602com(0x0b);
- break;
- case 2:fen++;
- if(fen==60)
- fen=0;
- write_sfm(0x07,fen);
- temp=(fen)/10*16+(fen)%10;
- write_1302(0x8e,0x00);
- write_1302(0x82,temp);
- write_1302(0x8e,0x80);
- write_1602com(er+8);
- break;
- case 3:shi++;
- if(shi==24)
- shi=0;
- write_sfm(4,shi);
- temp=(shi)/10*16+(shi)%10;
- write_1302(0x8e,0x00);
- write_1302(0x84,temp);
- write_1302(0x8e,0x80);
- write_1602com(er+5);
- break;
- case 4:week++;
- if(week==8)
- week=0;
- write_week(week);
-
- write_1602com(yh+0x0f);
- break;
- case 5:ri++;
- if(ri==31)
- ri=0;
- write_nyr(10,ri);
- temp=(ri)/10*16+(ri)%10;
- write_1302(0x8e,0x00);
- write_1302(0x86,temp);
- write_1302(0x8e,0x80);
- write_1602com(yh+11);
- break;
- case 6:yue++;
- if(yue==13)
- yue=0;
- write_nyr(7,yue);
- temp=(yue)/10*16+(yue)%10;
- write_1302(0x8e,0x00);
- write_1302(0x88,temp);
- write_1302(0x8e,0x80);
- write_1602com(yh+8);
- break;
- case 7:nian++;
- if(nian==100)
- nian=0;
- write_nyr(4,nian);
- write_1602com(yh+5);
- break;
-
-
- } //switchkeyln
-
- }//key2
-
- }
- if(key3==0)
- {
- delay(5);
- if(key3==0)
- {
- while(!key3);
- switch(key1n)
- {
- case 1:miao--;
- if(miao==-1)
- miao=59;
- write_sfm(0x0a,miao);//写入新的秒数
- write_1602com(er+0x0b);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置
- //write_1602com(0x0b);
- break;
- case 2:fen--;
- if(fen==-1)
- fen=59;
- write_sfm(7,fen);
- temp=(fen)/10*16+(fen)%10;
- write_1302(0x8e,0x00);
- write_1302(0x82,temp);
- write_1302(0x8e,0x80);
- write_1602com(er+8);
- break;
-
- case 3:shi--;
- if(shi==-1)
- shi=23;
- write_sfm(4,shi);
- temp=(shi)/10*16+(shi)%10;
- write_1302(0x8e,0x00);
- write_1302(0x84,temp);
- write_1302(0x8e,0x80);
- write_1602com(er+5);
- break;
- case 4:week--;
- if(week==-1)
- week=7;
- write_week(week);
- write_1602com(yh+0x0f);
- break;
- case 5:ri--;
- if(ri==-1)
- ri=30;
- write_nyr(10,ri);
- temp=(ri)/10*16+(ri)%10;
- write_1302(0x8e,0x00);
- write_1302(0x86,temp);
- write_1302(0x8e,0x80);
- write_1602com(yh+11);
- break;
- case 6:yue--;
- if(yue==-1)
- yue=12;
- write_nyr(7,yue);
- temp=(yue)/10*16+(yue)%10;
- write_1302(0x8e,0x00);
- write_1302(0x88,temp);
- write_1302(0x8e,0x80);
- write_1602com(yh+8);
- break;
- case 7:nian--;
- if(nian==-1)
- nian=99;
- write_nyr(4,nian);
- write_1602com(yh+5);
- break;
-
-
- } //switchkeyln
-
- }
-
- } //key3
-
- }
- }//case1 菜单
- break;
- case 2:
- {
-
- static uint data count;
- TR0=0;TR1=1;
-
- SysTick_intgnd();
- if(key1==0)//秒表计时开始
- {
- delay(5);
- if(key1==0)
- {
- write_1602com(0x01);
- delay(1);
- swatch_Start_Flag =1;
- }
- }
- if(key2==0)//秒表计时结束
- {
- delay(5);
- if(key2==0)
- swatch_Start_Flag =0;
- }
- if(key3==0)//复位
- {
- delay(5);
- if(key3==0)
- swatch_Start_Flag =0;
- count=0;
- }
- if(swatch_Start_Flag ==1)
- {
- if(f_systick_10ms == 1) //产生跑秒
- {
- f_systick_10ms = 0;
- count++;
- if(count==9999) count = 0;
- }
- }
- ge=count%10;
- shi=count/10%10;
- bai=count/100%10;
- qian=count/1000;
- // lcd_init();
- write_1602com(yh+3);
- write_1602dat(ge+0x30);
- write_1602com(yh+2);
- write_1602dat(shi+0x30);
- write_1602com(yh+1);
- write_1602dat(bai+0x30);
- write_1602com(yh+0);
- write_1602dat(qian+0x30);
- }
- break;
-
- }
- }
- void init()
- {
- TMOD=0x11;
- TH0=0;
- TL0=0;
- EA=1;
- ET0=1;
- //TR0=1;
- }
- //void cmg(void)//数码管锁存函数
- //{
- //dula=1;
- //P0=0x00;
- //dula=0;
- //wela=1;
- //P0=0x00;
- //wela=0;
- //}
- 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));
- //keyscan();
- write_sfm(10,miao);
- write_1602com(er+0x09);
- write_1602dat(':');
- write_sfm(7,fen);
- write_1602com(er+0x06);
- write_1602dat(':');
- write_sfm(4,shi);
-
- write_nyr(4,nian);
- write_1602com(yh+0x06);
- write_1602dat('-');
- write_nyr(10,ri);
- write_nyr(7,yue);
- write_1602com(yh+0x09);
- write_1602dat('-');
- write_week(week);
- }
- void main()
- {
- // cmg();//数码管锁存
- lcd_init();
- ds1302_init();
- init();
- Timer1_Init();
- SysTick_intgnd();
- while(1)
- {
- //TH0=(65536-60000)/256;
- //TL0=(65536-60000)%256;
- // if(f_systick_1ms==1)
- // timer0();
- keyscan();
-
- }
- }
复制代码
所有资料51hei提供下载:
【实验104】DS1302时钟显示.rar
(294.79 KB, 下载次数: 17)
|