久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3767|回復: 6
打印 上一主題 下一主題
收起左側

自己用洞洞板焊的單片機數碼管時鐘程序有問題

[復制鏈接]
跳轉到指定樓層
樓主
在本論壇看到的一個數碼管時鐘程序,稍作修改后,自己用洞洞板焊了一塊板子,用了兩個四位共陽數碼管做的,取消了鎖存器,實現的功能完全正常,后來又加入了DS18B20測溫程序,溫度顯示也正常,時間顯示4秒多然后顯示溫度1秒的樣子,交替顯示,現在遇到的問題是,在沒加溫度程序的時候,調整時間的時候時分秒年月日都會閃爍,并且調整加減的時候都實時顯示,現在加了溫度程序以后,按下調整鍵的時候,時分秒不會閃爍,按加減的時候,數據也不能實時變化,但是數據的加減在調整退出后是有變化的,只是沒能實時的顯示,而年月日的調整是正常的,就是說調整的時候年月日會閃爍,且數據也是隨加減鍵實時變化的,下面是我的程序,大神幫我看看程序哪里有問題?已經折騰好幾天了,沒能解決

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

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

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

  487.                         fg=1;                                                                //清負溫度標志      
  488.                 }
  489.         }//溫度為負時顯示的數據包含的大括號      
  490. }//顯示溫度數據包含的大括號                              

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


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

使用道具 舉報

沙發
ID:76227 發表于 2018-1-16 17:17 | 只看該作者
明顯是刷新數碼管頻率的問題,做好的辦法是使用數碼管驅動IC。最方便,軟件刷新數碼管效率很低
回復

使用道具 舉報

板凳
ID:46220 發表于 2018-1-16 20:51 | 只看該作者
905377346 發表于 2018-1-16 17:17
明顯是刷新數碼管頻率的問題,做好的辦法是使用數碼管驅動IC。最方便,軟件刷新數碼管效率很低

謝謝指導,那我再從這方面想想
回復

使用道具 舉報

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

使用道具 舉報

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

回復

使用道具 舉報

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

使用道具 舉報

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

是這個
http://www.zg4o1577.cn/bbs/dpj-99616-1.html
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲精品99 | 亚洲欧美精品国产一级在线 | 免费观看一区二区三区毛片 | 欧美福利专区 | 天天插天天狠天天透 | 亚洲一区国产 | 国产精品色 | 国产亚洲精品精品国产亚洲综合 | 久久久久国产 | 久久99国产精品久久99果冻传媒 | 国产精品久久久久久52avav | 亚洲久久一区 | 97在线观视频免费观看 | 日日骚网| www.国产视频 | 91xxx在线观看 | 欧美视频一区 | 成人免费在线电影 | 狠狠亚洲 | 91亚洲国产| 午夜精品一区二区三区在线观看 | 在线一区视频 | 亚洲精品久久 | 亚洲精品一 | 丁香久久 | 国产小视频在线 | 午夜成人在线视频 | 热re99久久精品国99热观看 | 中国av在线免费观看 | 97精品一区二区 | 成人黄色在线观看 | 中文字幕一级 | 欧美日韩精品一区二区三区四区 | 久久久激情 | 在线欧美 | 中文字幕一区二区三 | 毛片av免费在线观看 | 秋霞a级毛片在线看 | 国产精选一区 | 男人天堂999 | 久久色视频 |