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