|
|
- /****************************************************************/
- /******名字:DS1302**********************************************/
- /******功能:驅(qū)動(dòng)DS1302時(shí)鐘芯片通過(guò)數(shù)碼管顯示時(shí)間,時(shí)間可調(diào)******/
- /******作者:WPM*************************************************/
- /******修改日期:2010年7月21日***********************************/
- /****************************************************************/
- /*這是本人在外編寫(xiě)的第一個(gè)程序,目的只有一個(gè),就是方便以后直接調(diào)用,
- 我要徹底改變我以往編寫(xiě)程序的風(fēng)格,為自己這份新工作做準(zhǔn)備*/
- #include <reg52.h>//頭文件
- #include <intrins.h>
- #define uchar unsigned char//宏定義
- #define uint unsigned int
- sbit DS1302_SCL2=P1^3; //DS1302_SCL2定義為P1口的第3位腳,連接DS1302SCL和ADC0831SCL腳
- sbit DS1302_SDA2=P1^4; //DS1302_SDA2定義為P1口的第4位腳,連接DS1302SCL和ADC0831SDA腳
- sbit DS1302_RST = P1^5; // DS1302片選腳
- sbit DS1302_SPK=P3^4; //定義蜂鳴器的引腳
- uchar DS1302_tmpdate[8]={0x00,0x06,0x03,0x18,0x0c,0x07,0x06,0};//秒分時(shí)日月星期年
- uchar DS1302_tmpdisplay[8]={0x40,0x40,0x40,0x40,0x40,0x40,0x40,0}; //顯示“-”
- code uchar write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};//寫(xiě)秒分時(shí)日月星期年的地址
- code uchar DS1302_Read_RTC_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; //讀取秒分時(shí)日月星期年的地址
- code uchar DS1302_table[]= //共陰數(shù)碼管 0-9 '-' '熄滅‘表
- {0x3f,0x06,0x5b,0x4f,0x66,0x6d,
- 0x7d,0x07,0x7f,0x6f,0x40,0x00};
- uchar code DS1302_key_tab[]=
- {0xed,0x7e,0x7d,0x7b,
- 0xbe,0xbd,0xbb,0xde,
- 0xdd,0xdb,0x77,0xb7,
- 0xee,0xd7,0xeb,0xe7};
- //========================此數(shù)組為鍵盤(pán)編碼,
- //本人采用類(lèi)式類(lèi)似電話(huà)按鍵的編碼方式,方便以后設(shè)計(jì)
- // 1 2 3 a 0x01 0x02 0x03 0x0a
- // 4 5 6 b 對(duì)應(yīng)16進(jìn)制碼: 0x04 0x05 0x06 0x0b
- // 7 8 9 e 0x07 0x08 0x09 0x0e
- // * 0 # f 0x0c 0x00 0x0e 0x0f
- //打個(gè)比方,如果你按下0鍵,P0口讀到數(shù)據(jù)為0xed
- //如果你按下2鍵,P0口讀到數(shù)據(jù)為0x7d,按下9鍵為0xdb,
- //我們將讀到的P0口數(shù)據(jù)經(jīng)過(guò)查表法就能得到相應(yīng)的16進(jìn)制碼
- //鍵盤(pán)的讀取,我們采用分時(shí)掃描
- void DS1302_delay();//延時(shí)子函數(shù),5個(gè)空指令
- void DS1302_display(uchar *lp,uchar lc);//數(shù)字的顯示函數(shù);lp為指向數(shù)組的地址,lc為顯示的個(gè)數(shù)
- void Write_Ds1302_byte(uchar temp);
- void Write_Ds1302( uchar address,uchar dat );
- uchar Read_Ds1302 ( uchar address );
- void DS1302_Read_RTC();//read RTC
- void DS1302_Set_RTC();//set RTC
- void Ds1302Play(uchar tmp);
- void Ds1302Menu();
- uchar DS1302_keyold,DS1302_key=0xff,DS1302_keytmp=0;
- /***************************************************/
- /******名字:main***********************************/
- /******功能:通過(guò)調(diào)用其它子函數(shù),達(dá)到對(duì)應(yīng)的功能*****/
- /******作者:WPM************************************/
- /******修改日期:2010年7月21日**********************/
- /***************************************************/
- void main() //入口函數(shù)
- {
- DS1302_RST=0;
- DS1302_Set_RTC();
- EA=1; //開(kāi)啟總中斷
- EX0=1; //開(kāi)啟外部中斷 0
- IT0=1; // 設(shè)置成 下降沿觸發(fā)方式
- while(1)
- {
- Ds1302Menu();
- }
- }
- /*************************************************/
- /******名字:DS1302_display***********************/
- /******功能:八個(gè)數(shù)碼管顯示的數(shù)值*****************/
- /******作者:WPM**********************************/
- /******修改日期:2010年7月21日********************/
- /*************************************************/
- void DS1302_display(uchar *lp,uchar lc)//顯示
- {
- uchar i; //定義變量
- P2=0; //端口2為輸出
- P1=P1&0xF8; //將P1口的前3位輸出0,對(duì)應(yīng)138譯門(mén)輸入腳,全0為第一位數(shù)碼管
- for(i=0;i<lc;i++) //循環(huán)顯示
- {
- P2=DS1302_table[lp[i]]; //查表法得到要顯示數(shù)字的數(shù)碼段
- DS1302_delay(); //延時(shí)
- P2=0; //清0端口,準(zhǔn)備顯示下位
- if(i==7) //檢測(cè)顯示完8位否,完成直接退出,不讓P1口再加1,否則進(jìn)位影響到第四位數(shù)據(jù)
- break;
- P1++; //下一位數(shù)碼管
- }
- }
- /*************************************************/
- /******名字:DS1302_delay*************************/
- /******功能:起到一個(gè)延時(shí)的作用,用于掃描數(shù)碼管***/
- /******作者:WPM**********************************/
- /******修改日期:2010年7月21日********************/
- /*************************************************/
- void DS1302_delay()
- {
- uchar i=10;
- while(i)
- i--;
- }
- /*************************************************/
- /******名字:Write_DS1302_Byte********************/
- /******功能:向DS1302芯片寫(xiě)入一個(gè)字節(jié)的數(shù)據(jù)********/
- /******作者:WPM**********************************/
- /******修改日期:2010年7月21日********************/
- /************************************************/
- void Write_Ds1302_Byte(uchar temp)
- {
- uchar i;
- for (i=0;i<8;i++) //循環(huán)8次 寫(xiě)入數(shù)據(jù)
- {
- DS1302_SCL2=0; //給一個(gè)上升沿脈沖,即可寫(xiě)入一個(gè)位
- DS1302_SDA2=temp&0x01; //每次傳輸?shù)妥止?jié)
- temp>>=1; //右移一位
- DS1302_SCL2=1;
- }
- }
- /*********************************************/
- /*********************************************/
- /******名字:Write_DS1302*********************/
- /******功能:向DS1302芯片寫(xiě)入數(shù)據(jù)**************/
- /******作者:WPM******************************/
- /******修改日期:2010年7月21日****************/
- /*********************************************/
- void Write_Ds1302( uchar address,uchar dat )
- {
- DS1302_RST=0;
- _nop_();
- DS1302_SCL2=0;
- _nop_();
- DS1302_RST=1;
- _nop_(); //啟動(dòng)
- Write_Ds1302_Byte(address); //發(fā)送地址
- Write_Ds1302_Byte(dat); //發(fā)送數(shù)據(jù)
- DS1302_RST=0; //恢復(fù)
- }
- /***********************************************/
- /***********************************************/
- /******名字:Read_DS1302************************/
- /******功能:讀取DS1302一個(gè)字節(jié)的數(shù)據(jù)************/
- /******作者:WPM********************************/
- /******修改日期:2010年7月21日******************/
- /***********************************************/
- uchar Read_Ds1302 ( uchar address )
- {
- uchar i,temp=0x00;
- DS1302_RST=0;
- _nop_();
- DS1302_SCL2=0;
- _nop_();
- DS1302_RST=1;
- _nop_();
- Write_Ds1302_Byte(address);
- for (i=0;i<8;i++) //循環(huán)8次 讀取數(shù)據(jù)
- {
- DS1302_SCL2=1;
- _nop_();
- if(DS1302_SDA2)
- temp|=0x80; //每次傳輸?shù)妥止?jié)
- DS1302_SCL2=0;
- temp>>=1; //右移一位
- }
- DS1302_RST=0;
- _nop_();
- DS1302_SCL2=1;
- DS1302_SDA2=0;
- return (temp); //返回
- }
- /*********************************************/
- /*********************************************/
- /******名字:Write_DS1302*********************/
- /******功能:向DS1302芯片讀取日歷**************/
- /******作者:WPM******************************/
- /******修改日期:2010年7月21日****************/
- /*********************************************/
- void DS1302_Read_RTC() //讀取 日歷
- {
- uchar i,*p;
- p=DS1302_Read_RTC_address; //地址傳遞
- for(i=0;i<7;i++) //分7次讀取 年月日時(shí)分秒星期
- {
- DS1302_tmpdate[i]=Read_Ds1302(*p);
- p++;
- }
- }
- /**********************************************/
- /**********************************************/
- /******名字:Write_DS1302**********************/
- /******功能: 設(shè)置DS1302芯片的日歷值************/
- /******作者:WPM*******************************/
- /******修改日期:2010年7月21日*****************/
- /**********************************************/
- void DS1302_Set_RTC() //設(shè)定 日歷
- {
- uchar i,*p,tmp; //DS1302的數(shù)據(jù)是以十進(jìn)制存儲(chǔ)的,要轉(zhuǎn)化為十六進(jìn)制顯示
- for(i=0;i<7;i++)
- {
- tmp=DS1302_tmpdate[i]/10;
- DS1302_tmpdate[i]=DS1302_tmpdate[i]%10;
- DS1302_tmpdate[i]=DS1302_tmpdate[i]+tmp*16;
- }
- Write_Ds1302(0x8E,0X00);//允許寫(xiě)入數(shù)據(jù)
-
- p=write_rtc_address; //傳地址
- for(i=0;i<7;i++) //7次寫(xiě)入 年月日時(shí)分秒星期
- {
- Write_Ds1302(*p,DS1302_tmpdate[i]);
- p++;
- }
- Write_Ds1302(0x8E,0x80);//禁止寫(xiě)入數(shù)據(jù)
- }
- /**********************************************/
- /**********************************************/
- /******名字:ReadKey***************************/
- /******功能:鍵盤(pán)掃描子函數(shù),讀取按下的按鍵值***/
- /******作者:WPM*******************************/
- /******修改日期:2010年7月21日*****************/
- /**********************************************/
- void ReadKey() //鍵盤(pán)掃描函數(shù),讀取鍵盤(pán)值
- {
- uchar i,j,key;
- j=0xfe;//賦初值
- key=0xff;//判斷按鍵是否按下的標(biāo)志
- for (i=0;i<4;i++) //掃描鍵盤(pán),判斷是否有按鍵按下
- {
- P0=j; //把J的值賦給P0口,用于下面判斷是否有按鍵按下
- if ((P0&0xf0)!=0xf0) //判斷是否有按鍵按下
- {
- key=P0; //有按鍵按下,讀取P0口的值,賦給KRY,保存該值
- break; //跳出,結(jié)束
- }
- j=_crol_(j,1); //左循環(huán)
- }
- if (key==0xff) //沒(méi)有按鍵,有抖動(dòng)等
- {
- DS1302_keytmp=0xff;
- P0=0xf0;
- EX0=1; //打開(kāi)外部中斷
- DS1302_SPK=1; //關(guān)閉蜂鳴器
- return; //返回
- }
- DS1302_SPK=0; //驅(qū)動(dòng)蜂鳴器
- if(DS1302_keytmp==key) //按鍵按下了,但沒(méi)有松手
- {
- TH0=0X2E;//給定時(shí)器賦初值
- TL0=0;
- TR0=1;//啟動(dòng)定時(shí)器
- return; //返回
- }
- TH0=0X2E;//給定時(shí)器賦初值
- TL0=0;
- TR0=1;//啟動(dòng)定時(shí)器
- DS1302_keytmp=key;//把讀取的值賦給l-keytmp
- for(i=0;i<17;i++)
- {
- if (key==DS1302_key_tab[i]) //通過(guò)對(duì)比代碼,判斷是那個(gè)按鍵按下
- {
- DS1302_key=i;//保存對(duì)比好的值,用于顯示??
- break; //跳出,結(jié)束
- }
- }
- }
- /*****************************************************************/
- /***************************************************** ***********/
- /******名字:Key_Scan*********************************************/
- /******功能:外部中斷0,用于有按鍵按下時(shí),掃描鍵盤(pán),讀取鍵盤(pán)值*****/
- /******作者:WPM**************************************************/
- /******修改日期:2010年7月21日************************************/
- /*****************************************************************/
- void Key_Scan() interrupt 0 //外部中斷 0 的優(yōu)先級(jí)最高
- {
- TMOD&=0XF1;//定時(shí)器工作在方式1,既TMOD=0x01
- TH0=0X00;//定時(shí)時(shí)間為:(65536-65536)/晶振頻率/12
- TL0=0X00;
- ET0=1; //開(kāi)分控
- TR0=1; //啟動(dòng)定時(shí)器
- }
- /*****************************************************************/
- /***************************************************** ***********/
- /******名字:Timer0_isr*******************************************/
- /******功能:定時(shí)器0,用于每隔一段時(shí)間掃描鍵盤(pán)*********************/
- /******作者:WPM**************************************************/
- /******修改日期:2010年7月21日************************************/
- /*****************************************************************/
- void Timer0_isr() interrupt 1 //定時(shí)器0中斷
- {
- TR0=0; //關(guān)閉定時(shí)器
- ReadKey(); //讀取鍵盤(pán)掃描值
- }
- /**************************************************/
- /**************************************************/
- /******名字:DS1302Menu****************************/
- /******功能:修改時(shí)鐘的時(shí)間*************************/
- /******作者:WPM***********************************/
- /******修改日期:2010年7月21日*********************/
- /**************************************************/
- void Ds1302Menu()//時(shí)鐘讀取,可修改,按A、B鍵更改顯示時(shí)間還是日
- //期,再按#鍵可對(duì)其做修改
- {
- uchar i,tmp,temp,oldtimer=0;
- tmp=0;
- while (1)
- {
- DS1302_Read_RTC();
- if(tmp==0) //用于區(qū)別是否按下了B鍵
- {
- DS1302_tmpdisplay[0]=DS1302_tmpdate[2]/16; //十六進(jìn)制轉(zhuǎn)化為十進(jìn)制顯示,顯示時(shí)
- DS1302_tmpdisplay[1]=DS1302_tmpdate[2]&0x0f; //顯示個(gè)位
- DS1302_tmpdisplay[2]=10; //顯示‘-’
- DS1302_tmpdisplay[3]=DS1302_tmpdate[1]/16; //顯示分的十位
- DS1302_tmpdisplay[4]=DS1302_tmpdate[1]&0x0f;//顯示分的個(gè)位
- DS1302_tmpdisplay[5]=10; //顯示‘-’
- DS1302_tmpdisplay[6]=DS1302_tmpdate[0]/16; //顯示秒的十位
- DS1302_tmpdisplay[7]=DS1302_tmpdate[0]&0x0f;//顯示秒的個(gè)位
- }
- if((tmp==0)&&(oldtimer!=DS1302_tmpdate[0])) //tmp作為標(biāo)志位,與秒作比較,
- //判斷數(shù)據(jù)是否修改,修改時(shí)分秒
- {
- oldtimer=DS1302_tmpdate[0]; //暫存該值,用于比較
- DS1302_tmpdisplay[0]=DS1302_tmpdate[2]/16; //十六進(jìn)制轉(zhuǎn)化為十進(jìn)制顯示,顯示時(shí)
- DS1302_tmpdisplay[1]=DS1302_tmpdate[2]&0x0f; //顯示個(gè)位
- DS1302_tmpdisplay[2]=10; //顯示‘-’
- DS1302_tmpdisplay[3]=DS1302_tmpdate[1]/16; //顯示分的十位
- DS1302_tmpdisplay[4]=DS1302_tmpdate[1]&0x0f;//顯示分的個(gè)位
- DS1302_tmpdisplay[5]=10; //顯示‘-’
- DS1302_tmpdisplay[6]=DS1302_tmpdate[0]/16; //顯示秒的十位
- DS1302_tmpdisplay[7]=DS1302_tmpdate[0]&0x0f;//顯示秒的個(gè)位
- }
- if((tmp==1)&&(oldtimer!=DS1302_tmpdate[3]))//tmp作為標(biāo)志位,與日作比較
- //判斷數(shù)據(jù)是否修改,修改年月日
- {
- oldtimer=DS1302_tmpdate[3];//暫存該值,用于比較
- DS1302_tmpdisplay[0]=DS1302_tmpdate[6]/16; //改為十進(jìn)制顯示,顯示年的十位
- DS1302_tmpdisplay[1]=DS1302_tmpdate[6]&0x0f;//顯示年的個(gè)位,
- DS1302_tmpdisplay[2]=10; //顯示‘-’
- DS1302_tmpdisplay[3]=DS1302_tmpdate[4]/16;//顯示月的十位
- DS1302_tmpdisplay[4]=DS1302_tmpdate[4]&0x0f;//顯示月的個(gè)位
- DS1302_tmpdisplay[5]=10; //顯示‘-’
- DS1302_tmpdisplay[6]=DS1302_tmpdate[3]/16; //顯示日的十位
- DS1302_tmpdisplay[7]=DS1302_tmpdate[3]&0x0f; //顯示日的個(gè)位
- }
- DS1302_display(DS1302_tmpdisplay,8);//顯示時(shí)分秒,年月日
- DS1302_display(DS1302_tmpdisplay,8); //增加亮度
- DS1302_display(DS1302_tmpdisplay,8);
- DS1302_display(DS1302_tmpdisplay,8);
- ReadKey(); //讀取按下的按鍵值
- if(DS1302_key==0x0c)
- {
- DS1302_key=0xff;//退出鍵按下了,結(jié)果退出
- break;
- }
- if(DS1302_key==0x0e) //確定鍵按下了
- {
- DS1302_key=0xff;
- for(i=0;i<7;i++) //保存當(dāng)前的時(shí)間,用于作比較,判斷是否修改了時(shí)間
- {
- temp=DS1302_tmpdate[i]/16; //數(shù)據(jù)處理,在前程序講過(guò),時(shí)鐘I
- //C它是以十進(jìn)制對(duì)數(shù)據(jù)存儲(chǔ),所以要將它轉(zhuǎn)為十進(jìn)制
- DS1302_tmpdate[i]=DS1302_tmpdate[i]%16;
- DS1302_tmpdate[i]=temp*10+DS1302_tmpdate[i];
- }
- while(1)
- {
- if(DS1302_key==0x0c)
- {
- DS1302_key=0xff;
- break;
- }
- if(DS1302_key==0x0e)
- { //按#鍵對(duì)修改的數(shù)據(jù)進(jìn)行寫(xiě)入時(shí)鐘IC1302
- DS1302_key=0xff;
- DS1302_Set_RTC();
- break;
- }
- switch(DS1302_key)
- {
- case 0x01: //按1鍵對(duì)小時(shí),或年的加1
- DS1302_key=0xff;
- if(tmp==0)
- {
- if(DS1302_tmpdate[2]<23)
- DS1302_tmpdate[2]++;
- }
- else
- {
- if(DS1302_tmpdate[6]<99)
- DS1302_tmpdate[6]++;
- }
- break;
- case 0x02: //按2鍵對(duì)分鐘,或月的加1
- DS1302_key=0xff;
- if(tmp==0)
- {
- if(DS1302_tmpdate[1]<59) //對(duì)分進(jìn)行修改,判斷分是否小于59
- DS1302_tmpdate[1]++; //是,則加1
- }
- else //其他情況對(duì)月進(jìn)行修改
- {
- if(DS1302_tmpdate[4]<12)
- DS1302_tmpdate[4]++;
- }
- break;
- case 0x03: //按3鍵對(duì)秒,或日的加1
- DS1302_key=0xff;
- if(tmp==0)
- {
- if(DS1302_tmpdate[0]<59)
- DS1302_tmpdate[0]++;
- }
- else
- {
- if(DS1302_tmpdate[3]<31)
- DS1302_tmpdate[3]++;
- }
- break;
- case 0x04: //按4鍵對(duì)小時(shí),或年的減1
- DS1302_key=0xff;
- if(tmp==0)
- {
- if(DS1302_tmpdate[2]>0)
- DS1302_tmpdate[2]--;
- }
- else
- {
- if(DS1302_tmpdate[6]>0)
- DS1302_tmpdate[6]--;
- }
- break;
- case 0x05: //按5鍵對(duì)分鐘,或月的減1
- DS1302_key=0xff;
- if(tmp==0)
- {
- if(DS1302_tmpdate[1]>0)
- DS1302_tmpdate[1]--;
- }
- else
- {
- if(DS1302_tmpdate[4]>0)
- DS1302_tmpdate[4]--;
- }
- break;
- case 0x06: //按6鍵對(duì)秒,或日的減1
- DS1302_key=0xff;
- if(tmp==0)
- {
- if(DS1302_tmpdate[0]>0)
- DS1302_tmpdate[0]--;
- }
- else
- {
- if(DS1302_tmpdate[3]>0)
- DS1302_tmpdate[3]--;
- }
- break;
- }
- Ds1302Play(tmp);
- }
- }
- if(DS1302_key==0x0a) //判斷是否按鍵A按下
- {
- DS1302_key=0xff;
- tmp=0; //置標(biāo)志位
- }
- if(DS1302_key==0x0b)
- {
- DS1302_key=0xff;
- tmp=1;
- }
- }
- }
- /**************************************************/
- /**************************************************/
- /******名字:DS1302Play****************************/
- /******功能:用于判斷顯示時(shí)分秒還是年月日***********/
- /******作者:WPM***********************************/
- /******修改日期:2010年7月21日*********************/
- /**************************************************/
- void Ds1302Play(uchar tmp)
- {
- if(tmp==0) //用于顯示時(shí)分秒
- {
- DS1302_tmpdisplay[0]=DS1302_tmpdate[2]/10;
- DS1302_tmpdisplay[1]=DS1302_tmpdate[2]%10;
- DS1302_tmpdisplay[2]=10;
- DS1302_tmpdisplay[3]=DS1302_tmpdate[1]/10;
- DS1302_tmpdisplay[4]=DS1302_tmpdate[1]%10;
- DS1302_tmpdisplay[5]=10;
- DS1302_tmpdisplay[6]=DS1302_tmpdate[0]/10;
- DS1302_tmpdisplay[7]=DS1302_tmpdate[0]%10;
- }
- else //其他情況顯示日月年
- {
- DS1302_tmpdisplay[0]=DS1302_tmpdate[6]/10;
- DS1302_tmpdisplay[1]=DS1302_tmpdate[6]%10;
- DS1302_tmpdisplay[2]=10;
- DS1302_tmpdisplay[3]=DS1302_tmpdate[4]/10;
- DS1302_tmpdisplay[4]=DS1302_tmpdate[4]%10;
- DS1302_tmpdisplay[5]=10;
- DS1302_tmpdisplay[6]=DS1302_tmpdate[3]/10;
- DS1302_tmpdisplay[7]=DS1302_tmpdate[3]%10;
- }
- DS1302_display(DS1302_tmpdisplay,8);
- }
復(fù)制代碼
|
|