找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 3771|回復(fù): 6
打印 上一主題 下一主題
收起左側(cè)

自己用洞洞板焊的單片機(jī)數(shù)碼管時(shí)鐘程序有問(wèn)題

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:46220 發(fā)表于 2018-1-16 13:00 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
在本論壇看到的一個(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)能解決

  1. #include <reg52.h>                                //頭文件
  2. #define uchar unsigned char                //宏定義
  3. #define uint unsigned  int                //宏定義

  4. sbit TRST = P1^0;        /* DS1302實(shí)時(shí)時(shí)鐘的復(fù)位/片選線(xiàn)引腳(第5腳RST低電平復(fù)位高電平時(shí)芯片正常工作)*/
  5. sbit TIO  = P1^1;        /* DS1302實(shí)時(shí)時(shí)鐘的數(shù)據(jù)輸入/輸出引腳(第6腳I/O)*/
  6. sbit SCLK = P1^2;        /* DS1302實(shí)時(shí)時(shí)鐘的串行時(shí)鐘引腳(第7腳SCLK)*/
  7. sbit S2 = P1^3;                //定義調(diào)整按鍵
  8. sbit S3 = P1^4;                //定義減數(shù)據(jù)按鍵,正常走時(shí)情況下按下顯示年月日,延時(shí)6秒后轉(zhuǎn)回時(shí)間顯示
  9. sbit S4 = P1^5;                //定義加數(shù)據(jù)按鍵
  10. sbit  DQ = P1^6;         //定義DS18B20的數(shù)據(jù)輸入/輸出口

  11. unsigned char code duan[]=
  12. {0xc0,0xf9,0xa4,0xb0,
  13. 0x99,0x92,0x82,0xf8,
  14. 0x80,0x90,0xbf,0xff,0x9c,0xc6};           //共陽(yáng)數(shù)碼管段選碼0-9     
  15. /*****************************************************/
  16. /***********ds18b20子程序模塊*************************/
  17. /*****************************************************/                  
  18. unsigned char temp_value,temp1_value;      //temp_value溫度值整數(shù)部分 temp1_value溫度值小數(shù)部分
  19. bit  fg=1;        //溫度正負(fù)標(biāo)志  1為正0為負(fù)
  20. /***********ds18b20延遲子函數(shù)(晶振12MHz )*******/
  21. void delay_18B20(unsigned int i)
  22. {
  23.         while(i--);
  24. }
  25. /**********ds18b20初始化函數(shù)**********************/
  26. void Init_DS18B20(void)
  27. {
  28.          unsigned char x=0;
  29.          DQ = 1;          //DQ復(fù)位,不要也行
  30.          delay_18B20(8);  //稍做延時(shí)
  31.          DQ = 0;          //單片機(jī)將DQ拉低
  32.          delay_18B20(40); //精確延時(shí)維持至少480us當(dāng)總線(xiàn)停留在低電平超過(guò)480us,總線(xiàn)上所以器件都將被復(fù)位
  33.          DQ = 1;          //釋放總線(xiàn)即拉高總線(xiàn),產(chǎn)生復(fù)位脈沖后,微處理器釋放總線(xiàn),讓總線(xiàn)處于空閑狀態(tài)
  34.          delay_18B20(7);        //稍作延時(shí),釋放總線(xiàn)后,以便從機(jī)18b20通過(guò)拉低總線(xiàn)來(lái)指示其是否在線(xiàn)
  35.          x=DQ;            //稍做延時(shí)后 如果x=0則初始化成功 x=1則初始化失敗
  36.          delay_18B20(10);        //稍作延時(shí)
  37. }
  38. /***********ds18b20讀一個(gè)字節(jié)**************/  
  39. unsigned char ReadOneChar(void)
  40. {
  41.         unsigned char i=0;
  42.         unsigned char dat = 0;        //一定別忘了給初值
  43.         for (i=8;i>0;i--)        //讀取數(shù)據(jù)時(shí),數(shù)據(jù)以字節(jié)的最低有效位先從總線(xiàn)移出
  44.          {
  45.                   DQ = 0; // 給脈沖信號(hào),單片機(jī)(微處理器)將DS18B20總線(xiàn)拉低
  46.                   dat>>=1;
  47.                   DQ = 1; // 給脈沖信號(hào),拉低總線(xiàn)后接著釋放總線(xiàn),讓從機(jī)18b20能夠接管總線(xiàn),輸出有效數(shù)據(jù)
  48.                   if(DQ)
  49.                   dat|=0x80;
  50.                   delay_18B20(4);        //所有讀"時(shí)間隙"必須60~120us
  51.          }
  52.         return(dat);        //返回一個(gè)字節(jié)的數(shù)據(jù)
  53. }
  54. /*************ds18b20寫(xiě)一個(gè)字節(jié)****************/  
  55. void WriteOneChar(unsigned char dat)
  56. {
  57.         unsigned char i=0;
  58.         for (i=8; i>0; i--)
  59.         {
  60.                   DQ = 0;
  61.                 DQ = dat&0x01;
  62.             delay_18B20(5);
  63.                 DQ = 1;
  64.             dat>>=1;
  65.         }
  66. }
  67. /**************讀取ds18b20當(dāng)前溫度************/
  68. void ReadTemp(void)
  69. {
  70.         unsigned char L=0;
  71.         unsigned char H=0;
  72.         unsigned char t=0;
  73.         Init_DS18B20();                        //ds18b20初始化
  74.         WriteOneChar(0xCC);            // 跳過(guò)讀序號(hào)列號(hào)的操作
  75.         WriteOneChar(0x44);         // 啟動(dòng)溫度轉(zhuǎn)換
  76.         delay_18B20(100);       // this message is wery important
  77.         Init_DS18B20();                        //ds18b20初始化
  78.         WriteOneChar(0xCC);         //跳過(guò)讀序號(hào)列號(hào)的操作
  79.         WriteOneChar(0xBE);         //讀取溫度寄存器等(共可讀9個(gè)寄存器) 前兩個(gè)就是溫度
  80.         delay_18B20(50);                //延時(shí)
  81.         L=ReadOneChar();            //讀取溫度值低8位
  82.         H=ReadOneChar();                   //讀取溫度值高8位
  83.         t=H&0xf8;                //把讀取到的溫度值高8位跟11111000做與運(yùn)算判斷溫度正負(fù),若高5位全部為1即為負(fù)否則為正
  84.         if(t)
  85.         {
  86.           fg=0;                //給出溫度為負(fù)的標(biāo)志
  87.             temp_value=H<<4;
  88.           temp_value+=(L&0xf0)>>4;  
  89.           temp_value=~temp_value+1;        //負(fù)溫度值整數(shù)部分-取反加1
  90.           temp1_value=~L&0x0f;                //負(fù)溫度值小數(shù)部分
  91.         }
  92.         else
  93.         {  
  94.         temp_value=H<<4;
  95.         temp_value+=(L&0xf0)>>4; //正溫度值整數(shù)部分
  96.                 temp1_value=L&0x0f;                //正溫度值小數(shù)部分            
  97.     }
  98. }
  99. //*********************************************************************************************
  100. /*******************************時(shí)鐘芯片DS1302的數(shù)據(jù)時(shí)序子程序********************************/
  101. //*********************************************************************************************
  102. #include <intrins.h>                        //包含_nop_函數(shù)的頭文件
  103. #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è)位)
  104. #define min   timedate[2]        //分鐘寄存器2讀WRITE 0x82寫(xiě)READ 0x83(bit7沒(méi)意義,剩下的7位高3位是分鐘的十位,低4位是分鐘的個(gè)位)
  105. #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è)位)
  106. #define date  timedate[4]        //日期寄存器4讀WRITE 0x86寫(xiě)READ 0x87(高2位固定是0,bit5和bit4是日期的十位,低4位是日期的個(gè)位)
  107. #define month timedate[5]        //月份寄存器5讀WRITE 0x88寫(xiě)READ 0x89(高3位固定是0 bit4是月的十位,低4位是月的個(gè)位)
  108. #define week  timedate[6]        //星期寄存器6讀WRITE 0x8a寫(xiě)READ 0x8b(高5位固定是0,低3位代表了星期)
  109. #define year  timedate[7]        //年份寄存器7讀WRITE 0x8c寫(xiě)READ 0x8d(高4位代表了年的十位,低4位代表了年的個(gè)位,這里特別注意,這里的00到99年指的是2000年到2099)
  110.                                                         //寄存器8讀WRITE 0x8e寫(xiě)READ 0x8f(bit7是一個(gè)保護(hù)位,如果這一位是1,那么是禁止給任何其他的寄存器或者那31個(gè)字節(jié)的RAM寫(xiě)數(shù)據(jù)的,因此在寫(xiě)數(shù)據(jù)之前,這一位必須先寫(xiě)成0,剩下7位都是0)
  111. 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í)程序用
  112. 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ù)位
  113. unsigned char timedate[8],sdat,seta,b,fen,tz;        //fen用來(lái)給分鐘計(jì)數(shù),tz用來(lái)計(jì)算分鐘數(shù)自動(dòng)補(bǔ)償差錯(cuò)
  114. unsigned char LD = 1;      //************數(shù)碼管,亮度調(diào)節(jié),0最小,10最高,越亮越閃 因會(huì)影響開(kāi)始信號(hào)查詢(xún)時(shí)間,建議最高設(shè)置為3**************
  115. char m;
  116. bit s,s2,s3,s4,K,setbit,sk;
  117. /******************延時(shí)子程序***********************/
  118. void timeout(unsigned char a)      
  119.         {
  120.            unsigned char b;
  121.            for(;a>0;a--)
  122.               for(b=10;b>0;b--);//本來(lái)b=114會(huì)閃爍
  123.         }
  124.                   /*********延時(shí)5微秒子程序************/
  125. //        void timeout5us()      
  126. //                {
  127. //                    _nop_();
  128. //                }
  129. /**************寫(xiě)控制和一個(gè)字節(jié)***********************/
  130. void sendchar(unsigned char csdat,unsigned char sdat)
  131.         {
  132.                 SCLK = 0;                //串行時(shí)鐘置低//拉低SCLK,為脈沖上升沿寫(xiě)入數(shù)據(jù)做好準(zhǔn)備
  133.                 TRST = 1;                //啟動(dòng)數(shù)據(jù)傳輸 打開(kāi)片選 DS1302實(shí)時(shí)時(shí)鐘的復(fù)位/片選線(xiàn)引腳(第5腳RST低電平復(fù)位高電平時(shí)芯片正常工作)
  134.                 for(a=0;a<8;a++)        //連續(xù)寫(xiě)8個(gè)二進(jìn)制位數(shù)據(jù)
  135.                 {                                   
  136.                         SCLK = 0;//確保寫(xiě)數(shù)據(jù)前SCLK被拉低
  137.                         TIO  = (csdat%2);
  138.                         SCLK = 1;//上升沿寫(xiě)入數(shù)據(jù)
  139.                         csdat >>=1; //將csdat的各數(shù)據(jù)位右移1位,準(zhǔn)備寫(xiě)入下一個(gè)數(shù)據(jù)位
  140.                 }
  141.                 for(a=0;a<8;a++)        //連續(xù)寫(xiě)8個(gè)二進(jìn)制位數(shù)據(jù)
  142.                 {                                   
  143.                         SCLK = 0;//確保寫(xiě)數(shù)據(jù)前SCLK被拉低
  144.                         TIO  = (sdat%2);
  145.                         SCLK = 1;//上升沿寫(xiě)入數(shù)據(jù)
  146.                         sdat >>=1;
  147.                 }
  148.                 SCLK = 0;        //重新拉低SCLK,形成脈沖
  149.                 TRST = 0;        //禁止數(shù)據(jù)傳遞 關(guān)閉片選 DS1302實(shí)時(shí)時(shí)鐘的復(fù)位/片選線(xiàn)引腳(第5腳RST低電平復(fù)位高電平時(shí)芯片正常工作)      
  150.         }
  151. /**************************讀一個(gè)字節(jié)**************************************************************/
  152. unsigned char receviechar(unsigned char crdat)
  153.         {                        
  154.                 unsigned char rdat;
  155.                 TRST = 1;       //打開(kāi)片選 DS1302實(shí)時(shí)時(shí)鐘的復(fù)位/片選線(xiàn)引腳(第5腳RST低電平復(fù)位高電平時(shí)芯片正常工作)
  156.                 //TRST = 1;
  157.                 for(a=0;a<8;a++)
  158.                 {                                   
  159.                         SCLK = 0;
  160.                         TIO  = (crdat%2);
  161.                         SCLK = 1;
  162.                         crdat >>=1;
  163.                 }
  164.                 for(a=0;a<8;a++)
  165.                 {
  166.                         SCLK =   1;
  167.                         rdat >>= 1;
  168.                         SCLK =   0;
  169.                
  170.                         if(TIO)
  171.                         rdat = rdat|0x80;
  172.                 }
  173.                 SCLK = 0;
  174.             TRST = 0;        
  175.                 return rdat ; //返回讀出的rdat的值
  176.         }
  177. /*************************讀取時(shí)分秒子程序**************************************/
  178. void readtime()
  179.         {                                   
  180.             sendchar(0x8e,0);                        //去DS1302寫(xiě)保護(hù)
  181.             hour = receviechar(0x85);         //讀小時(shí)數(shù)據(jù)
  182.             min  = receviechar(0x83);         //讀分鐘數(shù)據(jù)
  183.             sce  = receviechar(0x81);        //讀秒針數(shù)據(jù)
  184.             sendchar(0x8e,0x80);        //DS1302加寫(xiě)保護(hù)               
  185.         }
  186. /************************讀取年月日子程序***************************************/
  187. void readyear()
  188.         {                                   
  189.             sendchar(0x8e,0);                        //去DS1302寫(xiě)保護(hù)
  190.             date = receviechar(0x87);         //讀日期
  191.             month  = receviechar(0x89);        //讀月份
  192.             year  = receviechar(0x8d);        //讀年份
  193.             sendchar(0x8e,0x80);         //DS1302加寫(xiě)保護(hù)                        
  194.         }
  195. /**********************鍵盤(pán)掃描子程序,用定時(shí)器延時(shí)******************************/
  196. bit jianpan(K)
  197.         {
  198.             if((!K)&TF0)    //如果S2或S3或S4被按下且計(jì)時(shí)器0溢出
  199.             {
  200.                  TF0 = 0;        //定時(shí)器0溢出標(biāo)志清0(溢出時(shí)TF0被硬件置1,并且申請(qǐng)中斷,軟件查詢(xún)到該位置1后需用軟件清零)
  201.                  ja++;         
  202.                  if(ja>=2)
  203.                  {
  204.                     TR0 = 0; //關(guān)閉定時(shí)器0,每次按下后都會(huì)關(guān)閉定時(shí)器,后面的程序會(huì)檢測(cè)松手,松開(kāi)按鍵后會(huì)重新打開(kāi)定時(shí)器,可以保護(hù)每次按下只起作用一次
  205.                     ja = 0;                                
  206.                     s = 1;
  207.                  }
  208.                  return s;        //返回s的值給K
  209.             }
  210.              //return s;        //返回s的值給K
  211.         }
  212. //**********************************************設(shè)置時(shí)間日期子程序*******************************************/
  213. void settime()
  214. {        
  215.         setbit=1;                //設(shè)置控制標(biāo)識(shí),進(jìn)本函數(shù)后先就讓標(biāo)識(shí)打開(kāi),在下面延時(shí)跳出前都會(huì)一直跳入設(shè)置功能函數(shù)
  216.         if(TF1&(s2==s3==s4==0))  //沒(méi)有按鍵按下時(shí)用定時(shí)器1來(lái)延時(shí)跳出
  217.         {                  
  218.             TF1=0;      //定時(shí)器1溢出標(biāo)志清0(溢出時(shí)TF1被硬件置1,并且申請(qǐng)中斷,軟件查詢(xún)到該位置1后需用軟件清零)   
  219.             seta ++;
  220.         }
  221.         if(!(s2==s3==s4==0))        //松手檢測(cè)
  222.                 seta = 0;        //延時(shí)時(shí)間超過(guò)一定值,或者有按鍵被按下(注意!這個(gè)符號(hào))時(shí),時(shí)間會(huì)被延長(zhǎng)
  223.         if(seta>=70)                //延時(shí)
  224.         {                  
  225.              setbit=0;        //關(guān)閉設(shè)置
  226.              sdat = 0;        
  227.         }
  228.         if(sk!=s2)            //sk用來(lái)做s2的中間暫存數(shù)據(jù),用來(lái)用來(lái)識(shí)別S2是否變化過(guò)
  229.         {
  230.                 sk = s2;
  231.                 if(s2)
  232.                 sdat ++;      //每次進(jìn)行一次S2動(dòng)作時(shí)才自加一次sdat
  233.                 if(sdat ==6)sdat=7;   //跳過(guò)星期,本程序不顯示星期                           
  234.         }
  235.         m = timedate[sdat]/16*10+timedate[sdat]%16;        //m用10進(jìn)制存下以供寫(xiě)入DS1302
  236.         if(s3) m--;
  237.                 switch (sdat)           //每次進(jìn)入設(shè)置的對(duì)應(yīng)操作判斷
  238.         {
  239.                 case 1:
  240.                         if(m==-1)                                        //調(diào)整秒鐘
  241.                                                  m = 59;
  242.                                   break;
  243.       
  244.                 case 2:
  245.                         if(m==-1)                                        //調(diào)整分鐘
  246.                                                  m = 59;
  247.                                   break;
  248.       
  249.                 case 3:
  250.                         if(m==-1)                                        //調(diào)整小時(shí)
  251.                                                  m =23;
  252.                                   break;
  253.       
  254.                 case 4:                                                //調(diào)整日期***因?yàn)樵路莶煌悦總(gè)月的天數(shù)是不同的
  255.                         if(timedate[5]==4|timedate[5]==6|timedate[5]==9|timedate[5]==11)  //小月,
  256.                         {
  257.                            if(m<=0)
  258.                                                  m = 30;
  259.                               break;        //4月6月9月和11月是小月份,只有30天,所以到了30后轉(zhuǎn)到1日
  260.                         }
  261.                         if(timedate[5]==2&(timedate[7]%4==0))                            //閏年2月
  262.                         {
  263.                            if(m<=0)
  264.                                                  m=29;
  265.                                    break;     //閏年2月有29天
  266.                         }
  267.                         if(timedate[5]==2&(timedate[7]%4!=0))                          //平年2月
  268.                         {
  269.                            if(m<=0)
  270.                                                  m=28;
  271.                                 break;     //平年2月只有28天                                                      
  272.                         }
  273.                         if(m<=0)
  274.                                                  m =31;
  275.                                 break;         //其它月分情況
  276.         /********************************************************************************************************
  277.         怎么判斷一個(gè)年份是不是閏年:1:普通情況求閏年只需除以4可除盡即可 年/4余數(shù)為0
  278.                                                                    2:如果是100的倍數(shù)但不是400的倍數(shù),那就不是閏年了,即末兩位都是零的整除400才行
  279.         判斷閏年條件①:非整百年數(shù)除以4,無(wú)余為閏,有余為平;②整百年數(shù)除以400,無(wú)余為閏有余為平。
  280.         *********************************************************************************************************/
  281.                 case 5:                                        //調(diào)整月份
  282.                         if(m==0)
  283.                                                 m = 12;
  284.                                break;
  285.       
  286.                 case 6:
  287.                          sdat++;        //跳過(guò)星期本程序不顯示星期
  288.                         if(m<=0)
  289.                                           m = 7;
  290.                               break;
  291.       
  292.                 case 7:                                        //調(diào)整年份17-99
  293.                         if(m<=16)
  294.                                                  m = 99;
  295.                               break;
  296.       
  297.                 default :         /****不在判斷范圍的進(jìn)行初始化處理*/
  298.                         sdat = 0;        //S2按鍵計(jì)數(shù)清0
  299.                                     sk = 0;                //s2的中間暫存數(shù)據(jù)清0
  300.                         setbit = 0;        //設(shè)置控制標(biāo)識(shí)清0
  301.                         s2 = 0;     //s2=0是優(yōu)化點(diǎn),在按下S2后按鍵標(biāo)識(shí)不會(huì)清零,松手時(shí)程序已重復(fù)運(yùn)行了很多遍,所以會(huì)重新跳回設(shè)置的第一位.加本命令可以讓設(shè)置判斷失效,不進(jìn)設(shè)置頁(yè)。                             
  302.                                          break;
  303.         }
  304.         if(s4) m++;
  305.         switch (sdat)           //每次進(jìn)入設(shè)置的對(duì)應(yīng)操作判斷
  306.         {
  307.                 case 1:                                 //調(diào)整秒鐘
  308.                         if(m>59)
  309.                                                  m = 0;
  310.                                   break;
  311.       
  312.                 case 2:                                        //調(diào)整分鐘
  313.                         if(m>59)
  314.                                                  m = 0;
  315.                                   break;
  316.       
  317.                 case 3:                                        //調(diào)整小時(shí)
  318.                         if(m>23)
  319.                                                  m = 0;
  320.                                   break;
  321.       
  322.                 case 4:                                        //調(diào)整日期***因?yàn)樵路莶煌悦總(gè)月的天數(shù)是不同的
  323.                         if(timedate[5]==4|timedate[5]==6|timedate[5]==9|timedate[5]==11)  //小月,
  324.                         {
  325.                            if(m>=31)
  326.                                                          m = 1;
  327.                                        break;//4月6月9月和11月是小月份,只有30天,所以到了30后轉(zhuǎn)到1日
  328.                         }
  329.                         if(timedate[5]==2&(timedate[7]%4==0))                            //閏年2月
  330.                         {
  331.                            if(m>=30)
  332.                                                         m = 1;
  333.                                            break;      //閏年2月有29天
  334.                         }
  335.                         if(timedate[5]==2&(timedate[7]%4!=0))                          //平年2月
  336.                         {
  337.                            if(m>=29)
  338.                                                         m = 1;
  339.                                         break;     //平年2月只有28天                                                      
  340.                         }
  341.                         if(m>=32)
  342.                                                         m = 1;
  343.                                     break;            //其它月分情況
  344.       
  345.                 case 5:                                                        //調(diào)整月份
  346.                         if(m>=13)
  347.                                                  m = 1;
  348.                                     break;
  349.       
  350.                 case 6:
  351.                         sdat++;              //跳過(guò)星期本程序不顯示星期
  352.                         if(m>=8)
  353.                                                  m = 1;
  354.                                     break;
  355.       
  356.                 case 7:                                                //調(diào)整年份17-99
  357.                         if(m>=100)
  358.                                                  m = 17;
  359.                                     break;
  360.       
  361.                 default : /****不在判斷范圍的進(jìn)行初始化處理*/
  362.                         sdat = 0;        //S2按鍵計(jì)數(shù)清0
  363.                                     sk = 0;                //s2的中間暫存數(shù)據(jù)清0
  364.                         setbit = 0;        //設(shè)置控制標(biāo)識(shí)清0
  365.                         s2 = 0;     //s2=0是優(yōu)化點(diǎn),在按下S2后按鍵標(biāo)識(shí)不會(huì)清零,松手時(shí)程序已重復(fù)運(yùn)行了很多遍,所以會(huì)重新跳回設(shè)置的第一位.加本命令可以讓設(shè)置判斷失效,不進(jìn)設(shè)置頁(yè)。                                 
  366.                                         break;
  367.         }
  368.         if(setbit)        //如果設(shè)置控制標(biāo)識(shí)setbit為1則說(shuō)明以上有成立的條件,需要發(fā)送修改數(shù)據(jù)
  369.         {
  370.            sendchar(0x8e,0);                         //去DS1302寫(xiě)保護(hù)
  371.            sendchar(commandchar[sdat],m/10*16+m%10); //將改好的數(shù)據(jù)寫(xiě)入DS1302(sdat的值決定寫(xiě)時(shí)分秒或年月日星期,m的值轉(zhuǎn)換成BCD寫(xiě)入)
  372.            sendchar(0x8e,0x80);                      //加寫(xiě)保護(hù)
  373.         
  374.            if(seta%5>2&seta<50)                 //設(shè)置延時(shí)操作期間控制閃爍時(shí)間
  375.               timedate[sdat] = 0xbb;  //顯示空,對(duì)應(yīng)段選的兩位11;0xbb/16=11,0xbb%16=11,而上面段選數(shù)組中第12個(gè)數(shù)是顯示空   
  376.         }                                 
  377. }
  378. /***************************************************************************************
  379.                  顯示子程序 兩個(gè)數(shù),分別記錄鍵值和重復(fù)碼個(gè)數(shù)
  380. *****************************************************************************************/
  381.                 void display()  
  382.                         {   
  383.                                P2 = 0x7f;         //送位選數(shù)據(jù)0111 1111                                 
  384.                                    P0 = (displaychar1[0]);        //送段選數(shù)據(jù)
  385.                                       timeout(LD);        //延時(shí)
  386.                                        P0 =0xff;                        //消隱,很重要,不然會(huì)閃爍,共陰數(shù)碼管用P0=0x00
  387.                                                                                                                                 
  388.                                 P2 = 0xbf;                //送位選數(shù)據(jù)1011 1111     
  389.                                    P0 = displaychar1[1];
  390.                                       timeout(LD);        //延時(shí)
  391.                                        P0 =0xff;
  392.                        
  393.                                 P2 = 0xdf;                //送位選數(shù)據(jù)1101 1111   
  394.                                    P0 = displaychar1[2];
  395.                                       timeout(LD);//延時(shí)      
  396.                                        P0 =0xff;
  397.                                     
  398.                                 P2 = 0xef;                //送位選數(shù)據(jù)1110 1111   
  399.                                    P0 = displaychar1[3];
  400.                                       timeout(LD);        //延時(shí)
  401.                                        P0 =0xff;      
  402.                                 
  403.                                 P2 = 0xf7;                //送位選數(shù)據(jù)1111 0111     
  404.                                    P0 = displaychar1[4];
  405.                                       timeout(LD);        //延時(shí)
  406.                                        P0 =0xff;
  407.                                 
  408.                                 P2 = 0xfb;                //送位選數(shù)據(jù)1111 1011      
  409.                                    P0 = displaychar1[5];
  410.                                       timeout(LD);          //延時(shí)                                                         
  411.                                        P0 =0xff;
  412.                        
  413.                                 P2 = 0xfd;                //送位選數(shù)據(jù)1111 1101            
  414.                                    P0 = displaychar1[6];   
  415.                                       timeout(LD);        //延時(shí)
  416.                                        P0 =0xff;
  417.                        
  418.                                 P2 = 0xfe;                //送位選數(shù)據(jù)1111 1110   
  419.                                     P0 = displaychar1[7];
  420.                                        timeout(LD);        //延時(shí)
  421.                                         P0 =0xff;      
  422.                         }
  423. /************************************溫度顯示子程序*****************************************/
  424. DS18b20display()
  425. {
  426.         if(fg==1)        //溫度為正時(shí)顯示的數(shù)據(jù)
  427.         {
  428.                 if((temp_value/100)>=1)        //若溫度高于100度時(shí)--即溫度百位數(shù)大于或等于1的時(shí)候
  429.                 {
  430.                         displaychar1[0] = duan[11];                //不顯示
  431.                         displaychar1[1] = duan[temp_value/100];                //顯示溫度百位
  432.                         displaychar1[2] = duan[temp_value%100/10];        //顯示溫度十位
  433.                         displaychar1[3] = duan[temp_value%10]&0x7f;   //顯示溫度個(gè)位和小數(shù)點(diǎn)
  434.                         displaychar1[4] = duan[temp1_value*625/1000%10];//顯示溫度小數(shù)點(diǎn)后第一位
  435.                         displaychar1[5] = duan[11];                //不顯示
  436.                         displaychar1[6] = duan[12];      //溫度顯示"0"        
  437.                         displaychar1[7] = duan[13];                //溫度顯示"C"
  438.                 }
  439.                         if((temp_value%100/10)>=1&(temp_value/100)<1)        //若溫度高于10度與溫度低于100度時(shí)--即溫度十位數(shù)大于或等于1并且溫度百位數(shù)小于1的時(shí)候
  440.                         {
  441.                                 displaychar1[0] = duan[11];                //不顯示
  442.                                 displaychar1[1] = duan[11];                //不顯示
  443.                                 displaychar1[2] = duan[temp_value%100/10];        //顯示溫度十位
  444.                                 displaychar1[3] = duan[temp_value%10]&0x7f;   //顯示溫度個(gè)位和小數(shù)點(diǎn)
  445.                                 displaychar1[4] = duan[temp1_value*625/1000%10];//顯示溫度小數(shù)點(diǎn)后第一位
  446.                                 displaychar1[5] = duan[11];                //不顯示
  447.                                 displaychar1[6] = duan[12];     //溫度顯示"0"         
  448.                                 displaychar1[7] = duan[13];                //溫度顯示"C"
  449.                         }
  450.                                 if((temp_value%100/10)<1&(temp_value/100)<1)        //若溫度低于10度時(shí)--即溫度十位數(shù)小于1并且百位數(shù)小于1的時(shí)候
  451.                                 {
  452.                                         displaychar1[0] = duan[11];                //不顯示
  453.                                         displaychar1[1] = duan[11];                //不顯示
  454.                                         displaychar1[2] = duan[temp_value%10]&0x7f;   //顯示溫度個(gè)位和小數(shù)點(diǎn)
  455.                                         displaychar1[3] = duan[temp1_value*625/1000%10];//顯示溫度小數(shù)點(diǎn)后第一位
  456.                                         displaychar1[4] = duan[11];                //不顯示
  457.                                         displaychar1[5] = duan[12];     //溫度顯示"0"
  458.                                         displaychar1[6] = duan[13];      //溫度顯示"C"      
  459.                                         displaychar1[7] = duan[11];                //不顯示
  460.                                 }
  461.         }
  462.         if(fg==0)   //溫度為負(fù)時(shí)顯示的數(shù)據(jù)
  463.         {
  464.                 if(((temp_value-1)%100/10)>=1)        //如果為負(fù)10度以下時(shí)
  465.                 {
  466.                         displaychar1[0] = duan[11];                //不顯示
  467.                         displaychar1[1] = duan[10];                //顯示"-"
  468.                         displaychar1[2] = duan[(temp_value-1)%100/10];        //顯示負(fù)溫度十位
  469.                         displaychar1[3] = duan[(temp_value-1)%10]&0x7f;   //顯示負(fù)溫度個(gè)位和小數(shù)點(diǎn)
  470.                         displaychar1[4] = duan[temp1_value*625/1000%10];//顯示負(fù)溫度小數(shù)點(diǎn)后第一位
  471.                         displaychar1[5] = duan[11];                //不顯示
  472.                         displaychar1[6] = duan[12];      //溫度顯示"0"        
  473.                         displaychar1[7] = duan[13];                //溫度顯示"C"
  474.                                        
  475.                         fg=1;                                                                //清負(fù)溫度標(biāo)志
  476.                 }
  477.                 else                                //負(fù)十度以上時(shí)
  478.                 {
  479.                         displaychar1[0] = duan[11];                //不顯示
  480.                         displaychar1[1] = duan[11];                //不顯示
  481.                         displaychar1[2] = duan[10];        //顯示"-"
  482.                         displaychar1[3] = duan[(temp_value-1)%10]&0x7f;   //顯示負(fù)溫度個(gè)位和小數(shù)點(diǎn)
  483.                         displaychar1[4] = duan[temp1_value*625/1000%10];//顯示負(fù)溫度小數(shù)點(diǎn)后第一位
  484.                         displaychar1[5] = duan[11];                //不顯示
  485.                         displaychar1[6] = duan[12];     //溫度顯示"0"//小數(shù)點(diǎn)后第二位temp1_value*625/100%10      
  486.                         displaychar1[7] = duan[13];                //溫度顯示"C"   //小數(shù)點(diǎn)后第三位temp1_value*625/10%10

  487.                         fg=1;                                                                //清負(fù)溫度標(biāo)志      
  488.                 }
  489.         }//溫度為負(fù)時(shí)顯示的數(shù)據(jù)包含的大括號(hào)      
  490. }//顯示溫度數(shù)據(jù)包含的大括號(hào)                              

  491. /***************************************主函數(shù)**************************************************/
  492. main()
  493. {                                    
  494.     SCLK = 0 ;                 /* DS1302實(shí)時(shí)時(shí)鐘的串行時(shí)鐘引腳(第7腳SCLK)*/
  495.     TRST = 0 ;                /* DS1302實(shí)時(shí)時(shí)鐘的復(fù)位/片選線(xiàn)引腳(第5腳RST低電平復(fù)位高電平時(shí)芯片正常工作)*///復(fù)位DS1302實(shí)時(shí)時(shí)鐘
  496.         readtime();             //先讀一下時(shí)間然后再判斷自動(dòng)補(bǔ)償程序
  497.         fen=min;                                //fen用來(lái)判斷min是否到了1分鐘
  498.         if(S2==0)        //上電檢測(cè) 如果調(diào)整鍵S2被按下就初始化1302 給初值是17年12月26日,16:30:00星期二
  499.     {                                //這里是給系統(tǒng)送初始值的,使用的方法是斷電之后,按住S2調(diào)整鍵,然后上電,S2鍵按住1~3s,松開(kāi)即設(shè)置完成
  500.          sendchar(0x8e,0);                //去DS1302寫(xiě)保護(hù)
  501.          sendchar(0x80,0x00);        //寫(xiě)入秒數(shù)據(jù)00
  502.          sendchar(0x82,0x30);        //寫(xiě)入分?jǐn)?shù)據(jù)30
  503.          sendchar(0x84,0x16);        //寫(xiě)入小時(shí)數(shù)據(jù)16
  504.          sendchar(0x8a,0x02);        //寫(xiě)入星期數(shù)據(jù)2
  505.          sendchar(0x86,0x26);        //寫(xiě)入日期數(shù)據(jù)26
  506.          sendchar(0x88,0x12);        //寫(xiě)入月份數(shù)據(jù)12
  507.          sendchar(0x8c,0x17);        //寫(xiě)入年份數(shù)據(jù)17
  508.          sendchar(0x8e,0x80);        //DS1302加寫(xiě)保護(hù)
  509.     }
  510.     TMOD = 0x12;    //設(shè)置定時(shí)器工作模式0001 0010(T1為方式1-16位定時(shí)器/計(jì)數(shù)器  T2為方式2-8位初值自動(dòng)重裝的8位定時(shí)器/計(jì)數(shù)器)
  511.     TR1 = 1;        //啟動(dòng)定時(shí)器/計(jì)數(shù)器1               
  512.     TR0 = 1;                //啟動(dòng)定時(shí)器/計(jì)數(shù)器0
  513.     while(1)                //大循環(huán)
  514.     {
  515.                 readtime();             //先讀一下時(shí)間然后再判斷自動(dòng)補(bǔ)償程序
  516.                 if(fen!=min)                        //如果fen不等于min證明過(guò)了1分鐘了
  517.                 {
  518.                         fen=min;                //那么再讓fen等于min
  519.                         tz++;                        //tz自加1
  520.                 }
  521.                 if((tz==38)&(sce>=01))        //如果計(jì)時(shí)到了38分鐘和秒鐘過(guò)了1秒的時(shí)候
  522.                 {
  523.                         tz=0;                                                                        //tz清零
  524.                         sendchar(0x8e,0);                         //去DS1302寫(xiě)保護(hù)
  525.                 sendchar(0x80,0x00);                                         //秒清0--即減去1秒或者加1秒再這里修改
  526.                 sendchar(0x8e,0x80);                      //加寫(xiě)保護(hù)
  527.                 }
  528.         if(!S2)                //檢測(cè)設(shè)置按鍵S2是否按下
  529.                 s2 = jianpan(S2);        //若S2被按下則掃描鍵盤(pán)掃描程序S2
  530.                 if(!S3)                //檢測(cè)減數(shù)據(jù)按鍵S3是否被按下
  531.                         s3 = jianpan(S3);        //若S3被按下則掃描鍵盤(pán)掃描程序S3
  532.                          if(!S4)                 //檢測(cè)加數(shù)據(jù)按鍵S4是否被按下
  533.                                  s4 = jianpan(S4);        //若S4被按下則掃描鍵盤(pán)掃描程序S4
  534.                  TRST = 0;        /* DS1302實(shí)時(shí)時(shí)鐘的復(fù)位/片選線(xiàn)引腳(第5腳RST低電平復(fù)位高電平時(shí)芯片正常工作)*/
  535.         /*以下是開(kāi)始年月日自動(dòng)歸零的問(wèn)題修改,問(wèn)題產(chǎn)生原因是開(kāi)始沒(méi)有加!setbit這個(gè)條件,程序在運(yùn)行到設(shè)置年月日時(shí)依然會(huì)進(jìn)
  536.           入下面這個(gè)判斷,然后再進(jìn)入設(shè)置,但是年月日在這里還沒(méi)有讀數(shù),所以這里的設(shè)置就會(huì)進(jìn)入M=0然后加或減,從而讓設(shè)置值
  537.           出現(xiàn)錯(cuò)誤
  538.         */
  539.     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í)間格式                                                                                               
  540.         {
  541.         readtime();             //先讀一下時(shí)間然后再判斷設(shè)置程序,這樣的主要目的是讓初m的值由1302決定。
  542.                 ReadTemp();                                //讀取DS18B20當(dāng)前溫度
  543.         if(s2|setbit)          //按下S2或設(shè)置標(biāo)識(shí)打開(kāi)時(shí)會(huì)進(jìn)入本判斷
  544.         {
  545.              ya = 0;                                //進(jìn)設(shè)置后會(huì)關(guān)閉日期顯示延時(shí)
  546.              settime();                  //設(shè)置時(shí)間日期子程序
  547.         }
  548.                 else        //正常顯示時(shí)間和溫度
  549.                 {
  550.                         if((sce%5)!=0)        //如果秒對(duì)5求余不等于0的時(shí)候顯示時(shí)間--即溫度和時(shí)間間歇顯示,時(shí)間顯示比溫度顯示長(zhǎng)
  551.                         {
  552.                                 displaychar1[0] = duan[hour/16];                //正常顯示小時(shí)十位
  553.                                 displaychar1[1] = duan[hour%16];                //正常顯示小時(shí)個(gè)位
  554.                                 displaychar1[2] = duan[10];                                //正常顯示"-"
  555.                                 displaychar1[3] = duan[min/16];                        //正常顯示分鐘十位
  556.                                 displaychar1[4] = duan[min%16];                        //正常顯示分鐘個(gè)位
  557.                                 displaychar1[5] = duan[10];                                //正常顯示"-"
  558.                                 displaychar1[6] = duan[sce/16];             //正常顯示秒鐘十位         
  559.                                 displaychar1[7] = duan[sce%16];                        //正常顯示秒鐘個(gè)位
  560.                         }
  561.                         else        //否則顯示溫度
  562.                         {
  563.                                 DS18b20display();        //溫度顯示子程序
  564.                         }
  565.                 }//正常顯示時(shí)間和溫度數(shù)據(jù)包含的大括號(hào)                              
  566.         }//如果S2沒(méi)有被按下且不在顯示年月日的延時(shí)范圍,而且設(shè)置標(biāo)識(shí)為0時(shí),或者在標(biāo)識(shí)為1但是設(shè)置值在123中時(shí),則正常顯示時(shí)間格式包含的大括號(hào)                                       
  567.     if(((!setbit)&s3)|ya>0|(setbit&sdat>3))
  568.     {
  569.             if(TF1&!setbit)                 //如果定時(shí)器1計(jì)滿(mǎn)溢出或設(shè)置標(biāo)識(shí)打開(kāi)時(shí)會(huì)進(jìn)入本判斷
  570.             {
  571.                ya++;              //非設(shè)置頁(yè)面才進(jìn)去日期延時(shí)
  572.                TF1 = 0;                        //定時(shí)器1溢出標(biāo)志清0(溢出時(shí)TF1被硬件置1,并且申請(qǐng)中斷,軟件查詢(xún)到該位置1后需用軟件清零)
  573.             }                       
  574.             readyear();                                //讀取年月日數(shù)據(jù)
  575.             if(s2|setbit)            //如果按下S2或設(shè)置標(biāo)識(shí)打開(kāi)時(shí)會(huì)進(jìn)入本判斷
  576.             {
  577.                ya = 0;                //進(jìn)設(shè)置后會(huì)關(guān)閉日期顯示延時(shí)
  578.                settime();                        //設(shè)置時(shí)間日期子程序
  579.             }
  580.                 displaychar1[0] = duan[2];                        //顯示年月日 固定顯示2
  581.                 displaychar1[1] = duan[0];                        //顯示年月日 固定顯示0
  582.                 displaychar1[2] = duan[year/16];                //顯示年份十位
  583.                 displaychar1[3] = duan[year%16]&0x7f;        //顯示年份個(gè)位****&0x7f是讓這一位顯示出小數(shù)點(diǎn),共陰數(shù)碼管就是或0x80或者是+0x80
  584.                 displaychar1[4] = duan[month/16];                //顯示月份十位
  585.                 displaychar1[5] = duan[month%16]&0x7f;        //顯示月份個(gè)位****&0x7f是讓這一位顯示出小數(shù)點(diǎn),共陰數(shù)碼管就是或0x80或者是+0x80
  586.                 displaychar1[6] = duan[date/16];                //顯示日期十位
  587.                 displaychar1[7] = duan[date%16];                //顯示日期個(gè)位
  588.                 if(ya>70) ya =0;       //日期延時(shí)約6秒,大約時(shí)間,與計(jì)時(shí)器和程序的運(yùn)行有關(guān)
  589.      }
  590.      s3 = s4 =0;               
  591.      if(S2==S3==S4==1)                //松手檢測(cè)  如果三個(gè)按鍵都沒(méi)有被按下
  592.      {  
  593.          ja = 0;
  594.          TR0 = 1;                //啟動(dòng)定時(shí)器0
  595.          s2= s3= s4= 0; //松開(kāi)按鍵后恢復(fù)計(jì)時(shí)器并清零按鍵值
  596.        //s=0;     //為快速跳時(shí),s清零放在松手檢測(cè)中,s3和s4在按下不放后會(huì)重復(fù)跳值,想要每次按下只起作用一次,請(qǐng)將s放在本循環(huán)外面這個(gè)循環(huán)后面
  597.      }                               //
  598.          s = 0;
  599.      for(a=0; a<50;a++)                 //一個(gè)循環(huán)顯示50次數(shù)碼管
  600.          display();
  601.   }//while包含的大括號(hào)
  602. }
復(fù)制代碼


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:76227 發(fā)表于 2018-1-16 17:17 | 只看該作者
明顯是刷新數(shù)碼管頻率的問(wèn)題,做好的辦法是使用數(shù)碼管驅(qū)動(dòng)IC。最方便,軟件刷新數(shù)碼管效率很低
回復(fù)

使用道具 舉報(bào)

板凳
ID:46220 發(fā)表于 2018-1-16 20:51 | 只看該作者
905377346 發(fā)表于 2018-1-16 17:17
明顯是刷新數(shù)碼管頻率的問(wèn)題,做好的辦法是使用數(shù)碼管驅(qū)動(dòng)IC。最方便,軟件刷新數(shù)碼管效率很低

謝謝指導(dǎo),那我再?gòu)倪@方面想想
回復(fù)

使用道具 舉報(bào)

地板
ID:46220 發(fā)表于 2018-1-16 22:03 | 只看該作者
我把數(shù)碼管的刷新時(shí)間加快也不行,還是老樣子,數(shù)碼管的顯示亮度已經(jīng)變得很暗了,時(shí)分秒還是不能閃爍
回復(fù)

使用道具 舉報(bào)

5#
ID:46220 發(fā)表于 2018-1-16 23:05 | 只看該作者

回復(fù)

使用道具 舉報(bào)

6#
ID:267736 發(fā)表于 2018-1-18 04:02 | 只看該作者
樓主搞定了嗎?你是參考哪個(gè)帖子做的?
回復(fù)

使用道具 舉報(bào)

7#
ID:46220 發(fā)表于 2018-1-18 07:52 | 只看該作者
izhineng 發(fā)表于 2018-1-18 04:02
樓主搞定了嗎?你是參考哪個(gè)帖子做的?

是這個(gè)
http://www.torrancerestoration.com/bbs/dpj-99616-1.html
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表