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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

STC15F104W單片機+DS3231實時時鐘PADS9.5原理圖+源程序

[復制鏈接]
跳轉到指定樓層
樓主
實時時鐘資料:


單片機源程序如下:
  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.          I2CWrite(DS3231_ReadAddress);  ////從寫  器件碼  
  343.          temp = I2CReadNAK();       //<<<<I2C總線讀操作,并發送非應答信號,不讀了
  344.      I2CStop();   //產生總線停止信號
  345.      return(temp);
  346. }

  347. //BCD轉換為Byte
  348. u8 BCD2HEX(u8 val)   
  349. {
  350.      u8 temp;
  351.      temp=val&0x0f;
  352.      val>>=4;
  353.      val*=10;
  354.      temp+=val;
  355.    
  356.      return temp;
  357. }
  358. //Byte碼轉換為BCD碼
  359. u8 HEX2BCD(u8 val)   
  360. {
  361.      u8 temp;
  362.      temp=(val/10%10)<<4;
  363.          temp=temp+val%10;
  364.      return temp;
  365. }
  366. //按鈕掃描         需在定時中斷中調用
  367. void anjian()
  368. {        static u16 JiShu=0;
  369.     static u8 keybuf = 0xff;

  370.         keybuf = (keybuf <<1) |KEY1;
  371.         if(keybuf == 0x00)
  372.         { JiShu++; if(JiShu>=300) JiShu=300; }
  373.         else if(keybuf == 0xFF)
  374.         {
  375.              if(JiShu>=300)
  376.              {   BianJi_c=1;  }        //大于1.5秒,長按鍵標記置1
  377.                  else if(BianJi>=1 && JiShu>0 )
  378.                  {         BianJi_d=1;  }        //小于1.5秒,短按鍵標記置1
  379.                    JiShu=0;
  380.         }

  381. }
復制代碼

所有資料51hei提供下載:
實時時鐘.zip (169.17 KB, 下載次數: 164)


評分

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

查看全部評分

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

使用道具 舉報

沙發
ID:1 發表于 2018-12-2 02:08 | 只看該作者
好資料,51黑有你更精彩!!!
回復

使用道具 舉報

板凳
ID:353831 發表于 2019-12-14 10:17 | 只看該作者
樓主 下載的壓縮包里沒有原理圖,另外問一下用的什么型號的單片機?
回復

使用道具 舉報

地板
ID:499081 發表于 2020-11-10 07:37 | 只看該作者
wl020807 發表于 2019-12-14 10:17
樓主 下載的壓縮包里沒有原理圖,另外問一下用的什么型號的單片機?

15f104
回復

使用道具 舉報

5#
ID:227504 發表于 2020-11-24 09:28 | 只看該作者
樓主,什么數碼管驅動芯片?
回復

使用道具 舉報

6#
ID:227504 發表于 2020-11-24 09:34 | 只看該作者
樓主,原理圖打不開,可以生成PDF文件嗎?
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 激情六月丁香 | av中文字幕在线 | www.久草.com | 久久天堂| 日韩欧美视频 | 国产高清在线观看 | 日日夜夜免费精品视频 | 人人人艹 | 欧美日韩一区不卡 | 免费在线一区二区 | 久久777 | 欧美黄视频| 日韩欧美国产一区二区 | 欧美亚洲国产日韩 | 亚洲视频免费播放 | 国产精品免费观看 | 欧美精品一区在线发布 | 国产精品视频久久久 | 伊人久久综合 | a国产一区二区免费入口 | 欧美a级网站 | 久久精品欧美一区二区三区不卡 | 日韩国产精品一区二区三区 | av男人的天堂在线 | 欧美精品福利 | 欧美一区二区三区在线播放 | 国产区精品在线观看 | 91av视频| 黄色网毛片| 免费黄色录像视频 | 欧洲国产精品视频 | 国产精品亚洲欧美日韩一区在线 | 国产欧美日韩精品一区 | 欧美黄色片| 欧美日本高清 | 精品视频一区二区三区四区 | 国产一区二区在线视频 | 亚洲午夜视频 | 久久小视频 | 在线三级网址 | 成人小视频在线观看 |