#include"STC89C51RC_RD_PLUS.H"<br />#define uchar unsigned char<br />#define uint unsigned int<br />uchar code TAB[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};<br />uchar ucCurtime[7];<br />uchar hour[9],min[9]; <br />uchar *pSecDa;<br />uint KeyValue,x=0,y,c,d,f;<br />uchar time1,time2,time3,a,b;<br />bit e,h=1;<br /><br />/*********************************************************************<br />* 实时时钟模块 时钟芯片型号:DS1302 *<br />*********************************************************************/<br />sbit T_CLK = P3^4; /*实时时钟时钟线引脚 */<br />sbit T_IO = P3^3; /*实时时钟数据线引脚 */<br />sbit T_RST = P3^2; /*实时时钟复位线引脚 */<br />sbit ACC0=ACC^0;<br />sbit ACC7=ACC^7;<br />sbit rxd=P3^0;<br />sbit txd=P3^1;<br />sbit s1=P1^0;<br />sbit s2=P1^1;<br />sbit s3=P1^2;<br />sbit s4=P1^3;<br />sbit s5=P1^4;<br />sbit s6=P1^5;<br />sbit s7=P1^6;<br />sbit s17=P1^7;<br />sbit s37=P3^7;<br />sbit s35=P3^5;<br /><br />/******************************************************************** <br />*<br />* 名称: v_RTInputByte<br />* 说明: <br />* 功能: 往DS1302写入1Byte数据<br />* 调用:<br />* 输入: ucDa 写入的数据 <br />* 返回值: 无<br />***********************************************************************/<br />void v_RTInputByte(uchar ucDa) <br />{ <br />uchar i;<br />ACC = ucDa;<br /><br /><br />for(i=8; i>0; i--)<br />{<br /><br />T_IO = ACC0; /*相当于汇编中的 RRC */<br />T_CLK = 1;<br />T_CLK = 0;<br />ACC = ACC >> 1; <br />} <br />}<br />/******************************************************************** <br />*<br />* 名称: uchar uc_RTOutputByte<br />* 说明: <br />* 功能: 从DS1302读取1Byte数据<br />* 调用: <br />* 输入: <br />* 返回值: ACC<br />***********************************************************************/<br />uchar uc_RTOutputByte(void) <br />{ <br />uchar i;<br />for(i=8; i>0; i--)<br />{<br />ACC = ACC >>1; /*相当于汇编中的 RRC */<br />ACC7 = T_IO;<br />T_CLK = 1;<br />T_CLK = 0;<br />} <br />return(ACC); <br />}<br />/******************************************************************** <br />*<br />* 名称: v_W1302<br />* 说明: 先写地址,后写命令/数据<br />* 功能: 往DS1302写入数据<br />* 调用: v_RTInputByte() <br />* 输入: ucAddr: DS1302地址, ucDa: 要写的数据<br />* 返回值: 无<br />***********************************************************************/<br />void v_W1302(uchar ucAddr, uchar ucDa)<br />{<br />T_RST = 0;<br />T_CLK = 0;<br />T_RST = 1;<br />v_RTInputByte(ucAddr); /* 地址,命令 */<br />v_RTInputByte(ucDa); /* 写1Byte数据*/<br />T_CLK = 1;<br />T_RST =0;<br />} <br />/******************************************************************** <br />*<br />* 名称: uc_R1302<br />* 说明: 先写地址,后读命令/数据<br />* 功能: 读取DS1302某地址的数据<br />* 调用: v_RTInputByte() , uc_RTOutputByte()<br />* 输入: ucAddr: DS1302地址<br />* 返回值: ucDa :读取的数据<br />***********************************************************************/<br />uchar uc_R1302(uchar ucAddr)<br />{<br />uchar ucDa;<br />T_RST = 0;<br />T_CLK = 0;<br />T_RST = 1;<br />v_RTInputByte(ucAddr); /* 地址,命令 */<br />ucDa = uc_RTOutputByte(); /* 读1Byte数据 */<br />T_CLK = 1;<br />T_RST =0;<br />return(ucDa);<br />}<br /><br />/******************************************************************** <br />*<br />* 名称: v_Get1302<br />* 说明: <br />* 功能: 读取DS1302当前时间<br />* 调用: uc_R1302() <br />* 输入: ucCurtime: 保存当前时间地址。当前时间格式为: 秒 分 时 日 月 星期 年 <br />* 7Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B<br />* 返回值: 无<br />***********************************************************************/<br />void v_Get1302() <br />{<br />uchar i;<br />uchar ucAddr = 0x81;<br />for (i=0;i<7;i++)<br />{<br />ucCurtime = uc_R1302(ucAddr);/*格式为: 秒 分 时 日 月 <br />星期 年 */<br />ucAddr += 2;<br />}<br />}<br /><br />void delay(int a) //延时<br />{int i,j;<br />for(j=0;j<a;j++)<br />for(i=0;i<1;i++)v_Get1302();<br />}<br />void xianshi() //....数码管显示子程序....<br />{<br />if(x!=0&e==0)SBUF=0XFF; <br />else SBUF=TAB[time1/16]; //<br />while(!TI) ;<br />TI=0;<br />s5=1;s6=0;s7=1;<br />delay(4);<br />if(x!=0&e==0)SBUF=0XFF; <br />else SBUF=(TAB[time1%16])&0X7F; //<br />while(!TI) ;<br />TI=0;<br />s5=1;s6=0;s7=0;<br />delay(4); <br />if(x!=0&e==0)SBUF=0XFF; <br />else SBUF=TAB[time3/16];<br />while(!TI) ;<br />TI=0;<br />s5=0;s6=1;s7=1;<br />delay(4);<br />if(x!=0&e==0)SBUF=0XFF; <br />else SBUF=(TAB[time3%16])&0X7F;<br />while(!TI) ;<br />TI=0;<br />s5=0;s6=1;s7=0;<br />delay(4); <br />if(x!=0&e==0)SBUF=0XFF; <br />else SBUF=TAB[time2/16]; //<br />while(!TI) ;<br />TI=0;<br />s5=0;s6=0;s7=1;<br />delay(4);<br />if(x!=0&e==0)SBUF=0XFF; <br />else SBUF=TAB[time2%16];<br />while(!TI) ;<br />TI=0;<br />s5=0;s6=0;s7=0;<br />delay(4);<br />}<br />/****************以下为EPPROM读写相关函数*******************************/<br />/*以下为EPPROM保护,每次操作后更改指令值,使EPPROM免于被误操作*/<br />void EPPROM_Protect()<br />{<br /> ISP_CONTR=0x00; //更改指令值,防止出现误操作<br />ISP_CMD=0x00;<br />ISP_TRIG=0x00;<br />ISP_ADDRH=0x00;<br />ISP_ADDRL=0x00;<br />}<br /><br />/*以下为读入指令,入口参数为要读的地址(16位),返回内容(8位)*/<br />uchar EEPROM_Read(uint Addr)<br />{ <br />ISP_ADDRH=Addr/0x100; //送地址<br />ISP_ADDRL=Addr%0x100;<br />ISP_CONTR=0x83; //控制字节<br />ISP_CMD=0x01; //读命令<br />ISP_TRIG=0x46; //触发<br />ISP_TRIG=0xB9;<br />EPPROM_Protect(); //更改相关数值,防止误操作 <br />return(ISP_DATA); //返回读出的值 <br />}<br /><br />/*以下为扇区擦除指令,入口参数为扇区首地址 */<br />void EEPROM_Erase(uint Addr) <br />{<br />ISP_ADDRH=Addr/0x100; //待写入扇区首地址<br />ISP_ADDRL=0x00;<br />ISP_CONTR=0x83;<br />ISP_CMD=0x03; //扇区擦除指令<br />ISP_TRIG=0x46; //触发,将擦除整个扇区<br />ISP_TRIG=0xB9;<br />EPPROM_Protect(); //更改相关数值,防止误操作 <br />}<br /><br />/*以下为写入指令,入口参数为写入的地址(16位)和内容(8位),每次要写入的位置*/<br />void EEPROM_Write(uint Addr,uchar Data)<br />{<br />ISP_DATA=Data; //待写入值<br />ISP_ADDRH=Addr/0x100; //待写入扇区首地址<br />ISP_ADDRL=Addr%0x100;<br />ISP_CONTR=0x83;<br />ISP_CMD=0x02; //写入指令<br />ISP_TRIG=0x46; //触发,数据写入<br />ISP_TRIG=0xB9;<br />EPPROM_Protect(); //更改相关数值,防止误操作 <br />}<br /><br />/**********************数据存储与读取******************************/<br />void DatSave()<br />{ <br /><br /> EEPROM_Erase(0x1000);<br /> EEPROM_Write(0x1000,hour[1]); <br /> EEPROM_Write(0x1001,min[1]);<br /> EEPROM_Write(0x1002,hour[2]); <br /> EEPROM_Write(0x1003,min[2]);<br /> EEPROM_Write(0x1004,hour[3]); <br /> EEPROM_Write(0x1005,min[3]);<br /> EEPROM_Write(0x1006,hour[4]); <br /> EEPROM_Write(0x1007,min[4]);<br />EEPROM_Write(0x1008,hour[5]); <br /> EEPROM_Write(0x1009,min[5]);<br />EEPROM_Write(0x100a,hour[6]); <br /> EEPROM_Write(0x100b,min[6]);<br />EEPROM_Write(0x100c,hour[7]); <br /> EEPROM_Write(0x100d,min[7]);<br />EEPROM_Write(0x100e,hour[8]); <br /> EEPROM_Write(0x100f,min[8]);<br />EEPROM_Write(0x1010,hour[9]); <br /> EEPROM_Write(0x1011,min[9]); <br />} <br /> <br /><br />void DatLoad()<br />{<br /><br /><br /> hour[1]=EEPROM_Read(0x1000); <br /> min[1]=EEPROM_Read(0x1001);<br />hour[2]=EEPROM_Read(0x1002); <br /> min[2]=EEPROM_Read(0x1003);<br />hour[3]=EEPROM_Read(0x1004); <br /> min[3]=EEPROM_Read(0x1005);<br />hour[4]=EEPROM_Read(0x1006); <br /> min[4]=EEPROM_Read(0x1007);<br />hour[5]=EEPROM_Read(0x1008); <br /> min[5]=EEPROM_Read(0x1009);<br />hour[6]=EEPROM_Read(0x100a); <br /> min[6]=EEPROM_Read(0x100b);<br />hour[7]=EEPROM_Read(0x100c); <br /> min[7]=EEPROM_Read(0x100d);<br />hour[8]=EEPROM_Read(0x100e); <br /> min[8]=EEPROM_Read(0x100f);<br />hour[9]=EEPROM_Read(0x1010); <br /> min[9]=EEPROM_Read(0x1011);<br /> <br /><br />}<br />void anjiansm()<br />{<br /> if(s1&s2&s3&s4){ KeyValue=0;return;}<br /> delay(16);<br /> if(!s1)<br /> {<br /> while(!s1){xianshi();}; <br /> KeyValue=1;<br /> return;<br /> }<br /> if(!s2)<br /> {<br /> while(!s2){xianshi();};<br /> KeyValue=2;<br /> return;<br /> }<br /> if(!s3)<br /> {<br /> while(!s3){xianshi();}; <br /> KeyValue=3;<br /> return;<br /> }<br /> if(!s4)<br /> {<br /> while(!s4){xianshi();};<br /> KeyValue=4;<br /> return;<br /> }<br />}<br />void anjiancl() //按键处理子程序<br />{<br /> switch (KeyValue)<br /> {<br /> case 1: x++;if(x==3){x=0;<br /> v_W1302(0x8e,0x00); //写入允许 <br /> v_W1302(0x84,a);<br /> v_W1302(0x82,b);<br /> v_W1302(0x8a,f); <br /> v_W1302(0x80,0x7f&ucCurtime[0]);<br /> v_W1302(0x8e,0x80);<br /> c=1;<br /> } <br /> if(x==2){a=ucCurtime[2] ;<br /> b=ucCurtime[1] ;<br /> f=ucCurtime[5] ; } <br /> break;<br /> case 2:<br /> if(x==1){<br /> hour[c]++; <br /> if((hour[c]|0xf0)==0xfa)hour[c]=(hour[c]+0x10)&0xf0;<br /> if(hour[c]==0x24)hour[c]=0xff;<br /> }<br /> if(x==2) {<br /> a++;<br /> if((a|0xf0)==0xfa)a=(a+0x10)&0xf0;<br /> if(a==0x24)a=0; <br /> } <br /> break;<br /> case 3: <br /> if(x==1){<br /> min[c]++;<br /> if((min[c]|0xf0)==0xfa)min[c]=(min[c]+0x10)&0xf0;<br /> if(min[c]==0x60)min[c]=0x00;<br /> }<br /> if(x==2){<br /> b++;<br /> if((b|0xf0)==0xfa)b=(b+0x10)&0xf0;<br /> if(b==0x60)b=0; <br /> v_W1302(0x8e,0x00);<br /> v_W1302(0x80,0x80);<br /> v_W1302(0x8e,0x80);<br /> }<br /> <br /> break;<br /> case 4:if(x==0) h=~h;<br /> if(x==1){<br /> <br /> c++; if(c==10){c=1; DatSave();}<br /> <br /> }<br /> if(x==2){ f++;if(f==8)f=1;}<br /> break;<br /> default:<br /> if(x==1){time3=hour[c];<br /> time1=c;<br /> time2=min[c];}<br /> if(x==0){ if(h==0){ <br /> time1=ucCurtime[5];<br /> time2=0;<br /> time3=0; <br /> } <br /> else{<br /> time1=ucCurtime[2] ;<br /> time3=ucCurtime[1] ;<br /> time2=ucCurtime[0] ;<br /> }<br /> }<br /> if(x==2) {<br /> time1=a ;<br /> time3=b ;<br /> time2=f ;<br /> }<br /> break;<br /> }<br />}<br />void shaomiao()<br />{<br />for(c=2;c<10;c++)<br /> {<br /> if(hour[c]==ucCurtime[2]&&min[c]==ucCurtime[1]){y=c;return;} <br /> }<br />c=1;<br />}<br />void dingshi()<br />{<br /> int z,l=1;<br /> switch (y)<br />{<br /> case 1:if(ucCurtime[0]%5==0){ //闹钟定时<br /> s17=0;<br /> for(z=0;z<25;z++)xianshi();<br /> s17=1;<br /> for(z=0;z<75;z++)xianshi();}<br /> break;<br /> case 2:if(ucCurtime[0]%5==0){ //闹钟定时<br /> s17=0;<br /> for(z=0;z<25;z++)xianshi();<br /> s37=1;<br /> for(z=0;z<75;z++)xianshi();}<br /> break;<br /> case 3:if(ucCurtime[0]==0x01) //1路电脑开机定时处理<br /> {s37=0;<br /> for(z=0;z<25;z++)xianshi();<br /> s37=1;<br /> for(z=0;z<75;z++)xianshi();}<br /> y=0;<br /> break;<br /> case 4:if(ucCurtime[0]==0x01) //2路电脑开机定时处理<br /> {s37=0;<br /> for(z=0;z<25;z++)xianshi();<br /> s37=1;<br /> for(z=0;z<75;z++)xianshi();}<br /> y=0;<br /> break;<br /> case 5:s35=0; //用电器定时开<br /> break;<br /> case 6:if(ucCurtime[0]==0x00)s35=0; //用电器定时开(一分钟内有30秒是开)<br /> if(ucCurtime[0]==0x30)s35=1;<br /> break;<br /> case 7:s35=1; //定时关<br /> break;<br /> case 8:s35=0; //用电器定时开<br /> break;<br /> case 9:s35=1; //用电器定时关<br /> break;<br /> default:s35=1;s37=1;s17=1;<br /> break;<br />}<br />}<br /><br />void Timer0() interrupt 1 //计时中断子函数,调节闪烁<br />{<br /> d++; //中断一次加1<br />if(d>2) <br /> {<br /> d=0;<br /> e=~e; <br /> }<br />}<br />void main()<br />{ <br /> <br /><br />c=1;<br /><br /> TH0=0x3c; //设定中断初始值<br />TL0=0xb0;<br />TMOD=0x01;<br />EA=1;<br />TR0=1;<br />ET0=1;<br /> v_W1302(0x8e,0x00); //写入允许<br />v_W1302(0x90,0x05); //涓流充电<br />v_W1302(0x8e,0x80);<br />v_Get1302(); <br /> while(1)<br />{<br /> anjiansm();<br /> anjiancl(); <br /> xianshi();<br /> if(x==0) //在未设置完时不扫描定时设置<br /> {<br /> shaomiao();<br /> dingshi();<br /> DatLoad();<br /> }<br /><br />}<br />}<br /><br />
|