|
在本論壇看到的一個(gè)數(shù)碼管時(shí)鐘程序,稍作修改后,自己用洞洞板焊了一塊板子,用了兩個(gè)四位共陽(yáng)數(shù)碼管做的,取消了鎖存器,實(shí)現(xiàn)的功能完全正常,后來(lái)又加入了DS18B20測(cè)溫程序,溫度顯示也正常,時(shí)間顯示4秒多然后顯示溫度1秒的樣子,交替顯示,現(xiàn)在遇到的問(wèn)題是,在沒(méi)加溫度程序的時(shí)候,調(diào)整時(shí)間的時(shí)候時(shí)分秒年月日都會(huì)閃爍,并且調(diào)整加減的時(shí)候都實(shí)時(shí)顯示,現(xiàn)在加了溫度程序以后,按下調(diào)整鍵的時(shí)候,時(shí)分秒不會(huì)閃爍,按加減的時(shí)候,數(shù)據(jù)也不能實(shí)時(shí)變化,但是數(shù)據(jù)的加減在調(diào)整退出后是有變化的,只是沒(méi)能實(shí)時(shí)的顯示,而年月日的調(diào)整是正常的,就是說(shuō)調(diào)整的時(shí)候年月日會(huì)閃爍,且數(shù)據(jù)也是隨加減鍵實(shí)時(shí)變化的,下面是我的程序,大神幫我看看程序哪里有問(wèn)題?已經(jīng)折騰好幾天了,沒(méi)能解決
- #include <reg52.h> //頭文件
- #define uchar unsigned char //宏定義
- #define uint unsigned int //宏定義
- sbit TRST = P1^0; /* DS1302實(shí)時(shí)時(shí)鐘的復(fù)位/片選線(xiàn)引腳(第5腳RST低電平復(fù)位高電平時(shí)芯片正常工作)*/
- sbit TIO = P1^1; /* DS1302實(shí)時(shí)時(shí)鐘的數(shù)據(jù)輸入/輸出引腳(第6腳I/O)*/
- sbit SCLK = P1^2; /* DS1302實(shí)時(shí)時(shí)鐘的串行時(shí)鐘引腳(第7腳SCLK)*/
- sbit S2 = P1^3; //定義調(diào)整按鍵
- sbit S3 = P1^4; //定義減數(shù)據(jù)按鍵,正常走時(shí)情況下按下顯示年月日,延時(shí)6秒后轉(zhuǎn)回時(shí)間顯示
- sbit S4 = P1^5; //定義加數(shù)據(jù)按鍵
- sbit DQ = P1^6; //定義DS18B20的數(shù)據(jù)輸入/輸出口
- unsigned char code duan[]=
- {0xc0,0xf9,0xa4,0xb0,
- 0x99,0x92,0x82,0xf8,
- 0x80,0x90,0xbf,0xff,0x9c,0xc6}; //共陽(yáng)數(shù)碼管段選碼0-9
- /*****************************************************/
- /***********ds18b20子程序模塊*************************/
- /*****************************************************/
- unsigned char temp_value,temp1_value; //temp_value溫度值整數(shù)部分 temp1_value溫度值小數(shù)部分
- bit fg=1; //溫度正負(fù)標(biāo)志 1為正0為負(fù)
- /***********ds18b20延遲子函數(shù)(晶振12MHz )*******/
- void delay_18B20(unsigned int i)
- {
- while(i--);
- }
- /**********ds18b20初始化函數(shù)**********************/
- void Init_DS18B20(void)
- {
- unsigned char x=0;
- DQ = 1; //DQ復(fù)位,不要也行
- delay_18B20(8); //稍做延時(shí)
- DQ = 0; //單片機(jī)將DQ拉低
- delay_18B20(40); //精確延時(shí)維持至少480us當(dāng)總線(xiàn)停留在低電平超過(guò)480us,總線(xiàn)上所以器件都將被復(fù)位
- DQ = 1; //釋放總線(xiàn)即拉高總線(xiàn),產(chǎn)生復(fù)位脈沖后,微處理器釋放總線(xiàn),讓總線(xiàn)處于空閑狀態(tài)
- delay_18B20(7); //稍作延時(shí),釋放總線(xiàn)后,以便從機(jī)18b20通過(guò)拉低總線(xiàn)來(lái)指示其是否在線(xiàn)
- x=DQ; //稍做延時(shí)后 如果x=0則初始化成功 x=1則初始化失敗
- delay_18B20(10); //稍作延時(shí)
- }
- /***********ds18b20讀一個(gè)字節(jié)**************/
- unsigned char ReadOneChar(void)
- {
- unsigned char i=0;
- unsigned char dat = 0; //一定別忘了給初值
- for (i=8;i>0;i--) //讀取數(shù)據(jù)時(shí),數(shù)據(jù)以字節(jié)的最低有效位先從總線(xiàn)移出
- {
- DQ = 0; // 給脈沖信號(hào),單片機(jī)(微處理器)將DS18B20總線(xiàn)拉低
- dat>>=1;
- DQ = 1; // 給脈沖信號(hào),拉低總線(xiàn)后接著釋放總線(xiàn),讓從機(jī)18b20能夠接管總線(xiàn),輸出有效數(shù)據(jù)
- if(DQ)
- dat|=0x80;
- delay_18B20(4); //所有讀"時(shí)間隙"必須60~120us
- }
- return(dat); //返回一個(gè)字節(jié)的數(shù)據(jù)
- }
- /*************ds18b20寫(xiě)一個(gè)字節(jié)****************/
- void WriteOneChar(unsigned char dat)
- {
- unsigned char i=0;
- for (i=8; i>0; i--)
- {
- DQ = 0;
- DQ = dat&0x01;
- delay_18B20(5);
- DQ = 1;
- dat>>=1;
- }
- }
- /**************讀取ds18b20當(dāng)前溫度************/
- void ReadTemp(void)
- {
- unsigned char L=0;
- unsigned char H=0;
- unsigned char t=0;
- Init_DS18B20(); //ds18b20初始化
- WriteOneChar(0xCC); // 跳過(guò)讀序號(hào)列號(hào)的操作
- WriteOneChar(0x44); // 啟動(dòng)溫度轉(zhuǎn)換
- delay_18B20(100); // this message is wery important
- Init_DS18B20(); //ds18b20初始化
- WriteOneChar(0xCC); //跳過(guò)讀序號(hào)列號(hào)的操作
- WriteOneChar(0xBE); //讀取溫度寄存器等(共可讀9個(gè)寄存器) 前兩個(gè)就是溫度
- delay_18B20(50); //延時(shí)
- L=ReadOneChar(); //讀取溫度值低8位
- H=ReadOneChar(); //讀取溫度值高8位
- t=H&0xf8; //把讀取到的溫度值高8位跟11111000做與運(yùn)算判斷溫度正負(fù),若高5位全部為1即為負(fù)否則為正
- if(t)
- {
- fg=0; //給出溫度為負(fù)的標(biāo)志
- temp_value=H<<4;
- temp_value+=(L&0xf0)>>4;
- temp_value=~temp_value+1; //負(fù)溫度值整數(shù)部分-取反加1
- temp1_value=~L&0x0f; //負(fù)溫度值小數(shù)部分
- }
- else
- {
- temp_value=H<<4;
- temp_value+=(L&0xf0)>>4; //正溫度值整數(shù)部分
- temp1_value=L&0x0f; //正溫度值小數(shù)部分
- }
- }
- //*********************************************************************************************
- /*******************************時(shí)鐘芯片DS1302的數(shù)據(jù)時(shí)序子程序********************************/
- //*********************************************************************************************
- #include <intrins.h> //包含_nop_函數(shù)的頭文件
- #define sce timedate[1] //秒鐘寄存器1讀WRITE 0x80寫(xiě)READ 0x81(bit7CH是時(shí)鐘停止標(biāo)志位0是正常工作若為1說(shuō)明芯片掉電沒(méi)有備用電池未運(yùn)行剩下7位高3位是秒的十位,低4位是秒的個(gè)位)
- #define min timedate[2] //分鐘寄存器2讀WRITE 0x82寫(xiě)READ 0x83(bit7沒(méi)意義,剩下的7位高3位是分鐘的十位,低4位是分鐘的個(gè)位)
- #define hour timedate[3] //小時(shí)寄存器3讀WRITE 0x84寫(xiě)READ 0x85(bit7是1代表12小時(shí)制,0代表24小時(shí)制bit6固定是0,bit5在12小時(shí)制下0代表上午1代表下午在24小時(shí)制下和bit4一起代表了小時(shí)的十位低4位代表的是小時(shí)的個(gè)位)
- #define date timedate[4] //日期寄存器4讀WRITE 0x86寫(xiě)READ 0x87(高2位固定是0,bit5和bit4是日期的十位,低4位是日期的個(gè)位)
- #define month timedate[5] //月份寄存器5讀WRITE 0x88寫(xiě)READ 0x89(高3位固定是0 bit4是月的十位,低4位是月的個(gè)位)
- #define week timedate[6] //星期寄存器6讀WRITE 0x8a寫(xiě)READ 0x8b(高5位固定是0,低3位代表了星期)
- #define year timedate[7] //年份寄存器7讀WRITE 0x8c寫(xiě)READ 0x8d(高4位代表了年的十位,低4位代表了年的個(gè)位,這里特別注意,這里的00到99年指的是2000年到2099)
- //寄存器8讀WRITE 0x8e寫(xiě)READ 0x8f(bit7是一個(gè)保護(hù)位,如果這一位是1,那么是禁止給任何其他的寄存器或者那31個(gè)字節(jié)的RAM寫(xiě)數(shù)據(jù)的,因此在寫(xiě)數(shù)據(jù)之前,這一位必須先寫(xiě)成0,剩下7位都是0)
- unsigned char displaychar1[8]={0,1,2,3,4,5,6,7},a,ya,ja ; //a結(jié)尾的字符都用來(lái)專(zhuān)門(mén)延時(shí),a通用,ya日期延時(shí)程序用
- unsigned char commandchar[9]={0,0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e}; //與timedate對(duì)應(yīng),分別控制每個(gè)寄存器的寫(xiě),讀時(shí)數(shù)組+1,第8個(gè)數(shù)是控制寫(xiě)保護(hù)位
- unsigned char timedate[8],sdat,seta,b,fen,tz; //fen用來(lái)給分鐘計(jì)數(shù),tz用來(lái)計(jì)算分鐘數(shù)自動(dòng)補(bǔ)償差錯(cuò)
- unsigned char LD = 1; //************數(shù)碼管,亮度調(diào)節(jié),0最小,10最高,越亮越閃 因會(huì)影響開(kāi)始信號(hào)查詢(xún)時(shí)間,建議最高設(shè)置為3**************
- char m;
- bit s,s2,s3,s4,K,setbit,sk;
- /******************延時(shí)子程序***********************/
- void timeout(unsigned char a)
- {
- unsigned char b;
- for(;a>0;a--)
- for(b=10;b>0;b--);//本來(lái)b=114會(huì)閃爍
- }
- /*********延時(shí)5微秒子程序************/
- // void timeout5us()
- // {
- // _nop_();
- // }
- /**************寫(xiě)控制和一個(gè)字節(jié)***********************/
- void sendchar(unsigned char csdat,unsigned char sdat)
- {
- SCLK = 0; //串行時(shí)鐘置低//拉低SCLK,為脈沖上升沿寫(xiě)入數(shù)據(jù)做好準(zhǔn)備
- TRST = 1; //啟動(dòng)數(shù)據(jù)傳輸 打開(kāi)片選 DS1302實(shí)時(shí)時(shí)鐘的復(fù)位/片選線(xiàn)引腳(第5腳RST低電平復(fù)位高電平時(shí)芯片正常工作)
- for(a=0;a<8;a++) //連續(xù)寫(xiě)8個(gè)二進(jìn)制位數(shù)據(jù)
- {
- SCLK = 0;//確保寫(xiě)數(shù)據(jù)前SCLK被拉低
- TIO = (csdat%2);
- SCLK = 1;//上升沿寫(xiě)入數(shù)據(jù)
- csdat >>=1; //將csdat的各數(shù)據(jù)位右移1位,準(zhǔn)備寫(xiě)入下一個(gè)數(shù)據(jù)位
- }
- for(a=0;a<8;a++) //連續(xù)寫(xiě)8個(gè)二進(jìn)制位數(shù)據(jù)
- {
- SCLK = 0;//確保寫(xiě)數(shù)據(jù)前SCLK被拉低
- TIO = (sdat%2);
- SCLK = 1;//上升沿寫(xiě)入數(shù)據(jù)
- sdat >>=1;
- }
- SCLK = 0; //重新拉低SCLK,形成脈沖
- TRST = 0; //禁止數(shù)據(jù)傳遞 關(guān)閉片選 DS1302實(shí)時(shí)時(shí)鐘的復(fù)位/片選線(xiàn)引腳(第5腳RST低電平復(fù)位高電平時(shí)芯片正常工作)
- }
- /**************************讀一個(gè)字節(jié)**************************************************************/
- unsigned char receviechar(unsigned char crdat)
- {
- unsigned char rdat;
- TRST = 1; //打開(kāi)片選 DS1302實(shí)時(shí)時(shí)鐘的復(fù)位/片選線(xiàn)引腳(第5腳RST低電平復(fù)位高電平時(shí)芯片正常工作)
- //TRST = 1;
- for(a=0;a<8;a++)
- {
- SCLK = 0;
- TIO = (crdat%2);
- SCLK = 1;
- crdat >>=1;
- }
- for(a=0;a<8;a++)
- {
- SCLK = 1;
- rdat >>= 1;
- SCLK = 0;
-
- if(TIO)
- rdat = rdat|0x80;
- }
- SCLK = 0;
- TRST = 0;
- return rdat ; //返回讀出的rdat的值
- }
- /*************************讀取時(shí)分秒子程序**************************************/
- void readtime()
- {
- sendchar(0x8e,0); //去DS1302寫(xiě)保護(hù)
- hour = receviechar(0x85); //讀小時(shí)數(shù)據(jù)
- min = receviechar(0x83); //讀分鐘數(shù)據(jù)
- sce = receviechar(0x81); //讀秒針數(shù)據(jù)
- sendchar(0x8e,0x80); //DS1302加寫(xiě)保護(hù)
- }
- /************************讀取年月日子程序***************************************/
- void readyear()
- {
- sendchar(0x8e,0); //去DS1302寫(xiě)保護(hù)
- date = receviechar(0x87); //讀日期
- month = receviechar(0x89); //讀月份
- year = receviechar(0x8d); //讀年份
- sendchar(0x8e,0x80); //DS1302加寫(xiě)保護(hù)
- }
- /**********************鍵盤(pán)掃描子程序,用定時(shí)器延時(shí)******************************/
- bit jianpan(K)
- {
- if((!K)&TF0) //如果S2或S3或S4被按下且計(jì)時(shí)器0溢出
- {
- TF0 = 0; //定時(shí)器0溢出標(biāo)志清0(溢出時(shí)TF0被硬件置1,并且申請(qǐng)中斷,軟件查詢(xún)到該位置1后需用軟件清零)
- ja++;
- if(ja>=2)
- {
- TR0 = 0; //關(guān)閉定時(shí)器0,每次按下后都會(huì)關(guān)閉定時(shí)器,后面的程序會(huì)檢測(cè)松手,松開(kāi)按鍵后會(huì)重新打開(kāi)定時(shí)器,可以保護(hù)每次按下只起作用一次
- ja = 0;
- s = 1;
- }
- return s; //返回s的值給K
- }
- //return s; //返回s的值給K
- }
- //**********************************************設(shè)置時(shí)間日期子程序*******************************************/
- void settime()
- {
- setbit=1; //設(shè)置控制標(biāo)識(shí),進(jìn)本函數(shù)后先就讓標(biāo)識(shí)打開(kāi),在下面延時(shí)跳出前都會(huì)一直跳入設(shè)置功能函數(shù)
- if(TF1&(s2==s3==s4==0)) //沒(méi)有按鍵按下時(shí)用定時(shí)器1來(lái)延時(shí)跳出
- {
- TF1=0; //定時(shí)器1溢出標(biāo)志清0(溢出時(shí)TF1被硬件置1,并且申請(qǐng)中斷,軟件查詢(xún)到該位置1后需用軟件清零)
- seta ++;
- }
- if(!(s2==s3==s4==0)) //松手檢測(cè)
- seta = 0; //延時(shí)時(shí)間超過(guò)一定值,或者有按鍵被按下(注意!這個(gè)符號(hào))時(shí),時(shí)間會(huì)被延長(zhǎng)
- if(seta>=70) //延時(shí)
- {
- setbit=0; //關(guān)閉設(shè)置
- sdat = 0;
- }
- if(sk!=s2) //sk用來(lái)做s2的中間暫存數(shù)據(jù),用來(lái)用來(lái)識(shí)別S2是否變化過(guò)
- {
- sk = s2;
- if(s2)
- sdat ++; //每次進(jìn)行一次S2動(dòng)作時(shí)才自加一次sdat
- if(sdat ==6)sdat=7; //跳過(guò)星期,本程序不顯示星期
- }
- m = timedate[sdat]/16*10+timedate[sdat]%16; //m用10進(jìn)制存下以供寫(xiě)入DS1302
- if(s3) m--;
- switch (sdat) //每次進(jìn)入設(shè)置的對(duì)應(yīng)操作判斷
- {
- case 1:
- if(m==-1) //調(diào)整秒鐘
- m = 59;
- break;
-
- case 2:
- if(m==-1) //調(diào)整分鐘
- m = 59;
- break;
-
- case 3:
- if(m==-1) //調(diào)整小時(shí)
- m =23;
- break;
-
- case 4: //調(diào)整日期***因?yàn)樵路莶煌悦總(gè)月的天數(shù)是不同的
- if(timedate[5]==4|timedate[5]==6|timedate[5]==9|timedate[5]==11) //小月,
- {
- if(m<=0)
- m = 30;
- break; //4月6月9月和11月是小月份,只有30天,所以到了30后轉(zhuǎn)到1日
- }
- if(timedate[5]==2&(timedate[7]%4==0)) //閏年2月
- {
- if(m<=0)
- m=29;
- break; //閏年2月有29天
- }
- if(timedate[5]==2&(timedate[7]%4!=0)) //平年2月
- {
- if(m<=0)
- m=28;
- break; //平年2月只有28天
- }
- if(m<=0)
- m =31;
- break; //其它月分情況
- /********************************************************************************************************
- 怎么判斷一個(gè)年份是不是閏年:1:普通情況求閏年只需除以4可除盡即可 年/4余數(shù)為0
- 2:如果是100的倍數(shù)但不是400的倍數(shù),那就不是閏年了,即末兩位都是零的整除400才行
- 判斷閏年條件①:非整百年數(shù)除以4,無(wú)余為閏,有余為平;②整百年數(shù)除以400,無(wú)余為閏有余為平。
- *********************************************************************************************************/
- case 5: //調(diào)整月份
- if(m==0)
- m = 12;
- break;
-
- case 6:
- sdat++; //跳過(guò)星期本程序不顯示星期
- if(m<=0)
- m = 7;
- break;
-
- case 7: //調(diào)整年份17-99
- if(m<=16)
- m = 99;
- break;
-
- default : /****不在判斷范圍的進(jìn)行初始化處理*/
- sdat = 0; //S2按鍵計(jì)數(shù)清0
- sk = 0; //s2的中間暫存數(shù)據(jù)清0
- setbit = 0; //設(shè)置控制標(biāo)識(shí)清0
- s2 = 0; //s2=0是優(yōu)化點(diǎn),在按下S2后按鍵標(biāo)識(shí)不會(huì)清零,松手時(shí)程序已重復(fù)運(yùn)行了很多遍,所以會(huì)重新跳回設(shè)置的第一位.加本命令可以讓設(shè)置判斷失效,不進(jìn)設(shè)置頁(yè)。
- break;
- }
- if(s4) m++;
- switch (sdat) //每次進(jìn)入設(shè)置的對(duì)應(yīng)操作判斷
- {
- case 1: //調(diào)整秒鐘
- if(m>59)
- m = 0;
- break;
-
- case 2: //調(diào)整分鐘
- if(m>59)
- m = 0;
- break;
-
- case 3: //調(diào)整小時(shí)
- if(m>23)
- m = 0;
- break;
-
- case 4: //調(diào)整日期***因?yàn)樵路莶煌悦總(gè)月的天數(shù)是不同的
- if(timedate[5]==4|timedate[5]==6|timedate[5]==9|timedate[5]==11) //小月,
- {
- if(m>=31)
- m = 1;
- break;//4月6月9月和11月是小月份,只有30天,所以到了30后轉(zhuǎn)到1日
- }
- if(timedate[5]==2&(timedate[7]%4==0)) //閏年2月
- {
- if(m>=30)
- m = 1;
- break; //閏年2月有29天
- }
- if(timedate[5]==2&(timedate[7]%4!=0)) //平年2月
- {
- if(m>=29)
- m = 1;
- break; //平年2月只有28天
- }
- if(m>=32)
- m = 1;
- break; //其它月分情況
-
- case 5: //調(diào)整月份
- if(m>=13)
- m = 1;
- break;
-
- case 6:
- sdat++; //跳過(guò)星期本程序不顯示星期
- if(m>=8)
- m = 1;
- break;
-
- case 7: //調(diào)整年份17-99
- if(m>=100)
- m = 17;
- break;
-
- default : /****不在判斷范圍的進(jìn)行初始化處理*/
- sdat = 0; //S2按鍵計(jì)數(shù)清0
- sk = 0; //s2的中間暫存數(shù)據(jù)清0
- setbit = 0; //設(shè)置控制標(biāo)識(shí)清0
- s2 = 0; //s2=0是優(yōu)化點(diǎn),在按下S2后按鍵標(biāo)識(shí)不會(huì)清零,松手時(shí)程序已重復(fù)運(yùn)行了很多遍,所以會(huì)重新跳回設(shè)置的第一位.加本命令可以讓設(shè)置判斷失效,不進(jìn)設(shè)置頁(yè)。
- break;
- }
- if(setbit) //如果設(shè)置控制標(biāo)識(shí)setbit為1則說(shuō)明以上有成立的條件,需要發(fā)送修改數(shù)據(jù)
- {
- sendchar(0x8e,0); //去DS1302寫(xiě)保護(hù)
- sendchar(commandchar[sdat],m/10*16+m%10); //將改好的數(shù)據(jù)寫(xiě)入DS1302(sdat的值決定寫(xiě)時(shí)分秒或年月日星期,m的值轉(zhuǎn)換成BCD寫(xiě)入)
- sendchar(0x8e,0x80); //加寫(xiě)保護(hù)
-
- if(seta%5>2&seta<50) //設(shè)置延時(shí)操作期間控制閃爍時(shí)間
- timedate[sdat] = 0xbb; //顯示空,對(duì)應(yīng)段選的兩位11;0xbb/16=11,0xbb%16=11,而上面段選數(shù)組中第12個(gè)數(shù)是顯示空
- }
- }
- /***************************************************************************************
- 顯示子程序 兩個(gè)數(shù),分別記錄鍵值和重復(fù)碼個(gè)數(shù)
- *****************************************************************************************/
- void display()
- {
- P2 = 0x7f; //送位選數(shù)據(jù)0111 1111
- P0 = (displaychar1[0]); //送段選數(shù)據(jù)
- timeout(LD); //延時(shí)
- P0 =0xff; //消隱,很重要,不然會(huì)閃爍,共陰數(shù)碼管用P0=0x00
-
- P2 = 0xbf; //送位選數(shù)據(jù)1011 1111
- P0 = displaychar1[1];
- timeout(LD); //延時(shí)
- P0 =0xff;
-
- P2 = 0xdf; //送位選數(shù)據(jù)1101 1111
- P0 = displaychar1[2];
- timeout(LD);//延時(shí)
- P0 =0xff;
-
- P2 = 0xef; //送位選數(shù)據(jù)1110 1111
- P0 = displaychar1[3];
- timeout(LD); //延時(shí)
- P0 =0xff;
-
- P2 = 0xf7; //送位選數(shù)據(jù)1111 0111
- P0 = displaychar1[4];
- timeout(LD); //延時(shí)
- P0 =0xff;
-
- P2 = 0xfb; //送位選數(shù)據(jù)1111 1011
- P0 = displaychar1[5];
- timeout(LD); //延時(shí)
- P0 =0xff;
-
- P2 = 0xfd; //送位選數(shù)據(jù)1111 1101
- P0 = displaychar1[6];
- timeout(LD); //延時(shí)
- P0 =0xff;
-
- P2 = 0xfe; //送位選數(shù)據(jù)1111 1110
- P0 = displaychar1[7];
- timeout(LD); //延時(shí)
- P0 =0xff;
- }
- /************************************溫度顯示子程序*****************************************/
- DS18b20display()
- {
- if(fg==1) //溫度為正時(shí)顯示的數(shù)據(jù)
- {
- if((temp_value/100)>=1) //若溫度高于100度時(shí)--即溫度百位數(shù)大于或等于1的時(shí)候
- {
- displaychar1[0] = duan[11]; //不顯示
- displaychar1[1] = duan[temp_value/100]; //顯示溫度百位
- displaychar1[2] = duan[temp_value%100/10]; //顯示溫度十位
- displaychar1[3] = duan[temp_value%10]&0x7f; //顯示溫度個(gè)位和小數(shù)點(diǎn)
- displaychar1[4] = duan[temp1_value*625/1000%10];//顯示溫度小數(shù)點(diǎn)后第一位
- displaychar1[5] = duan[11]; //不顯示
- displaychar1[6] = duan[12]; //溫度顯示"0"
- displaychar1[7] = duan[13]; //溫度顯示"C"
- }
- if((temp_value%100/10)>=1&(temp_value/100)<1) //若溫度高于10度與溫度低于100度時(shí)--即溫度十位數(shù)大于或等于1并且溫度百位數(shù)小于1的時(shí)候
- {
- displaychar1[0] = duan[11]; //不顯示
- displaychar1[1] = duan[11]; //不顯示
- displaychar1[2] = duan[temp_value%100/10]; //顯示溫度十位
- displaychar1[3] = duan[temp_value%10]&0x7f; //顯示溫度個(gè)位和小數(shù)點(diǎn)
- displaychar1[4] = duan[temp1_value*625/1000%10];//顯示溫度小數(shù)點(diǎn)后第一位
- displaychar1[5] = duan[11]; //不顯示
- displaychar1[6] = duan[12]; //溫度顯示"0"
- displaychar1[7] = duan[13]; //溫度顯示"C"
- }
- if((temp_value%100/10)<1&(temp_value/100)<1) //若溫度低于10度時(shí)--即溫度十位數(shù)小于1并且百位數(shù)小于1的時(shí)候
- {
- displaychar1[0] = duan[11]; //不顯示
- displaychar1[1] = duan[11]; //不顯示
- displaychar1[2] = duan[temp_value%10]&0x7f; //顯示溫度個(gè)位和小數(shù)點(diǎn)
- displaychar1[3] = duan[temp1_value*625/1000%10];//顯示溫度小數(shù)點(diǎn)后第一位
- displaychar1[4] = duan[11]; //不顯示
- displaychar1[5] = duan[12]; //溫度顯示"0"
- displaychar1[6] = duan[13]; //溫度顯示"C"
- displaychar1[7] = duan[11]; //不顯示
- }
- }
- if(fg==0) //溫度為負(fù)時(shí)顯示的數(shù)據(jù)
- {
- if(((temp_value-1)%100/10)>=1) //如果為負(fù)10度以下時(shí)
- {
- displaychar1[0] = duan[11]; //不顯示
- displaychar1[1] = duan[10]; //顯示"-"
- displaychar1[2] = duan[(temp_value-1)%100/10]; //顯示負(fù)溫度十位
- displaychar1[3] = duan[(temp_value-1)%10]&0x7f; //顯示負(fù)溫度個(gè)位和小數(shù)點(diǎn)
- displaychar1[4] = duan[temp1_value*625/1000%10];//顯示負(fù)溫度小數(shù)點(diǎn)后第一位
- displaychar1[5] = duan[11]; //不顯示
- displaychar1[6] = duan[12]; //溫度顯示"0"
- displaychar1[7] = duan[13]; //溫度顯示"C"
-
- fg=1; //清負(fù)溫度標(biāo)志
- }
- else //負(fù)十度以上時(shí)
- {
- displaychar1[0] = duan[11]; //不顯示
- displaychar1[1] = duan[11]; //不顯示
- displaychar1[2] = duan[10]; //顯示"-"
- displaychar1[3] = duan[(temp_value-1)%10]&0x7f; //顯示負(fù)溫度個(gè)位和小數(shù)點(diǎn)
- displaychar1[4] = duan[temp1_value*625/1000%10];//顯示負(fù)溫度小數(shù)點(diǎn)后第一位
- displaychar1[5] = duan[11]; //不顯示
- displaychar1[6] = duan[12]; //溫度顯示"0"//小數(shù)點(diǎn)后第二位temp1_value*625/100%10
- displaychar1[7] = duan[13]; //溫度顯示"C" //小數(shù)點(diǎn)后第三位temp1_value*625/10%10
- fg=1; //清負(fù)溫度標(biāo)志
- }
- }//溫度為負(fù)時(shí)顯示的數(shù)據(jù)包含的大括號(hào)
- }//顯示溫度數(shù)據(jù)包含的大括號(hào)
- /***************************************主函數(shù)**************************************************/
- main()
- {
- SCLK = 0 ; /* DS1302實(shí)時(shí)時(shí)鐘的串行時(shí)鐘引腳(第7腳SCLK)*/
- TRST = 0 ; /* DS1302實(shí)時(shí)時(shí)鐘的復(fù)位/片選線(xiàn)引腳(第5腳RST低電平復(fù)位高電平時(shí)芯片正常工作)*///復(fù)位DS1302實(shí)時(shí)時(shí)鐘
- readtime(); //先讀一下時(shí)間然后再判斷自動(dòng)補(bǔ)償程序
- fen=min; //fen用來(lái)判斷min是否到了1分鐘
- if(S2==0) //上電檢測(cè) 如果調(diào)整鍵S2被按下就初始化1302 給初值是17年12月26日,16:30:00星期二
- { //這里是給系統(tǒng)送初始值的,使用的方法是斷電之后,按住S2調(diào)整鍵,然后上電,S2鍵按住1~3s,松開(kāi)即設(shè)置完成
- sendchar(0x8e,0); //去DS1302寫(xiě)保護(hù)
- sendchar(0x80,0x00); //寫(xiě)入秒數(shù)據(jù)00
- sendchar(0x82,0x30); //寫(xiě)入分?jǐn)?shù)據(jù)30
- sendchar(0x84,0x16); //寫(xiě)入小時(shí)數(shù)據(jù)16
- sendchar(0x8a,0x02); //寫(xiě)入星期數(shù)據(jù)2
- sendchar(0x86,0x26); //寫(xiě)入日期數(shù)據(jù)26
- sendchar(0x88,0x12); //寫(xiě)入月份數(shù)據(jù)12
- sendchar(0x8c,0x17); //寫(xiě)入年份數(shù)據(jù)17
- sendchar(0x8e,0x80); //DS1302加寫(xiě)保護(hù)
- }
- TMOD = 0x12; //設(shè)置定時(shí)器工作模式0001 0010(T1為方式1-16位定時(shí)器/計(jì)數(shù)器 T2為方式2-8位初值自動(dòng)重裝的8位定時(shí)器/計(jì)數(shù)器)
- TR1 = 1; //啟動(dòng)定時(shí)器/計(jì)數(shù)器1
- TR0 = 1; //啟動(dòng)定時(shí)器/計(jì)數(shù)器0
- while(1) //大循環(huán)
- {
- readtime(); //先讀一下時(shí)間然后再判斷自動(dòng)補(bǔ)償程序
- if(fen!=min) //如果fen不等于min證明過(guò)了1分鐘了
- {
- fen=min; //那么再讓fen等于min
- tz++; //tz自加1
- }
- if((tz==38)&(sce>=01)) //如果計(jì)時(shí)到了38分鐘和秒鐘過(guò)了1秒的時(shí)候
- {
- tz=0; //tz清零
- sendchar(0x8e,0); //去DS1302寫(xiě)保護(hù)
- sendchar(0x80,0x00); //秒清0--即減去1秒或者加1秒再這里修改
- sendchar(0x8e,0x80); //加寫(xiě)保護(hù)
- }
- if(!S2) //檢測(cè)設(shè)置按鍵S2是否按下
- s2 = jianpan(S2); //若S2被按下則掃描鍵盤(pán)掃描程序S2
- if(!S3) //檢測(cè)減數(shù)據(jù)按鍵S3是否被按下
- s3 = jianpan(S3); //若S3被按下則掃描鍵盤(pán)掃描程序S3
- if(!S4) //檢測(cè)加數(shù)據(jù)按鍵S4是否被按下
- s4 = jianpan(S4); //若S4被按下則掃描鍵盤(pán)掃描程序S4
- TRST = 0; /* DS1302實(shí)時(shí)時(shí)鐘的復(fù)位/片選線(xiàn)引腳(第5腳RST低電平復(fù)位高電平時(shí)芯片正常工作)*/
- /*以下是開(kāi)始年月日自動(dòng)歸零的問(wèn)題修改,問(wèn)題產(chǎn)生原因是開(kāi)始沒(méi)有加!setbit這個(gè)條件,程序在運(yùn)行到設(shè)置年月日時(shí)依然會(huì)進(jìn)
- 入下面這個(gè)判斷,然后再進(jìn)入設(shè)置,但是年月日在這里還沒(méi)有讀數(shù),所以這里的設(shè)置就會(huì)進(jìn)入M=0然后加或減,從而讓設(shè)置值
- 出現(xiàn)錯(cuò)誤
- */
- if((!ya&(!setbit)&(!s3))|(setbit&(sdat<4)))//如果S2沒(méi)有被按下且不在顯示年月日的延時(shí)范圍,而且設(shè)置標(biāo)識(shí)為0時(shí),或者在標(biāo)識(shí)為1但是設(shè)置值在123中時(shí),則正常顯示時(shí)間格式
- {
- readtime(); //先讀一下時(shí)間然后再判斷設(shè)置程序,這樣的主要目的是讓初m的值由1302決定。
- ReadTemp(); //讀取DS18B20當(dāng)前溫度
- if(s2|setbit) //按下S2或設(shè)置標(biāo)識(shí)打開(kāi)時(shí)會(huì)進(jìn)入本判斷
- {
- ya = 0; //進(jìn)設(shè)置后會(huì)關(guān)閉日期顯示延時(shí)
- settime(); //設(shè)置時(shí)間日期子程序
- }
- else //正常顯示時(shí)間和溫度
- {
- if((sce%5)!=0) //如果秒對(duì)5求余不等于0的時(shí)候顯示時(shí)間--即溫度和時(shí)間間歇顯示,時(shí)間顯示比溫度顯示長(zhǎng)
- {
- displaychar1[0] = duan[hour/16]; //正常顯示小時(shí)十位
- displaychar1[1] = duan[hour%16]; //正常顯示小時(shí)個(gè)位
- displaychar1[2] = duan[10]; //正常顯示"-"
- displaychar1[3] = duan[min/16]; //正常顯示分鐘十位
- displaychar1[4] = duan[min%16]; //正常顯示分鐘個(gè)位
- displaychar1[5] = duan[10]; //正常顯示"-"
- displaychar1[6] = duan[sce/16]; //正常顯示秒鐘十位
- displaychar1[7] = duan[sce%16]; //正常顯示秒鐘個(gè)位
- }
- else //否則顯示溫度
- {
- DS18b20display(); //溫度顯示子程序
- }
- }//正常顯示時(shí)間和溫度數(shù)據(jù)包含的大括號(hào)
- }//如果S2沒(méi)有被按下且不在顯示年月日的延時(shí)范圍,而且設(shè)置標(biāo)識(shí)為0時(shí),或者在標(biāo)識(shí)為1但是設(shè)置值在123中時(shí),則正常顯示時(shí)間格式包含的大括號(hào)
- if(((!setbit)&s3)|ya>0|(setbit&sdat>3))
- {
- if(TF1&!setbit) //如果定時(shí)器1計(jì)滿(mǎn)溢出或設(shè)置標(biāo)識(shí)打開(kāi)時(shí)會(huì)進(jìn)入本判斷
- {
- ya++; //非設(shè)置頁(yè)面才進(jìn)去日期延時(shí)
- TF1 = 0; //定時(shí)器1溢出標(biāo)志清0(溢出時(shí)TF1被硬件置1,并且申請(qǐng)中斷,軟件查詢(xún)到該位置1后需用軟件清零)
- }
- readyear(); //讀取年月日數(shù)據(jù)
- if(s2|setbit) //如果按下S2或設(shè)置標(biāo)識(shí)打開(kāi)時(shí)會(huì)進(jìn)入本判斷
- {
- ya = 0; //進(jìn)設(shè)置后會(huì)關(guān)閉日期顯示延時(shí)
- settime(); //設(shè)置時(shí)間日期子程序
- }
- displaychar1[0] = duan[2]; //顯示年月日 固定顯示2
- displaychar1[1] = duan[0]; //顯示年月日 固定顯示0
- displaychar1[2] = duan[year/16]; //顯示年份十位
- displaychar1[3] = duan[year%16]&0x7f; //顯示年份個(gè)位****&0x7f是讓這一位顯示出小數(shù)點(diǎn),共陰數(shù)碼管就是或0x80或者是+0x80
- displaychar1[4] = duan[month/16]; //顯示月份十位
- displaychar1[5] = duan[month%16]&0x7f; //顯示月份個(gè)位****&0x7f是讓這一位顯示出小數(shù)點(diǎn),共陰數(shù)碼管就是或0x80或者是+0x80
- displaychar1[6] = duan[date/16]; //顯示日期十位
- displaychar1[7] = duan[date%16]; //顯示日期個(gè)位
- if(ya>70) ya =0; //日期延時(shí)約6秒,大約時(shí)間,與計(jì)時(shí)器和程序的運(yùn)行有關(guān)
- }
- s3 = s4 =0;
- if(S2==S3==S4==1) //松手檢測(cè) 如果三個(gè)按鍵都沒(méi)有被按下
- {
- ja = 0;
- TR0 = 1; //啟動(dòng)定時(shí)器0
- s2= s3= s4= 0; //松開(kāi)按鍵后恢復(fù)計(jì)時(shí)器并清零按鍵值
- //s=0; //為快速跳時(shí),s清零放在松手檢測(cè)中,s3和s4在按下不放后會(huì)重復(fù)跳值,想要每次按下只起作用一次,請(qǐng)將s放在本循環(huán)外面這個(gè)循環(huán)后面
- } //
- s = 0;
- for(a=0; a<50;a++) //一個(gè)循環(huán)顯示50次數(shù)碼管
- display();
- }//while包含的大括號(hào)
- }
復(fù)制代碼
|
|