- #include<reg51.h>
- #define uint unsigned int
- #define uchar unsigned char
- /*
- sbit VFD_REM = P1^7;
- sbit VFD_CLK = P1^6;
- sbit VFD_STB = P1^5;
- sbit VFD_DIN = P1^4;
- sbit DS1302_IO=P2^6;
- sbit DS1302_CLK=P2^5;
- sbit DS1302_RST=P2^7;
- sbit k1=P3^4;//功能键
- sbit k2=P3^5;//增加键
- sbit k3=P3^6;//减小键
- sbit k4=P3^7;//查看键
- */
- sbit VFD_CLK = P1^6;
- sbit VFD_STB = P1^5;
- sbit VFD_DIN = P1^7;
- sbit k1=P3^0;//功能键
- sbit k2=P3^1;//增加键
- sbit k3=P3^2;//减小键
- sbit k4=P3^6;//闹钟查看键
- sbit DS1302_IO=P1^0;
- sbit DS1302_CLK=P3^7;
- sbit DS1302_RST=P1^1;
- bit r=1; //用来显示秒点
- uchar code vfdmap[]={0xfc, 0x60, 0xda, 0xf2, 0x66, 0xb6, 0xbe, 0xe0, 0xfe, 0xf6, 0x00};//0-9,-,全灭
- uchar code tab[]={0x00,0x10,0x20,0x40,0x80,0x01,0x02,0x04};//用于星期的
- uchar sec,min,hour,year,month,day,week,s1num,flag,shu;
- unsigned char vfdbuf[]={0,0,0,0,0,0,0};
- uchar time[7];
- void vfd_cmd (uchar vfd_cmd0); /* 写命令*/
- void vfd_wrdata (uchar vfd_wrdata0); /* 写数据 */
- void vfd_init (void); /*16312初始化 */
- void vfd_cmd (uchar vfd_cmd0) /* VFD 写控制命令子程序 */
- {
- unsigned char i;
- VFD_STB=1;
- VFD_CLK=1;
- for ( i=0;i<8;i++ )
- {
- VFD_STB=0;
- VFD_CLK=0;
- VFD_DIN = vfd_cmd0&0x01;
- VFD_CLK=1;
- vfd_cmd0>>=1;
- }
- VFD_STB=1;
- VFD_CLK=1;
- }
- void vfd_wrdata (uchar vfd_wrdata0) /* VFD 写数据子程序 */
- {
- unsigned char i;
- for(i=0;i<8;i++)
- {
- VFD_CLK=1;
- VFD_STB=0;
- VFD_CLK=0;
- VFD_DIN=vfd_wrdata0&0x01;
- VFD_CLK=1;
- vfd_wrdata0>>=1;
- }
- VFD_STB=0;
- VFD_CLK=1;
- }
- void vfd_init(void)
- {
- vfd_cmd ( 0x02 ); /* 6栅X16段显示模式 */
- vfd_cmd ( 0x40 ); /* 显示正常模式,数据地址递增 */
- vfd_wrdata ( 0xc0 ); /* 设置地址从00H开始 */
- }
- void delay_ms(int z)
- {
- int x,y;
- for(x=z;x>0;x--)
- for(y=150;y>0;y--);
- }
- void vfd_time_disp(uchar t_sec,t_min,t_hour,t_week) //显示
- {
- uchar min_ge,sec_shi,sec_ge,min_shi,hour_ge,hour_shi,week;
- sec_shi=(t_sec>>4)&0x0f;
- sec_ge=t_sec&0x0f;
- min_shi=(t_min>>4)&0x0f;
- min_ge=t_min&0x0f;
- hour_shi=(t_hour>>4)&0x0f;
- hour_ge=t_hour&0x0f;
- week=t_week&0x0f;
- vfdbuf[0]=vfdmap[hour_shi];
- vfdbuf[1]=vfdmap[hour_ge];
- vfdbuf[2]=vfdmap[min_shi];
- vfdbuf[3]=vfdmap[min_ge];
- vfdbuf[4]=vfdmap[sec_shi];
- vfdbuf[5]=vfdmap[sec_ge];
- vfdbuf[6]=tab[week]; //星期
- vfd_init( );
- vfd_wrdata (vfdbuf[1]); //C0 第1栅
- vfd_wrdata (vfdbuf[0]); //C1
- vfd_wrdata (0x08); //C2 第2栅
- vfd_wrdata (0); //C3
- vfd_wrdata (vfdbuf[3]|r); //C4 第3栅
- vfd_wrdata (vfdbuf[2]|0x01); //C5
- vfd_wrdata (vfdbuf[5]); //C6 第4栅
- vfd_wrdata (vfdbuf[4]|0x01); //C7
- vfd_wrdata (0x10); //C8 第5栅
- vfd_wrdata (0x10); //C9
- vfd_wrdata (0); //CA
- vfd_wrdata (vfdbuf[6]);//CB
- VFD_STB=1;
- delay_ms(10);
- vfd_cmd ( 0x8f ); // 显示开,14/16脉宽
- delay_ms(1);
- }
- void vfd_date_disp(uchar t_day,t_month,t_year,t_week) //显示
- {
- uchar day_shi,day_ge,month_shi,month_ge,year_ge,year_shi,week;
- day_shi=(t_day>>4)&0x0f;
- day_ge=t_day&0x0f;
- month_shi=(t_month>>4)&0x0f;
- month_ge=t_month&0x0f;
- year_shi=(t_year>>4)&0x0f;
- year_ge=t_year&0x0f;
- week=t_week&0x0f;
- vfdbuf[0]=vfdmap[year_shi];
- vfdbuf[1]=vfdmap[year_ge];
- vfdbuf[2]=vfdmap[month_shi];
- vfdbuf[3]=vfdmap[month_ge];
- vfdbuf[4]=vfdmap[day_shi];
- vfdbuf[5]=vfdmap[day_ge];
- vfdbuf[6]=tab[week]; //星期
- vfd_init( );
- vfd_wrdata (vfdbuf[1]); //C0 第1栅
- vfd_wrdata (vfdbuf[0]); //C1
- vfd_wrdata (0x08); //C2 第2栅
- vfd_wrdata (0); //C3
- vfd_wrdata (vfdbuf[3]); //C4 第3栅
- vfd_wrdata (vfdbuf[2]); //C5
- vfd_wrdata (vfdbuf[5]); //C6 第4栅
- vfd_wrdata (vfdbuf[4]); //C7
- vfd_wrdata (0x10); //C8 第5栅
- vfd_wrdata (0x10); //C9
- vfd_wrdata (0); //CA
- vfd_wrdata (vfdbuf[6]);//CB
- VFD_STB=1;
- delay_ms(10);
- vfd_cmd ( 0x8f ); // 显示开,14/16脉宽
- delay_ms(1);
- }
- void wdayte_byte(uchar dat) //写1字节数据到1302,低位在前。
- {
- uchar i;
- for(i=0;i<8;i++)
- {
- DS1302_IO=0;
- if(dat&0x01)
- DS1302_IO=1;
- else
- DS1302_IO=0;
- dat=dat>>1;
- DS1302_CLK=0;
- DS1302_CLK=1;
- }
- DS1302_CLK=0;
- }
- uchar read_byte() //从DS1302中读1字节数据,读出时高位在前。
- {
- uchar i,dat;
- for(i=0;i<8;i++)
- {
- dat=dat>>1;
- if(DS1302_IO)
- dat=dat|0x80;
- DS1302_CLK=1;
- DS1302_CLK=0;
- }
- DS1302_CLK=0;
- return(dat);
- }
- void wdayte_ds1302(uchar add,uchar dat) //向DS1302的add地址中写入dat数据
- {
- DS1302_RST=0;
- DS1302_CLK=0;
- DS1302_RST=1;
- wdayte_byte(add);
- wdayte_byte(dat);
- DS1302_CLK=0;
- DS1302_RST=0;
- }
- uchar read_ds1302(uchar add) //从DS1302的add地址中读出数据
- {
- uchar time ;
- DS1302_RST=0;
- DS1302_CLK=0;
- DS1302_RST=1;
- wdayte_byte(add);
- time=read_byte();
- DS1302_CLK=0;
- DS1302_RST=0;
- return(time);
- }
- void init_ds1302() //时间初始化函数,不进行初始化DS1302不能正常工作
- {
- wdayte_ds1302(0x8e,0x00);
- wdayte_ds1302(0x8c,time[0]); //写入年数据
- wdayte_ds1302(0x88,time[1]); //写入月数据
- wdayte_ds1302(0x86,time[2]); //写入日数据
- wdayte_ds1302(0x84,time[3]); //写入时数据
- wdayte_ds1302(0x82,time[4]); //写入分数据
- wdayte_ds1302(0x80,time[5]); //写入秒数据
- wdayte_ds1302(0x8a,time[6]); //写入星期数据
- wdayte_ds1302(0x90,0xa5); //充电(因用的是法拉电容,所以选一个二极管,2K电阻)
- wdayte_ds1302(0x8e,0x80);
- }
- void read_time() //时间读取函数
- {
- sec=read_ds1302(0x81);
- min=read_ds1302(0x83);
- hour=read_ds1302(0x85);
- week=read_ds1302(0x8b);
- day=read_ds1302(0x87);
- month=read_ds1302(0x89);
- year=read_ds1302(0x8d);
- time[0]=year;
- time[1]=month;
- time[2]=day;
- time[3]=hour;
- time[4]=min;
- time[5]=sec;
- time[6]=week;
- }
- void keyscan() //键盘检测函数,用于时间的调节
- {
- if(k4==0) //K4在没有调整时间时按下显示日期,有调时按下先保存退出再显示日期
- {
- delay_ms(1);
- if(k4==0)
- {
- if(flag==1)
- {
- init_ds1302();
- }
- vfd_date_disp(day,month,year,week);
- delay_ms(2000);
- flag=0;
- s1num=0;
- }
- }
- if(k1==0)
- {
- delay_ms(1);
- if(k1==0)
- {
- while(!k1);
- s1num++;
- flag=1;
- if(s1num==7)
- {
- init_ds1302();
- flag=0;
- s1num=0;
- }
- }
- }
- if(s1num!=0)
- {
- if(k2==0)//加键按下
- {
- delay_ms(1);
- if(k2==0)
- {
- switch(s1num)
- {
- case 1: min=((min/16)*10)+(min%16);
- min++;
- if(min==60)
- min=0;
- time[4]=(((min/10)<<4)&0xf0)|((min%10)&0x0f);
- time[5]=0x00;
- wdayte_ds1302(0x8e,0x00);
- wdayte_ds1302(0x80,time[5]);
- wdayte_ds1302(0x82,time[4]);
- wdayte_ds1302(0x8e,0x80);
- break;
- case 2: hour=((hour/16)*10)+(hour%16);
- hour++;
- if(hour==24)
- hour=0;
- time[3]=(((hour/10)<<4)&0xf0)|((hour%10)&0x0f);
- wdayte_ds1302(0x8e,0x00);
- wdayte_ds1302(0x84,time[3]);
- wdayte_ds1302(0x8e,0x80);
- break;
- case 3: day=((day/16)*10)+(day%16);
- day++;
- if(day==32)
- day=1;
- time[2]=(((day/10)<<4)&0xf0)|((day%10)&0x0f);
- wdayte_ds1302(0x8e,0x00);
- wdayte_ds1302(0x86,time[2]);
- wdayte_ds1302(0x8e,0x80);
- break;
- case 4: month=((month/16)*10)+(month%16);
- month++;
- if(month==13)
- month=1;
- time[1]=(((month/10)<<4)&0xf0)|((month%10)&0x0f);
- wdayte_ds1302(0x8e,0x00);
- wdayte_ds1302(0x88,time[1]);
- wdayte_ds1302(0x8e,0x80);
- break;
- case 5: year=((year/16)*10)+(year%16);
- year++;
- if(year>99)
- year=0;
- time[0]=(((year/10)<<4)&0xf0)|((year%10)&0x0f);
- wdayte_ds1302(0x8e,0x00);
- wdayte_ds1302(0x8c,time[0]);
- wdayte_ds1302(0x8e,0x80);
- break;
- case 6: week=week%16;
- week++;
- if(week>7)
- week=1;
- time[6]=((week%10)&0x0f);
- wdayte_ds1302(0x8e,0x00);
- wdayte_ds1302(0x8a,time[6]);
- wdayte_ds1302(0x8e,0x80);
- break;
- }
- }
- }
- if(k3==0)//减键按下
- {
- delay_ms(1);
- if(k3==0)
- {
- switch(s1num)
- {
- case 1: min=((min/16)*10)+(min%16);
- min--;
- if(min==-1)
- min=59;
- time[4]=(((min/10)<<4)&0xf0)|((min%10)&0x0f);
- time[5]=0x00;
- wdayte_ds1302(0x8e,0x00);
- wdayte_ds1302(0x80,time[5]);
- wdayte_ds1302(0x82,time[4]);
- wdayte_ds1302(0x8e,0x80);
- break;
- case 2: hour=((hour/16)*10)+(hour%16);
- hour--;
- if(hour==-1)
- hour=23;
- time[3]=(((hour/10)<<4)&0xf0)|((hour%10)&0x0f);
- wdayte_ds1302(0x8e,0x00);
- wdayte_ds1302(0x84,time[3]);
- wdayte_ds1302(0x8e,0x80);
- break;
- case 3: day=((day/16)*10)+(day%16);
- day--;
- if(day==0)
- day=31;
- time[2]=(((day/10)<<4)&0xf0)|((day%10)&0x0f);
- wdayte_ds1302(0x8e,0x00);
- wdayte_ds1302(0x86,time[2]);
- wdayte_ds1302(0x8e,0x80);
- break;
- case 4: month=((month/16)*10)+(month%16);
- month--;
- if(month==-1)
- month=12;
- time[1]=(((month/10)<<4)&0xf0)|((month%10)&0x0f);
- wdayte_ds1302(0x8e,0x00);
- wdayte_ds1302(0x88,time[1]);
- wdayte_ds1302(0x8e,0x80);
- break;
- case 5: year=((year/16)*10)+(year%16);
- year--;
- if(year==-1)
- year=99;
- time[0]=(((year/10)<<4)&0xf0)|((year%10)&0x0f);
- wdayte_ds1302(0x8e,0x00);
- wdayte_ds1302(0x8c,time[0]);
- wdayte_ds1302(0x8e,0x80);
- break;
- case 6: week=week%16;
- week--;
- if(week==0)
- week=7;
- time[6]=((week%10)&0x0f);
- wdayte_ds1302(0x8e,0x00);
- wdayte_ds1302(0x8a,time[6]);
- wdayte_ds1302(0x8e,0x80);
- break;
- }
- }
- }
- }
- }
- void set_time_disp(s1num,flag) //时间调节显示函数
- {
- uchar i;
- if((s1num==1)&&(flag==1))
- {
- read_time();
- for(i=0;i<10;i++)
- vfd_time_disp(sec,min,hour,week);
- for(i=0;i<10;i++)
- vfd_time_disp(sec,0xaa,hour,week);
- }
- if((s1num==2)&&(flag==1))
- {
- read_time();
- for(i=0;i<10;i++)
- vfd_time_disp(sec,min,hour,week);
- for(i=0;i<10;i++)
- vfd_time_disp(sec,min,0xaa,week);
- }
- if((s1num==3)&&(flag==1))
- {
- read_time();
- for(i=0;i<10;i++)
- vfd_date_disp(day,month,year,week);
- for(i=0;i<10;i++)
- vfd_date_disp(0xaa,month,year,week);
- }
- if((s1num==4)&&(flag==1))
- {
- read_time();
- for(i=0;i<10;i++)
- vfd_date_disp(day,month,year,week);
- for(i=0;i<10;i++)
- vfd_date_disp(day,0xaa,year,week);
- }
- if((s1num==5)&&(flag==1))
- {
- read_time();
- for(i=0;i<10;i++)
- vfd_date_disp(day,month,year,week);
- for(i=0;i<10;i++)
- vfd_date_disp(day,month,0xaa,week);
- }
- if((s1num==6)&&(flag==1))
- {
- read_time();
- for(i=0;i<10;i++)
- vfd_date_disp(day,month,year,week);
- for(i=0;i<10;i++)
- vfd_date_disp(day,month,year,0x00);
- }
- }
- void main()
- {
- TMOD=0x01; //设定定时器0为方式1
- TH0=(65536-50000)/256; //定时时间设置,时间设为50毫秒
- TL0=(65536-50000)%256;
- EA=1; //开总中断
- ET0=1; //开定时器0中断
- TR0=1; //启动定时器0
- while(1)
- {
- keyscan();
- read_time(); //按键检测
- if(flag==0) //如果没有按键进入这里
- {
- vfd_time_disp(sec,min,hour,week);
- }
- if(flag==1) //如果有按键进入这里
- {
- set_time_disp(s1num,flag);
- }
- }
- }
- void T0_time() interrupt 1 //中断函数用于秒点的闪烁,周期1秒
- {
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- shu++; //用于时间的计数10次500MS
- if(shu==10)
- {
- shu=0;
- r=~r; //每500毫秒led取反一次
- }
- }
复制代码
|