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