#include<reg51.h> #include<intrins.h> #include"DS1302.h" #include"KEY.h" #include"IIC.H" #define uchar unsigned char #define uint unsigned int #define LEDIO P0 #define LEDCHIP P2 sbit BEEP=P3^7; /*************************數(shù)碼管定義**************************************/ //段碼 0 1 2 3 4 5 6 7 8 9 A B - P d uchar code led[15]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x40,0x73,0x5E}; //位選信號(hào) 全滅 uchar code selchip[7]={0x01,0x02,0x04,0x08,0x10,0x20,0x10}; //數(shù)據(jù)格式: 秒 分 時(shí) 日 月 星期 年 uchar time_temp[7]={0x00,0x50,0x10,0x12,0x30,0x01,0x11}; //存放初始化時(shí)間及設(shè)置ds1302的數(shù)據(jù) uchar DataTime[7]; //讀取DS1302的數(shù)據(jù) /**********************************************************/ uchar display[4][6]={0x06,0x5b,0x6d,0x6f,0x6d,0x6f}; //數(shù)碼管顯示 uchar i=0,key1,key2=20,pos=0,p,k; //按鍵和掃描變量 uchar mod=0; //模式:設(shè)置時(shí)間進(jìn)入按鈕 bit bflash=0,clockdown=0; //設(shè)置和鬧鈴標(biāo)志 uchar hour,minute,second,year,month,date; //有關(guān)時(shí)間的變量寄存 uchar ss=1;//鬧鈴響的次數(shù)可以自己修改 uchar clock1[3]={0x06,0,0x01},clock2[3]={14,0,0x01}; //鬧鐘時(shí)間與開關(guān),默認(rèn)開關(guān)開 uint num=5000; //設(shè)置自動(dòng)返回主界面時(shí)間 ///////////////////////////////// void TimeInit() //定時(shí)掃描初始化 { EA = 0; TMOD |= 0x10; TH1 = 0xfd; TL1 = 0xe6; EA=1; // ET0=1; ET1=1; TR1=1; } /////////////////////////////////////////////////////// /* void t0int() interrupt 1 //T0中斷程序,控制發(fā)音的音調(diào) { TR0 = 0; //先關(guān)閉T0 BEEP = ~BEEP; //輸出方波, 發(fā)音 TH0 = t0h; //下次的中斷時(shí)間, 這個(gè)時(shí)間, 控制音調(diào)高低 TL0 = t0l; TR0 = 1; //啟動(dòng)T0 LEDIO=display[mod][i]; LEDCHIP=selchip[i]; if(i>=5) i=0; else i++; } */ ///////////////////////////////////////// void TimeInt() interrupt 3 //定時(shí)掃描中斷 { if(i==pos) { if(bflash==1) //閃爍標(biāo)志;設(shè)置時(shí)間日期和鬧鈴 { if(k++<40) { if(i==4) i=0; else i=i+2; } else { if(p++>40) { p=0; k=0; } } } } LEDIO=display[mod][i]; LEDCHIP=selchip[i]; if(num==0) //自動(dòng)還回時(shí)間界面 { mod=0; bflash=0; } else num--; if(i>=5) i=0; else i++; TH1=0xfa; TL1=0xd8; } //////////////////////////////////////////////////////// void TimeToBin() //把時(shí)間變成2進(jìn)制 { second=DataTime[0]/16*10+DataTime[0]%16; minute=DataTime[1]/16*10+DataTime[1]%16; hour=DataTime[2]/16*10+DataTime[2]%16; date=DataTime[3]/16*10+DataTime[3]%16; month=DataTime[4]/16*10+DataTime[4]%16; year=DataTime[6]/16*10+DataTime[6]%16; } //////////////////////////////////////////////////////// void TimeToBCD() //把時(shí)間變?yōu)锽CD碼 { time_temp[0]=second/10*16+second%10; time_temp[1]=minute/10*16+minute%10; time_temp[2]=hour/10*16+hour%10; time_temp[3]=date/10*16+date%10; time_temp[4]=month/10*16+month%10; time_temp[6]=year/10*16+year%10; } //////////////////////////////////////////////// void TimerDis() { /************************時(shí)間掃描設(shè)置************************/ display[0][0]=led[hour/10]; display[0][1]=led[hour%10]|0x80; display[0][2]=led[minute/10]; display[0][3]=led[minute%10]|0x80; display[0][4]=led[second/10]; display[0][5]=led[second%10]; /************************日期掃描設(shè)置************************/ display[1][0]=led[year/10]; display[1][1]=led[year%10]|0x80; display[1][2]=led[month/10]; display[1][3]=led[month%10]|0x80; display[1][4]=led[date/10]; display[1][5]=led[date%10]; /**********************鬧鈴1掃描設(shè)置****************************/ display[2][0]=led[10]; //第一個(gè)鬧鐘 display[2][1]=led[14-clock1[2]]; //P鬧鐘開d鬧鐘關(guān) display[2][2]=led[clock1[0]/10]; display[2][3]=led[clock1[0]%10]|0x80; display[2][4]=led[clock1[1]/10]; display[2][5]=led[clock1[1]%10]; /***********************鬧鈴2掃描設(shè)置**************************/ display[3][0]=led[11]; //第一個(gè)鬧鐘 display[3][1]=led[14-clock2[2]]; //P鬧鐘開d鬧鐘關(guān) display[3][2]=led[clock2[0]/10]; display[3][3]=led[clock2[0]%10]|0x80; display[3][4]=led[clock2[1]/10]; display[3][5]=led[clock2[1]%10]; /********************************************************/ //second=DataTime[0]/16*10+DataTime[0]%16; } /////////////////////////////////////////////////////// void KeySet() { key1=KeyTab[KeyRvs()]; //讀取鍵盤值 if(key2!=key1) //防止連續(xù)跳動(dòng),釋放按鍵 { if(key1=='*') { pos=0; //返回首位方便設(shè)置 if(!bflash) //先進(jìn)設(shè)置時(shí)間的界面 mod=0; else mod=(mod+1)%4; //功能選擇 bflash=1; //進(jìn)入時(shí)鐘設(shè)置標(biāo)志 num=5000; //若是沒有操作自動(dòng)返回主界面 } /////////////////////////////移位按鍵選擇設(shè)置的位置 if((key1=='0')&&(bflash)) { pos=(pos+2)%6; num=5000; } if((!bflash)&&(key1=='0')) //一鍵關(guān)閉鬧鈴睡懶覺按鍵,下次又開鬧鈴 { clockdown=1; } ///////////////////////////// 時(shí)分秒設(shè)置,加按鍵, if((key1=='#')&&(bflash)) { num=5000; // if(mod==0) //時(shí)間設(shè)置 { if(pos==0) { hour=(hour+1)%24; } else if(pos==2) { minute=(minute+1)%60; } else { second=(second+1)%60; } } ////////////////////////////////年月日設(shè)置 if(mod==1) { if(pos==0) { year=(year+1)%100; } else if(pos==2) { month=(month+1)%13; } else { if(month==2) //二月處理 { if(year%4==0) //閏年二月 date=(date+1)%30; else date=(date+1)%29; } /////////////////////////////////////////////////大月設(shè)置 else if((month==1)||(month==3)||(month==5)||(month==7)||(month==8)||(month==10)||(month==12)) date=(date+1)%32; else /////////////////////////////////////////小月設(shè)置 date=(date+1)%31; } } //////////////////////////////////////////////鬧鈴1設(shè)置 if(mod==2) { if(pos==0) //鬧鈴1開關(guān)設(shè)置 { clock1[2]=(clock1[2]+1)%2; } if(pos==2) { clock1[0]=(clock1[0]+1)%24; } if(pos==4) { clock1[1]=(clock1[1]+1)%60; } } //////////////////////////////////////////////鬧鈴2設(shè)置 if(mod==3) { if(pos==0) //鬧鈴2開關(guān)設(shè)置 { clock2[2]=(clock2[2]+1)%2; } if(pos==2) { clock2[0]=(clock2[0]+1)%24; } if(pos==4) { clock2[1]=(clock2[1]+1)%60; } } } if((!bflash)&&(key1=='#')) //查看鬧鈴設(shè)置 { mod=(mod+1)%2+2; } ///////////////////////////////////////////////確認(rèn)鍵設(shè)置 if(key1=='D') { if(bflash) //清除設(shè)置標(biāo)志 { bflash=0; mod=0; TimeToBCD(); Set_Ds1302(time_temp); while(!Write_Nbyte_iic(SLAVE,0x50,clock1,3)); while(!Write_Nbyte_iic(SLAVE,0x60,clock2,3)); } else //切換時(shí)間和日期 mod=(mod+1)%2; num=5000; //自動(dòng)返回時(shí)間界面 } key2=key1; } //鍵值保存。釋放按鍵用 } ////////////////////////////////////// /********************鬧鈴響一分鐘****************************/ void CLOCK() { if((clock1[0]==hour)&&(clock1[1]==minute)&&(clock1[3])||((clock2[0]==hour)&&(clock2[1]==minute)&&(clock2[3]))) { if(!clockdown) //沒有睡懶覺則正常響鈴 BEEP=~BEEP; else BEEP=1; //否則關(guān)閉鬧鈴 } else { clockdown=0; //恢復(fù)鬧鈴 BEEP=1; //關(guān)閉鬧鈴 } } ///////////////////////////////////////// main() { while(!Read_Nbyte_iic(SLAVE,0x50,clock1,3)); while(!Read_Nbyte_iic(SLAVE,0x60,clock2,3)); TimeInit(); //斷電以后喚醒時(shí)鐘 Init_Ds1302(); while(1) { Get_Ds1302(DataTime); //讀取時(shí)間 TimerDis(); //段碼處理 KeySet(); //掃描按鍵 if(!bflash) //如果沒有進(jìn)入設(shè)置時(shí)間則正常顯示否則時(shí)間暫停 { TimeToBin(); } CLOCK(); //鬧鈴設(shè)置 } } /*******************************************************************************************************************************/ #ifndef _DS1302_H_ #define _DS1302_H_ /*********************************************************************************/ #include<reg51.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int sbit RST = P3^4; sbit SCLK = P3^5; sbit IO = P3^6; /********以下是函數(shù)聲明********/ void Ds1302_Write_Byte(uchar ch); //寫一字節(jié)數(shù)據(jù)函數(shù)聲明 uchar Ds1302_Read_Byte(); //讀一字節(jié)數(shù)據(jù)函數(shù)聲明 void Write_Ds1302(uchar cmd,uchar indata); //寫DS1302函數(shù)聲明 uchar Read_Ds1302(uchar addr); //讀DS1302函數(shù)聲明 void Set_Ds1302(uchar *str); //設(shè)置時(shí)鐘數(shù)據(jù)地址 格式為: 秒 分 時(shí) 日 月 星期 年 void Get_Ds1302(uchar *str); //讀當(dāng)前時(shí)間函數(shù)聲明 void Init_Ds1302(); //DS1302初始化函數(shù)聲明 /********以下是寫一字節(jié)數(shù)據(jù)函數(shù)********/ void Ds1302_Write_Byte(uchar ch) { uchar n; EA=0; for(n=0;n<8;n++) { SCLK=0; //寫時(shí)低電平改變數(shù)據(jù) if(ch&0x01) IO=1; else IO=0; SCLK=1; //高電平把數(shù)據(jù)寫入DS1302 _nop_(); _nop_(); ch=ch>>1; } EA=1; } /********以下是讀一字節(jié)數(shù)據(jù)函數(shù)********/ uchar Ds1302_Read_Byte() { uchar n,temp=0; EA=0; IO=1; for(n=0;n<8;n++) { SCLK=1; if(IO) temp|=0x80; else temp&=0x7f; SCLK=0; //產(chǎn)生下跳沿 temp=temp>>1; } EA=1; return (temp); } /********寫DS1302函數(shù), 往DS1302的某個(gè)地址寫入數(shù)據(jù) ********/ void Write_Ds1302(uchar cmd,uchar indata) { SCLK=0; RST=1; Ds1302_Write_Byte(cmd); Ds1302_Write_Byte(indata); SCLK=0; RST=0; } /********讀DS1302函數(shù),讀DS1302某地址的的數(shù)據(jù)********/ uchar Read_Ds1302(uchar addr) { uchar backdata; RST=0; SCLK=0; RST=1; Ds1302_Write_Byte(addr); //先寫地址 backdata=Ds1302_Read_Byte(); //然后讀數(shù)據(jù) SCLK=0; RST=0; return (backdata); } /********設(shè)置初始時(shí)間函數(shù)********/ void Set_Ds1302(uchar *str) { uchar n,addr = 0x80; Write_Ds1302(0x8e,0x00); //寫控制字,允許寫操作 for(n=0;n<7;n++) { Write_Ds1302(addr,*str); addr=addr+2; str++; } Write_Ds1302(0x8e,0x80); //寫保護(hù),不允許寫 } /********讀取當(dāng)前時(shí)間函數(shù)********/ void Get_Ds1302(uchar *str) { uchar n,addr = 0x81; for(n=0;n<7;n++) { str[n]=Read_Ds1302(addr); addr+=2; } } /************初始化時(shí)間********************/ void Init_Ds1302() { RST=0; SCLK=0; RST=1; Write_Ds1302(0x80,0x00); //寫秒寄存器 Write_Ds1302(0x90,0xab); //寫充電器 Write_Ds1302(0x8e,0x80); //寫保護(hù)控制字,禁止寫 } /////////////////////////////////////// #endif /***********************************************************************************************************************/ #ifndef _KEY_H_ #define _KEY_H_ /****************************************************/ #define KEYIO P1 //定義鍵盤的輸入口 unsigned char code KeyTab[17]="123A456B789C*0#D"; //鍵盤查表 /***********************************************/ void delay_ms(unsigned int time) //誤差 -0.000000000003us { unsigned char a,b; while(time--) { for(b=102;b>0;b--) for(a=3;a>0;a--); } } /**************************************************/ /////////////////////////////////////////////// unsigned char KeyRvs(void) //反轉(zhuǎn)法 { unsigned char temH, temL, key; delay_ms(10); //兩次掃描間隔為10ms,消除抖動(dòng)導(dǎo)致的誤操作 KEYIO = 0x0f; temL = KEYIO;//高四位先輸出0;讀入,低四位含有按鍵信息 KEYIO = 0xf0; temH = KEYIO;//然后反轉(zhuǎn)輸出0;讀入,高四位含有按鍵信息 switch(temL) { case 0x0e: key = 0; break; case 0x0d: key = 1; break; case 0x0b: key = 2; break; case 0x07: key = 3; break; default: return 16;//按下的不是上述按鍵,就當(dāng)是沒有按鍵 } switch(temH) { case 0xe0: return key; case 0xd0: return (key + 4); case 0xb0: return (key + 8); case 0x70: return (key + 12); default: return 16;//按下的不是上述按鍵,就當(dāng)是沒有按鍵 } } /**********************************************************/ #endif ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef _IIC_H #define _IIC_H_ /***************************************************/ #include<intrins.h> #define uchar unsigned char #define uint unsigned int #define SLAVE 0xa0 //IIC器件地址 注意全部接地 #define Rslave SLAVE+1 //送讀控制字 sbit SDA=P3^0; //IIC數(shù)據(jù)接口 sbit SCL=P3^1; //IIC時(shí)鐘接口 //////////////////////////////////////////////////////// void delay_iic(uint time) { for(time;time>0;time--); } /////////////////////////////////////// void start_iic() { SDA=1; SCL=1; delay_iic(10); SDA=0; delay_iic(10); SCL=0; } void stop_iic() { SDA=0; SCL=1; delay_iic(10); SDA=1; delay_iic(10); SCL=0; } void ack_iic() { SDA=0; SCL=1; delay_iic(10); SCL=0; SDA=1; } void nack_iic() { SDA=1; SCL=1; delay_iic(10); SCL=0; SDA=0; } ////////////////////////* write 1 byte *////////////////////// void write_byte(uchar ch) { uchar i; for(i=0;i<8;i++) { if(ch&0x80) SDA=1; else SDA=0; SCL=1; delay_iic(10); SCL=0; ch=ch<<1; } SDA=1; SCL=1; delay_iic(10); if(SDA==1) F0=0; else F0=1; SCL=0; } ///////////////////////////* read 1 byte *//////////////////////// uchar read_byte() { uchar i; uchar r=0; SDA=1; for(i=0;i<8;i++) { r=r<<1; SCL=1; delay_iic(10); if(SDA==1) r++; SCL=0; } return r; } /***********************寫一個(gè)字節(jié)************************** bit Write_Byte_iic(uchar addr,uchar ch) { start_iic(); //產(chǎn)生起始信號(hào) write_byte(SLAVE); //發(fā)送從器件地址 if(F0==0) return 0; //檢查應(yīng)答位 write_byte(addr); //發(fā)送目的地址 if(F0==0) return 0; write_byte(ch); //發(fā)送8為數(shù)據(jù) if(F0==0) return 0; stop_iic(); //停止信號(hào) return 1; } /********************讀一個(gè)字節(jié)*************************** uchar Read_Byte_iic(uchar addr) { uchar ch; start_iic(); //啟動(dòng)IIC write_byte(SLAVE); //寫器件地址 if(F0==0)return 0; write_byte(addr); //寫讀取的地址 if(F0==0)return 0; start_iic(); //再次產(chǎn)生起始信號(hào),不能少 write_byte(Rslave); //送讀控制字 if(F0==0)return 0; ch=read_byte(); //讀出指定單元的內(nèi)容 nack_iic(); //非應(yīng)答信號(hào) stop_iic(); //停止IIC return (ch); } ************************************************************/ //////////////////////////////////////////////////////////// bit Read_Nbyte_iic(uchar slave,uint addr,uchar *str,uchar numb) { uchar i; start_iic(); write_byte(slave); //write iic addr if(F0==0) return 0; write_byte(addr); //write data addr if(F0==0) return 0; start_iic(); //再次產(chǎn)生起始信號(hào),不能少 write_byte(Rslave); //送讀控制字 if(F0==0) return 0; for(i=0;i<numb-1;i++) // { *str=read_byte(); ack_iic(); str++; } *str=read_byte(); nack_iic(); stop_iic(); return(1); } /////////////////////////* write n byte *//////////////////////////// bit Write_Nbyte_iic(uchar slave,uint addr,uchar *str,uchar numb) { uchar i; start_iic(); write_byte(slave); //write iic addr if(F0==0) return 0; write_byte(addr); //write data addr if(F0==0) return 0; for(i=0;i<numb;i++) //write data { write_byte(*str); if(F0==0) return 0; str++; } stop_iic(); //stop iic return(1); } ///////////////////////////////////////////////////////////////// #endif