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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

單片機DS3231時鐘+溫度顯示源碼原理圖與實物制作

  [復制鏈接]
跳轉到指定樓層
樓主
采用stc15單片機做的主控芯片,僅供參考
制作出來的ds3132時鐘實物圖:



電路原理圖:




pcb文件:工程文件可到本帖附件中下載


51單片機源程序如下:
  1. //#include <reg52.h>
  2. #include "stc15f104w.h"
  3. #include "I2C.h"        
  4. #include "Led_can.h"
  5.          
  6. typedef unsigned int u16;  //16位無符號整型數
  7. typedef unsigned char u8;  //8位無符號整型數

  8. #define E2PROM_WriteAddress 0xAE    //器件寫地址
  9. #define DS3231_WriteAddress 0xD0    //器件寫地址
  10. #define DS3231_ReadAddress  0xD1    //器件讀地址
  11. #define DS3231_SECOND       0x00    //秒
  12. #define DS3231_MINUTE       0x01    //分
  13. #define DS3231_HOUR         0x02    //時
  14. #define DS3231_WEEK         0x03    //星期                           
  15. #define DS3231_DAY          0x04    //日
  16. #define DS3231_MONTH        0x05    //月
  17. #define DS3231_YEAR         0x06    //年
  18. //鬧鈴1            
  19. //#define DS3231_SALARM1ECOND 0x07    //秒
  20. //#define DS3231_ALARM1MINUTE 0x08    //分
  21. //#define DS3231_ALARM1HOUR   0x09    //時
  22. //#define DS3231_ALARM1WEEK   0x0A    //星期/日
  23. //鬧鈴2
  24. //#define DS3231_ALARM2MINUTE 0x0b    //分
  25. //#define DS3231_ALARM2HOUR   0x0c    //時
  26. //#define DS3231_ALARM2WEEK   0x0d    //星期/日
  27. #define DS3231_CONTROL      0x0e    //控制寄存器
  28. #define DS3231_STATUS       0x0f    //狀態寄存器
  29. #define BSY                 2       //忙
  30. #define OSF                 7       //振蕩器停止標志
  31. #define DS3231_XTAL         0x10    //晶體老化寄存器
  32. #define DS3231_TEMPERATUREH 0x11    //溫度寄存器高字節(8位)
  33. #define DS3231_TEMPERATUREL 0x12    //溫度寄存器低字節(高2位)



  34. sbit BP = P1^5;         //秒數碼管驅動
  35. sbit KEY1 =        P1^5;  //按鍵輸入引腳

  36. u8  Time[18];          //時鐘數值緩沖區
  37. bit BiaoJi=0;          //讀實時時鐘標記
  38. bit BianJi_c=0;          //長按鍵標記
  39. bit BianJi_d=0;          //短按鍵標記
  40. u8 BianJi=0;          //編輯模式標記
  41. u8 L_u[4]={2,3,4,5};//數碼管顯示第幾時鐘緩沖區
  42. u8 ling=0;              //數碼管首位是否顯示零標記
  43. bit WenDu = 0;          //溫度轉換標記

  44. void ConfigTimer0(u8 ms);               //配置并啟動T0,ms-T0定時時間
  45. void write_byte(u8 addr, u8 write_data);//DS3231_寫一個字節數據到時鐘芯片        
  46. u8 read_byte(u8 random_addr);           //DS3231_讀一個字節數據到時鐘芯片
  47. void write_byte_E2( u8 write_data);     //E2PROM-寫一個字節數據到時鐘芯片        
  48. u8 read_byte_E2();                      //E2PROM-讀一個字節數據到時鐘芯片
  49. u8 BCD2HEX(u8 val);                     //BCD轉換為Byte
  50. u8 HEX2BCD(u8 val);                     //B碼轉換為BCD碼
  51. void anjian();                                                     //按鈕掃描         需在定時中斷中調用
  52. void Anjian_d(u8 addr, u8 map);         //短按鍵處理—子程序

  53. void main()
  54. {
  55.      u8 map;
  56.          u16 wend;
  57.          
  58.          EA = 1;      //開總中斷
  59.          Led_cu();         //數碼管初始化
  60.          ConfigTimer0(5);   //配置T0定時

  61.          ling=read_byte_E2();         //E2PROM讀出數據—數碼管首位是否顯示零標記        
  62.      //初始化實時時鐘,小時采用24小時制
  63.          write_byte(DS3231_CONTROL, 0x1C);              //控制寄存器  DS3231_CONTROL
  64.      write_byte(DS3231_STATUS, 0x00);               //狀態寄存器  DS3231_STATUS
  65.          //write_byte(DS3231_SECOND,HEX2BCD(30)); //修改秒
  66.      //write_byte(DS3231_MINUTE,HEX2BCD(30)); //修改分
  67.          //write_byte(DS3231_HOUR,HEX2BCD(16));   //修改時
  68.          //write_byte(DS3231_DAY,HEX2BCD(1));     //修改日
  69.          //write_byte(DS3231_MONTH,HEX2BCD(12));  //修改月
  70.          //write_byte(DS3231_YEAR,HEX2BCD(17));   //修改年
  71.                                        
  72.      while(1)
  73.          {         //讀取時鐘芯片并寫進數碼管顯示緩沖區======================
  74.                   if(BiaoJi == 1)
  75.                  {      BiaoJi = 0;                                
  76.                                        
  77.                                 map=read_byte(DS3231_SECOND);     //讀秒        
  78.                             map=BCD2HEX(map);
  79.                                 Time[0]=map%10;
  80.                                 Time[1]=map/10%10;
  81.                             map=read_byte(DS3231_MINUTE);     //讀分        
  82.                             map=BCD2HEX(map);
  83.                                 Time[2]=map%10;
  84.                                 Time[3]=map/10%10;
  85.                                 map=read_byte(DS3231_HOUR)&0x3f;  //讀小時 24小時制               
  86.                             map=BCD2HEX(map);
  87.                                 Time[4]=map%10 ;
  88.                                 Time[5]=map/10%10 ;
  89.                         
  90.                                 //map=read_byte(DS3231_WEEK );      //讀星期           
  91.                                 //Time[6]=map
  92.                                 //map=read_byte(DS3231_DAY);        //讀日
  93.                             //map=BCD2HEX(map);
  94.                                 //Time[8]=map%10
  95.                                 //Time[9]=map/10%10
  96.                             //map=read_byte(DS3231_MONTH);      //讀月
  97.                             //map=BCD2HEX(map);
  98.                                 //Time[10]=map%10
  99.                                 //Time[11]=map/10%10
  100.                                 //map=read_byte(DS3231_YEAR);       //讀年
  101.                             //map=BCD2HEX(map);
  102.                                 //Time[12]=map%10
  103.                                 //Time[13]=map/10%10

  104.                                 if((ling==0) && (Time[L_u[3]]==0))         //判斷數碼管首位零是否顯示
  105.                                 Led_buff[3]        = 0xff;
  106.                                 else
  107.                                 Led_buff[3]        = Led_Char[ Time[L_u[3]]];  
  108.                                 Led_buff[2]        = Led_Char[ Time[L_u[2]]];
  109.                                 Led_buff[1]        = Led_Char[ Time[L_u[1]]];
  110.                                 Led_buff[0]        = Led_Char[ Time[L_u[0]]];
  111.                                        
  112.                  }
  113.                  //讀取溫度并寫進數碼管顯示緩沖區======================
  114.                  if(WenDu == 1)
  115.                  {            WenDu = 0;
  116.                                                 //零上溫度轉換
  117.                                 map=read_byte(DS3231_TEMPERATUREH);    //溫度高字節—整數位
  118.                                    if((map&0x80)==0)                //判斷首字節為1即為        零下溫度
  119.                                    {   Led_buff[0] = 0xa7;
  120.                                     Time[16]=map%10        ;
  121.                                     Time[17]=map/10%10;        
  122.                                         map=read_byte(DS3231_TEMPERATUREL);    //溫度低字節—小數位
  123.                                     map=(map>>6)*25;  //由于分辨率為0.25        所以擴大25倍便于顯示
  124.                                         Time[14]=map%10;
  125.                                         Time[15]=map/10%10;
  126.                                 }
  127.                                    else         //零下溫度轉換—零下是以2的補碼形式存儲的
  128.                                 {        Led_buff[0] = 0xa6;
  129.                                         wend=map;                 //單字節轉換雙字節
  130.                                         wend=wend<<2;         //移出兩位放溫度的低位
  131.                                         map=read_byte(DS3231_TEMPERATUREL);    //讀溫度低字節
  132.                                         map=map>>6;                 //由于2位放在頭兩位上,移到低位
  133.                                         wend=wend+map;         //組成10位的2進制的溫度編碼
  134.                                         wend=(~wend)+1;         //負數是以2的補碼形式存儲的,轉為原碼
  135.                                         wend=wend&0x03ff;//10位的2進制的溫度編碼,截去無用位
  136.                                         map= wend&0x0003;//分離低兩位,作為小數位
  137.                                         map= map*25;          //由于分辨率為0.25        所以擴大25倍便于顯示
  138.                                         Time[14]=map%10;
  139.                                         Time[15]=map/10%10;
  140.                                         wend=wend>>2;         //整數位處理
  141.                                         Time[16]=wend%10;
  142.                                     Time[17]=wend/10%10;        
  143.                                 }        
  144.         
  145.                                 if((ling==0) && (Time[L_u[17]]==0))         //判斷數碼管首位零是否顯示
  146.                                 Led_buff[3]        = 0xff;
  147.                                 else
  148.                                 Led_buff[3]        = Led_Char[ Time[17]]; //整數位顯示兩位
  149.                                 Led_buff[2]        = Led_Char[ Time[16]];
  150.                                 Led_buff[1]        = Led_Char[ Time[15]]; //小數位顯示一位
  151.                                 
  152.                                 write_byte(DS3231_CONTROL, 0x3C);  //溫度強制轉換—準備下次讀取
  153.                  }

  154.                  //長按鍵處理
  155.          if(BianJi_c==1)
  156.                  {           BianJi_c=0;
  157.                                 KEY1=1;
  158.                                  BianJi++;
  159.                                 if(BianJi==1)         //進入溫度顯示
  160.                             {  WenDu = 1; }
  161.                                 if(BianJi==2)        //進入首位數碼管修改位
  162.                             {        Led_buff[3]        = Led_Char[ Time[L_u[3]]];
  163.                                         Led_buff[2]        = 0xbf;
  164.                                         Led_buff[1]        = 0xbf;
  165.                                         Led_buff[0]        = 0xbf;
  166.                             }
  167.                                 if(BianJi==3)  //進入第二位數碼管修改位
  168.                             {        Led_buff[3]        = 0xbf;
  169.                                         Led_buff[2]        = Led_Char[ Time[L_u[2]]];
  170.                                         if(Time[L_u[3]]==2 && Time[L_u[2]]>3) //若為24小時制 首位為2則壓縮次位的修改范圍
  171.                                         {   Time[L_u[2]]=3;
  172.                                                 Anjian_d(L_u[2],3);
  173.                                         }        
  174.                             }
  175.                             if(BianJi==4)  //進入第三位數碼管修改位
  176.                             {        Led_buff[2]        = 0xbf;
  177.                                         Led_buff[1]        = Led_Char[ Time[L_u[1]]];               
  178.                             }
  179.                                 if(BianJi==5)  //進入第四位數碼管修改位
  180.                             {        Led_buff[1]        = 0xbf;
  181.                                     Led_buff[0]        = Led_Char[ Time[L_u[0]]];                        
  182.                             }
  183.                                 if(BianJi==6)  //進入數碼管首位零是否顯示,修改選項         顯示零:ON         不顯示零:OFF
  184.                                  {    if(ling==0)
  185.                                           {        Led_buff[3]        = 0xff;  
  186.                                                 Led_buff[2]        = 0xC0;
  187.                                                 Led_buff[1]        = 0x8E;
  188.                                                 Led_buff[0]        = 0x8E;
  189.                                           }
  190.                                           else
  191.                                           {        Led_buff[3]        = 0xff;  
  192.                                                 Led_buff[2]        = 0xff;
  193.                                                 Led_buff[1]        = 0xC0;
  194.                                                 Led_buff[0]        = 0xc8;
  195.                                           }
  196.                                 }
  197.                                 if(BianJi==7)  //退出編輯模式
  198.                             { BianJi=0; }
  199.                                    
  200.                  }
  201.                  //短按鍵處理        
  202.          if(BianJi_d==1)
  203.                  {          BianJi_d=0;
  204.                                 if(BianJi==1) //退出編輯模式
  205.                             {        BianJi=0;  }
  206.                                 if(BianJi==2) //首位數碼管修改位
  207.                             {  Anjian_d(L_u[3],2);}
  208.                                 if(BianJi==3) //第二位數碼管修改位
  209.                             {        if(Time[L_u[3]]==2 )
  210.                                         { Anjian_d(L_u[2],3); }
  211.                                     else
  212.                                     { Anjian_d(L_u[2],9); }
  213.                                                 
  214.                             }
  215.                             if(BianJi==4) //第三位數碼管修改位
  216.                             {  Anjian_d(L_u[1],5); }
  217.                                 if(BianJi==5) //第四位數碼管修改位
  218.                             {  Anjian_d(L_u[0],9); }
  219.                                 if(BianJi==6) //進入數碼管首位零是否顯示,修改選項         顯示零:ON         不顯示零:OFF
  220.                             {
  221.                                           if(ling==0)
  222.                                           {        ling = 1;
  223.                                             Led_buff[3]        = 0xff;  
  224.                                                 Led_buff[2]        = 0xff;
  225.                                                 Led_buff[1]        = 0xC0;
  226.                                                 Led_buff[0]        = 0xc8;
  227.                                                 write_byte_E2(ling);         
  228.                                           }
  229.                                           else
  230.                                           {        ling = 0;
  231.                                             Led_buff[3]        = 0xff;  
  232.                                                 Led_buff[2]        = 0xC0;
  233.                                                 Led_buff[1]        = 0x8E ;
  234.                                                 Led_buff[0]        = 0x8E;
  235.                                                 write_byte_E2(ling);        
  236.                                   }
  237.                         }

  238.                            
  239.                  }                 

  240.          }

  241. }

  242. //短按鍵處理
  243. void Anjian_d(u8 addr, u8 map)
  244. {   
  245.          u8 i;

  246.      Time[addr]++; //時間變量
  247.          if(Time[addr]>map)         //時間變量最大值
  248.          Time[addr]=0;                 
  249.          if((addr%2)==0)  //計算傳入值時十位或個位  0:各位  1:十位
  250.          i = Time[addr+1]*10+Time[addr]; //十位個位組成數值待寫入DS3231
  251.          else
  252.          i = Time[addr]*10+Time[addr-1]; //十位個位組成數值待寫入DS3231
  253.          Led_buff[5-BianJi] = Led_Char[ Time[addr]]; //修改的值顯示到數碼管上
  254.          write_byte(addr/2,HEX2BCD(i)); //寫入DS3231
  255.          
  256. }

  257. /* 配置并啟動T0,ms-T0定時時間 */
  258. void ConfigTimer0(u8 ms)
  259. {
  260.     unsigned long tmp;  //臨時變量
  261.    
  262.     tmp = 12000000 / 12;      //定時器計數頻率
  263.     tmp = (tmp * ms) / 1000;  //計算所需的計數值
  264.     tmp = 65536 - tmp;        //計算定時器重載值
  265.     TMOD &= 0xF0;   //清零T0的控制位
  266.     TH0 = (u8)(tmp>>8);  //定時器重載值拆分為高低字節
  267.     TL0 = (u8)tmp;
  268.     ET0 = 1;        //使能T0中斷
  269.     TR0 = 1;        //啟動T0
  270. }
  271. //中斷定義為5毫秒
  272. void InterruptTimer0() interrupt 1
  273. {        
  274.         static        u8 Di;
  275.          //非編輯模式進入
  276.          if(BianJi==0)
  277.          {
  278.              Di++;
  279.                  if(Di==100)
  280.                  {BP=1;}          //秒顯示賦值 0.5秒
  281.                  if(Di==200)
  282.                  {   
  283.                      Di=0;
  284.                      BiaoJi=1; //一秒一次讀DS3231時間,并寫入數碼管緩沖區的標記
  285.                          BP=0;           //秒顯示賦值 0.5秒
  286.                  }
  287.          }
  288.          //編輯模式(1)進入
  289.          if(BianJi==1)
  290.          {        Di++;
  291.                 if(Di==200)
  292.                 { Di=0; WenDu = 1;}        //一秒一次讀DS3231溫度,并寫入數碼管緩沖區的標記
  293.          }
  294.          
  295.      Led_can();         //數碼管刷新
  296.          anjian();         //按鍵掃描
  297.          WDT_CONTR=0x37;           //看門狗刷新  8.4S

  298. }
  299. //E2PROM-寫一個字節數據到時鐘芯片
  300. void write_byte_E2( u8 write_data)        
  301. {         

  302.      I2CStart();      //產生總線起始信號
  303.      I2CWrite(E2PROM_WriteAddress);  //<<<<I2C總線寫操作  E2PROM-器件碼
  304.      I2CWrite(0);     //                                   E2PROM-存儲空間高八位地址
  305.          I2CWrite(1);     //                                   E2PROM-存儲空間低八位地址
  306.      I2CWrite(write_data);  //             寫數據         
  307.      I2CStop();       //產生總線停止信號   
  308.    
  309. }

  310. //E2PROM-讀一個字節數據到時鐘芯片
  311. u8 read_byte_E2()
  312. {
  313.          char temp;

  314.      I2CStart();      //產生總線起始信號
  315.          I2CWrite(E2PROM_WriteAddress);  //<<<<I2C總線寫操作 E2PROM-器件碼
  316.      I2CWrite(0);     //                       E2PROM-存儲空間高八位地址
  317.          I2CWrite(1);     //                      E2PROM-存儲空間低八位地址
  318.          I2CStart();      //產生總線起始信號
  319.          I2CWrite(E2PROM_WriteAddress|1);     //從寫                E2PROM-器件碼
  320.          temp = I2CReadNAK();  //             讀數據-發送非應答信號,不讀了
  321.      I2CStop();       //產生總線停止信號
  322.      return(temp);
  323. }

  324. //DS3231_寫一個字節數據到時鐘芯片
  325. void write_byte(u8 addr, u8 write_data)        
  326. {         

  327.      I2CStart();  //產生總線起始信號
  328.      I2CWrite(DS3231_WriteAddress);  //<<<<I2C總線寫操作
  329.      I2CWrite(addr);  //<<<<I2C總線寫操作
  330.      I2CWrite(write_data);  //<<<<I2C總線寫操作         
  331.      I2CStop();   //產生總線停止信號   
  332.    
  333. }

  334. //DS3231_讀一個字節數據到時鐘芯片
  335. u8 read_byte(u8 random_addr)
  336. {
  337.          char temp;

  338.      I2CStart();  //產生總線起始信號
  339.          I2CWrite(DS3231_WriteAddress);  //<<<<I2C總線寫操作 器件碼
  340.      I2CWrite(random_addr);  //<<<<存儲空間地址
  341.          I2CStart();  //產生總線起始信號
  342. ……………………

  343. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼


所有資料51hei提供下載:
實時時鐘.rar (145.56 KB, 下載次數: 369)


評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

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

使用道具 舉報

沙發
ID:259274 發表于 2017-12-18 23:21 | 只看該作者
樓主方便嗎?加我QQ1094883144,想問問 問題
回復

使用道具 舉報

板凳
ID:231936 發表于 2018-1-3 14:26 | 只看該作者
樓主這個程序電路都有問題,能不能實物點亮。
回復

使用道具 舉報

地板
ID:58730 發表于 2018-3-4 13:12 | 只看該作者
謝謝分享
回復

使用道具 舉報

5#
ID:287653 發表于 2018-3-5 10:28 | 只看該作者
很棒!!!
回復

使用道具 舉報

6#
ID:96881 發表于 2018-4-4 21:27 | 只看該作者
不錯的資料,學習一下
回復

使用道具 舉報

7#
ID:183763 發表于 2018-4-26 21:13 | 只看該作者
仿制了一個不成功,秒點能閃爍,時間顯示68:08,而且不會變化,會是哪里出了問題
回復

使用道具 舉報

8#
ID:243262 發表于 2018-5-15 19:56 | 只看該作者
66666666
回復

使用道具 舉報

9#
ID:334781 發表于 2018-5-21 12:36 | 只看該作者
剛剛下載了,程序很完整,還沒有試呢,謝謝樓主!
回復

使用道具 舉報

10#
ID:310015 發表于 2018-5-26 16:49 | 只看該作者
下一個試一試感謝樓主
回復

使用道具 舉報

11#
ID:367948 發表于 2018-8-9 13:17 | 只看該作者
謝謝樓主
回復

使用道具 舉報

12#
ID:363686 發表于 2018-8-10 06:49 | 只看該作者
學習貼,收藏了,謝謝分享
回復

使用道具 舉報

13#
ID:371527 發表于 2018-8-19 16:54 | 只看該作者
數碼管的顯示就是功耗的問題
回復

使用道具 舉報

14#
ID:387328 發表于 2018-9-17 15:59 | 只看該作者
好貼,學習了。
回復

使用道具 舉報

15#
ID:299145 發表于 2018-10-7 19:11 | 只看該作者
謝謝分享!!哈哈
回復

使用道具 舉報

16#
ID:101808 發表于 2018-10-10 18:00 | 只看該作者
這焊接技術,膜拜中
回復

使用道具 舉報

17#
ID:57984 發表于 2018-11-11 14:56 | 只看該作者
非常好的例程,照著做就可以了,謝謝
回復

使用道具 舉報

18#
ID:124234 發表于 2018-12-6 13:42 | 只看該作者
看著不錯,學習一下
回復

使用道具 舉報

19#
ID:59525 發表于 2019-1-1 16:49 | 只看該作者
這個電路有做成功的嗎??
回復

使用道具 舉報

20#
ID:237159 發表于 2019-6-4 01:42 | 只看該作者
感謝分享
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产精品91网站 | 亚欧洲精品在线视频免费观看 | 国产日韩欧美一区二区 | 欧美性影院| 精品美女在线观看 | 亚洲成人精 | 精品国产欧美一区二区 | 国产精品a久久久久 | 午夜av电影 | 国产成人精品福利 | 成人免费在线观看 | 国产伦一区二区三区四区 | 99国产精品久久久 | 一区二区视频在线 | 国产欧美视频一区二区 | 日韩久久久久久久久久久 | 欧美精品一区二区在线观看 | 欧美精品一区二区三区在线播放 | 欧美精品成人 | 国产欧美一区二区三区日本久久久 | 国产精品免费在线 | 亚洲成人精品一区二区 | 日韩在线一区二区 | 亚洲福利在线观看 | 久久国产精品无码网站 | 久久99国产精品 | 日本三级视频 | 97人人澡人人爽91综合色 | a级免费视频 | 日韩中文字幕区 | 丝袜 亚洲 另类 欧美 综合 | 欧美精品一区二区三 | 尤物视频在线免费观看 | 国产成人精品一区二 | 成人在线视频观看 | 国产精品亚洲视频 | 一区二区在线免费播放 | 91av在线看| 国产 亚洲 网红 主播 | 成人在线播放网址 | 伊人久操 |