新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 基于DS1302的簡易數(shù)碼管電子鐘

基于DS1302的簡易數(shù)碼管電子鐘

作者: 時間:2012-08-10 來源:網(wǎng)絡(luò) 收藏
#includereg51.h>#includeintrins.h>#include".h"#include"KEY.h"#include"IIC.H"#define uchar unsigned char#define uint unsigned int#define LEDIO P0#define LEDCHIP P2sbit BEEP=P3^7;/*************************定義**************************************///段碼        0   1    2    3    4    5     6    7   8    9   A    B  -  P   duchar code led[15]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x40,0x73,0x5E};//位選信號                                   全滅uchar code selchip[7]={0x01,0x02,0x04,0x08,0x10,0x20,0x10};//數(shù)據(jù)格式:   秒   分   時   日   月 星期   年uchar  time_temp[7]={0x00,0x50,0x10,0x12,0x30,0x01,0x11};  //存放初始化時間及設(shè)置ds1302的數(shù)據(jù)uchar  DataTime[7];           //讀取的數(shù)據(jù)/**********************************************************/    uchar  display[4][6]={0x06,0x5b,0x6d,0x6f,0x6d,0x6f};    //顯示uchar  i=0,key1,key2=20,pos=0,p,k;      //按鍵和掃描變量uchar  mod=0;          //模式:設(shè)置時間進入按鈕bit  bflash=0,clockdown=0;   //設(shè)置和鬧鈴標(biāo)志uchar   hour,minute,second,year,month,date;  //有關(guān)時間的變量寄存uchar  ss=1;//鬧鈴響的次數(shù)可以自己修改uchar  clock1[3]={0x06,0,0x01},clock2[3]={14,0,0x01};   //鬧鐘時間與開關(guān),默認開關(guān)開uint num=5000;     //設(shè)置自動返回主界面時間/////////////////////////////////void TimeInit()      //定時掃描初始化{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)閉T0BEEP = ~BEEP;          //輸出方波, 發(fā)音TH0 = t0h;               //下次的中斷時間, 這個時間, 控制音調(diào)高低TL0 = t0l;TR0 = 1;                     //啟動T0LEDIO=display[mod][i];LEDCHIP=selchip[i];if(i>=5)i=0;elsei++;}*//////////////////////////////////////////void TimeInt() interrupt 3   //定時掃描中斷{if(i==pos){if(bflash==1) //閃爍標(biāo)志;設(shè)置時間日期和鬧鈴{if(k++40){if(i==4)i=0;elsei=i+2;}  else{if(p++>40){p=0;k=0;}}}}LEDIO=display[mod][i];LEDCHIP=selchip[i];if(num==0)      //自動還回時間界面{mod=0;bflash=0;}elsenum--; if(i>=5)i=0;elsei++;TH1=0xfa;TL1=0xd8;}////////////////////////////////////////////////////////void TimeToBin()       //把時間變成2進制{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()      //把時間變?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è)置************************/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];       //第一個鬧鐘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];      //第一個鬧鐘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ù)跳動,釋放按鍵{if(key1=='*'){pos=0;        //返回首位方便設(shè)置if(!bflash)       //先進設(shè)置時間的界面mod=0;elsemod=(mod+1)%4;     //功能選擇bflash=1;     //進入時鐘設(shè)置標(biāo)志num=5000;      //若是沒有操作自動返回主界面}/////////////////////////////移位按鍵選擇設(shè)置的位置if((key1=='0')(bflash)){pos=(pos+2)%6;num=5000;}if((!bflash)(key1=='0'))      //一鍵關(guān)閉鬧鈴睡懶覺按鍵,下次又開鬧鈴{  clockdown=1;       }///////////////////////////// 時分秒設(shè)置,加按鍵,if((key1=='#')(bflash)){ num=5000;      //if(mod==0)       //時間設(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;elsedate=(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;       }///////////////////////////////////////////////確認鍵設(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         //切換時間和日期mod=(mod+1)%2;num=5000;          //自動返回時間界面}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;elseBEEP=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();      //斷電以后喚醒時鐘Init_Ds1302();while(1){Get_Ds1302(DataTime); //讀取時間TimerDis();   //段碼處理KeySet();    //掃描按鍵if(!bflash)   //如果沒有進入設(shè)置時間則正常顯示否則時間暫停{TimeToBin();}CLOCK();  //鬧鈴設(shè)置}}/*******************************************************************************************************************************/#ifndef  __H_#define  _DS1302_H_/*********************************************************************************/#includereg51.h>#includeintrins.h>#define uchar unsigned char#define uint unsigned intsbit 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ù)據(jù)地址 格式為: 秒 分 時 日 月 星期 年void  Get_Ds1302(uchar *str);    //讀當(dāng)前時間函數(shù)聲明void  Init_Ds1302();     //DS1302初始化函數(shù)聲明/********以下是寫一字節(jié)數(shù)據(jù)函數(shù)********/void Ds1302_Write_Byte(uchar ch){uchar n;EA=0;for(n=0;n8;n++){SCLK=0;             //寫時低電平改變數(shù)據(jù)if(ch0x01)IO=1;elseIO=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;n8;n++){SCLK=1;if(IO)temp|=0x80;elsetemp=0x7f;SCLK=0;             //產(chǎn)生下跳沿temp=temp>>1;}EA=1;return (temp);}/********寫DS1302函數(shù), 往DS1302的某個地址寫入數(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ù)********/void Set_Ds1302(uchar *str){uchar n,addr = 0x80;Write_Ds1302(0x8e,0x00);          //寫控制字,允許寫操作for(n=0;n7;n++){Write_Ds1302(addr,*str);addr=addr+2;str++;}Write_Ds1302(0x8e,0x80);          //寫保護,不允許寫}/********讀取當(dāng)前時間函數(shù)********/void Get_Ds1302(uchar *str){uchar n,addr = 0x81;for(n=0;n7;n++){str[n]=Read_Ds1302(addr);addr+=2;}}/************初始化時間********************/void Init_Ds1302(){RST=0;SCLK=0;RST=1;Write_Ds1302(0x80,0x00);  //寫秒寄存器Write_Ds1302(0x90,0xab);  //寫充電器Write_Ds1302(0x8e,0x80);  //寫保護控制字,禁止寫}///////////////////////////////////////#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ǎ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_/***************************************************/#includeintrins.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時鐘接口////////////////////////////////////////////////////////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;i8;i++){if(ch0x80)SDA=1;elseSDA=0;SCL=1;delay_iic(10);SCL=0;ch=ch1;}SDA=1;SCL=1;delay_iic(10);if(SDA==1)F0=0;elseF0=1;SCL=0;}///////////////////////////*  read 1 byte  *////////////////////////uchar read_byte(){uchar i;uchar r=0;SDA=1;for(i=0;i8;i++){r=r1;SCL=1;delay_iic(10);if(SDA==1)r++;SCL=0;}return r;}/***********************寫一個字節(jié)**************************bit  Write_Byte_iic(uchar addr,uchar ch){start_iic();  //產(chǎn)生起始信號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();      //停止信號return 1;}/********************讀一個字節(jié)***************************uchar Read_Byte_iic(uchar addr){ uchar ch;       start_iic();    //啟動IICwrite_byte(SLAVE);    //寫器件地址if(F0==0)return 0;write_byte(addr);    //寫讀取的地址if(F0==0)return 0;start_iic();   //再次產(chǎn)生起始信號,不能少write_byte(Rslave);  //送讀控制字if(F0==0)return 0;ch=read_byte();   //讀出指定單元的內(nèi)容nack_iic();    //非應(yīng)答信號stop_iic();    //停止IICreturn (ch); }************************************************************/////////////////////////////////////////////////////////////bit Read_Nbyte_iic(uchar slave,uint addr,uchar *str,uchar  numb){uchar i;start_iic();write_byte(slave);  //write  iic  addrif(F0==0)return 0;write_byte(addr);  //write  data   addrif(F0==0)return 0;start_iic();   //再次產(chǎn)生起始信號,不能少write_byte(Rslave);  //送讀控制字if(F0==0)return 0;for(i=0;inumb-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  addrif(F0==0)return 0;write_byte(addr);  //write  data   addrif(F0==0)return 0;for(i=0;inumb;i++)    //write data{write_byte(*str);if(F0==0)return 0;str++;}stop_iic();       //stop iicreturn(1);}/////////////////////////////////////////////////////////////////#endif


關(guān)鍵詞: DS1302 數(shù)碼管 電子鐘

評論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉