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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

C語言日期與時間戳轉(zhuǎn)換 STM32F103 DS1302

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:323589 發(fā)表于 2020-3-2 16:58 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
由于公司項目原因 用到了DS1302 其中時間是由時間戳轉(zhuǎn)換成日期存到DS1302的 在網(wǎng)上查找過一些代碼 再加上自己的一些理解 將代碼提供出來
適用于 DS1302 的讀寫驅(qū)動 以及 時間戳轉(zhuǎn)日期 日期轉(zhuǎn)時間戳 DS1302是否掉電等問題。有需要的可以了解一下。  DS1302.c

  1. #include "ds1302.h"

  2. char PowerDown=0;            //掉電標志 如果為 1 說明掉過電
  3. extern volatile u32 system_time;   //系統(tǒng)時間

  4. struct DS1302DATA ds1302Data = {0,0,0,0,0,0,0};
  5. u8 ascii_time[7] = {0};     //保存ascii格式數(shù)據(jù)

  6. u8 bcd_time[7] = {0};       //保存bcd碼數(shù)據(jù)

  7. static u8 AsciiToBcd(u8 asciiData)
  8. {
  9.     u8 bcdData = 0;
  10.     bcdData = (((asciiData/10)<<4)|((asciiData%10)));
  11.     return bcdData;
  12. }
  13. static u8 BcdToAscii(u8 bcdData)
  14. {
  15.     u8 asciiData = 0;
  16.     asciiData = (((bcdData&0xf0)>>4)*10 + (bcdData&0x0f));
  17.     return asciiData;
  18. }

  19. //IO口初始化
  20. void Ds1302_Gpio_Init(void)
  21. {
  22.     GPIO_InitTypeDef GPIO_InitStructure;
  23.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
  24.    
  25.     //RST
  26.     GPIO_InitStructure.GPIO_Pin =GPIO_Pin_12;      
  27.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  28.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
  29.     GPIO_Init(GPIOD, &GPIO_InitStructure);
  30.    
  31.     //CLK
  32.     GPIO_InitStructure.GPIO_Pin =GPIO_Pin_10;      
  33.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  34.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
  35.     GPIO_Init(GPIOD, &GPIO_InitStructure);
  36.    
  37.     //IO
  38.     GPIO_InitStructure.GPIO_Pin =GPIO_Pin_11;      
  39.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  40.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
  41.     GPIO_Init(GPIOD, &GPIO_InitStructure);
  42. }

  43. //讀取一個字節(jié)的時序
  44. u8 Ds1302_ReadByte(void)
  45. {
  46.     u8 i = 0, dat = 0;
  47.     DS1302_DAT_INPUT();
  48.     delay_us(5);
  49.     for(i = 0; i <8; i++)
  50.     {
  51.         dat >>= 1;
  52.         if(DS1302_DATIN == 1)dat |= 0x80;
  53.         DS1302_CLK = 1;
  54.         delay_us(2);
  55.         DS1302_CLK = 0;
  56.         delay_us(2);
  57.     }
  58.     return dat;
  59. }

  60. //寫入一個字節(jié)的時序
  61. void Ds1302_WriteByte(u8 dat)
  62. {
  63.     u8 i = 0, data = dat;
  64.     DS1302_DAT_OUTPUT();
  65.     DS1302_CLK = 0;
  66.     delay_us(2);
  67.     for(i = 0; i < 8; i++)
  68.     {
  69.         DS1302_DATOUT = data&0x01;
  70.         delay_us(2);
  71.         DS1302_CLK = 1;
  72.         delay_us(2);
  73.         DS1302_CLK = 0;
  74.         data >>= 1;
  75.     }
  76. }

  77. //寫入一個寄存器
  78. void Ds1302_Write(u8 address,u8 dat)
  79. {
  80.     DS1302_RST = 0;
  81.     DS1302_CLK = 0;
  82.     DS1302_RST = 1;
  83.     Ds1302_WriteByte(address);
  84.     Ds1302_WriteByte(dat);
  85.     DS1302_CLK = 1;
  86.     DS1302_RST = 0;
  87. }

  88. //單個寫入時間
  89. void Ds1302_Write_Time_Singel(u8 address,u8 dat)
  90. {
  91.     Ds1302_Write(DS1302_CONTROL_REG,0x00);  //取消寫保護
  92.     Ds1302_Write(address,dat);
  93.     Ds1302_Write(DS1302_CONTROL_REG,0x80);  //打開寫保護
  94. }

  95. //一次完成所有時間更新
  96. //start當(dāng)前時鐘運行還是停止
  97. void Ds1302_Write_Time_All(u8 start)
  98. {
  99.     Ds1302_Write(DS1302_CONTROL_REG,0x00);      //取消寫保護
  100.     Ds1302_Write(DS1302_SEC_REG,(AsciiToBcd(ds1302Data.sec)|start));
  101.     Ds1302_Write(DS1302_MIN_REG,AsciiToBcd(ds1302Data.min));
  102.     Ds1302_Write(DS1302_HR_REG,AsciiToBcd(ds1302Data.hour));
  103.     Ds1302_Write(DS1302_DATE_REG,AsciiToBcd(ds1302Data.day));
  104.     Ds1302_Write(DS1302_MONTH_REG,AsciiToBcd(ds1302Data.month));
  105.     Ds1302_Write(DS1302_DAY_REG,AsciiToBcd(ds1302Data.week));
  106.     Ds1302_Write(DS1302_YEAR_REG,AsciiToBcd(ds1302Data.year));
  107.     Ds1302_Write(DS1302_CONTROL_REG,0x80);  //打開寫保護
  108. }


  109. //讀取一個字節(jié)
  110. u8 Ds1302_Read(u8 address)
  111. {
  112.     u8 data = 0;
  113.     DS1302_RST = 0;
  114.     DS1302_CLK = 0;
  115.     DS1302_RST = 1;
  116.     Ds1302_WriteByte(address|0x01); //讀取地址需要與0x01相或,最低為變成1
  117.     data = Ds1302_ReadByte();
  118.     DS1302_CLK = 1;
  119.     DS1302_RST = 0;
  120.     return data;
  121. }

  122. //讀取時間的時候默認讓時間走起來
  123. void Ds1302_Readtime(void)
  124. {
  125.     ds1302Data.sec = BcdToAscii(Ds1302_Read(DS1302_SEC_REG));  //秒
  126.     ds1302Data.min = BcdToAscii(Ds1302_Read(DS1302_MIN_REG));  //分
  127.     ds1302Data.hour = BcdToAscii(Ds1302_Read(DS1302_HR_REG));   //小時
  128.     ds1302Data.day = BcdToAscii(Ds1302_Read(DS1302_DATE_REG)); //日
  129.     ds1302Data.month = BcdToAscii(Ds1302_Read(DS1302_MONTH_REG)); //月
  130.     ds1302Data.week = BcdToAscii(Ds1302_Read(DS1302_DAY_REG));  //星期幾
  131.     ds1302Data.year = BcdToAscii(Ds1302_Read(DS1302_YEAR_REG)); //年

  132. }
  133. //判斷DS1302是否掉過電
  134. void Time_correct()
  135. {
  136.    
  137.   if(Ds1302_Read(DS1302_RAM_BASE)!=0x55)   //掉過電
  138.   {
  139.         Ds1302_Readtime();
  140.     PowerDown=1;
  141.   }
  142. //   Ds1302_Write(DS1302_RAM_BASE,0x55);   //  RAM中掉電會丟失

  143. }

  144. //UNIX轉(zhuǎn)為UTC 已進行時區(qū)轉(zhuǎn)換 北京時間UTC+8
  145. void xSeconds2Date(unsigned int seconds)
  146. {
  147.     static unsigned int month[12]={
  148.         /*01月*/31,
  149.         /*02月*/28,
  150.         /*03月*/31,
  151.         /*04月*/30,
  152.         /*05月*/31,
  153.         /*06月*/30,
  154.         /*07月*/31,
  155.         /*08月*/31,
  156.         /*09月*/30,
  157.         /*10月*/31,
  158.         /*11月*/30,
  159.         /*12月*/31
  160.     };
  161.     unsigned int days;
  162.     unsigned short leap_y_count;
  163.     ds1302Data.sec=seconds%60;//獲得秒
  164.     seconds/=60;
  165.     ds1302Data.min=seconds%60;//獲得分
  166.     seconds+=8*60 ;        //時區(qū)矯正 轉(zhuǎn)為UTC+8 bylzs
  167.     seconds/=60;
  168.     ds1302Data.hour=seconds % 24;//獲得時
  169.     days=seconds/24;//獲得總天數(shù)
  170.     leap_y_count=(days + 365)/1461;//過去了多少個閏年(4年一閏)
  171.     if(((days + 366)%1461)==0)
  172.     {//閏年的最后1天
  173.         ds1302Data.year=1970+(days/366);//獲得年
  174.         ds1302Data.month=12;              //調(diào)整月
  175.         ds1302Data.day=31;
  176.         return;
  177.     }
  178.     days-=leap_y_count;
  179.     ds1302Data.year=1970+(days/365);     //獲得年
  180.     days%=365;                       //今年的第幾天
  181.     days=01+days;                  //1日開始
  182.     if((ds1302Data.year%4)==0)
  183.     {
  184.         if(days>60)--days;            //閏年調(diào)整
  185.         else
  186.         {
  187.             if(days == 60)
  188.             {
  189.                 ds1302Data.month=2;
  190.                 ds1302Data.day=29;
  191.                 return;
  192.             }
  193.         }
  194.     }
  195.     for(ds1302Data.month= 0;month[ds1302Data.month]<days;ds1302Data.month++)
  196.     {
  197.         days-=month[ds1302Data.month];
  198.     }
  199.     ++ds1302Data.month;               //調(diào)整月
  200.     ds1302Data.day=days;           //獲得日
  201. }
  202. typedef struct t_xtime {
  203.   int year; int month;  int day;  
  204.   int hour; int minute;  int second;
  205. } _xtime ;

  206. #define xMINUTE   (60) //1分的秒數(shù)
  207. #define xHOUR     (60*xMINUTE) //1小時的秒數(shù)
  208. #define xDAY      (24*xHOUR) //1天的秒數(shù)
  209. #define xYEAR     (365*xDAY) //1年的秒數(shù)
  210. unsigned int  xDate2Seconds()
  211. {
  212.   static unsigned int  month[12]={
  213.     /*01月*/xDAY*(0),
  214.     /*02月*/xDAY*(31),
  215.     /*03月*/xDAY*(31+28),
  216.     /*04月*/xDAY*(31+28+31),
  217.     /*05月*/xDAY*(31+28+31+30),
  218.     /*06月*/xDAY*(31+28+31+30+31),
  219.     /*07月*/xDAY*(31+28+31+30+31+30),
  220.     /*08月*/xDAY*(31+28+31+30+31+30+31),
  221.     /*09月*/xDAY*(31+28+31+30+31+30+31+31),
  222.     /*10月*/xDAY*(31+28+31+30+31+30+31+31+30),
  223.     /*11月*/xDAY*(31+28+31+30+31+30+31+31+30+31),
  224.     /*12月*/xDAY*(31+28+31+30+31+30+31+31+30+31+30)
  225.   };
  226.   unsigned int  seconds = 0;
  227.   unsigned int  year = 0;
  228.   year=ds1302Data.year-1970;       //不考慮2100年千年蟲問題
  229.   seconds = xYEAR*year + xDAY*((year+1)/4);  //前幾年過去的秒數(shù)
  230.   seconds += month[ds1302Data.month-1];      //加上今年本月過去的秒數(shù)
  231.   if( (ds1302Data.month > 2) && (((year+2)%4)==0) )//2008年為閏年
  232.     seconds += xDAY;            //閏年加1天秒數(shù)
  233.   seconds += xDAY*(ds1302Data.day-1);         //加上本天過去的秒數(shù)
  234.   seconds += xHOUR*ds1302Data.hour;           //加上本小時過去的秒數(shù)
  235.   seconds += xMINUTE*ds1302Data.min;       //加上本分鐘過去的秒數(shù)
  236.   seconds += ds1302Data.sec;               //加上當(dāng)前秒數(shù)<br> seconds -= 8 * xHOUR;
  237.   return seconds;
  238. }
  239. //讀取日期轉(zhuǎn)時間戳 本地時間
  240. void Read_TimeStamp(void)
  241. {
  242.   Ds1302_Readtime();
  243.   system_time=xDate2Seconds();
  244. }
  245. //時間戳轉(zhuǎn)日期 寫入DS1302
  246. void Write_TimeStamp(unsigned int secon)
  247. {
  248.   xSeconds2Date(secon);
  249.   
  250.   Ds1302_Write_Time_All(0);
  251.   PowerDown=0;
  252.   Ds1302_Write(DS1302_RAM_BASE,0x55);   //  RAM中掉電會丟失
  253. }
復(fù)制代碼
DS1302.h

  1. #ifndef __DS1302_H
  2. #define __DS1302_H
  3. #include "stm32f10x.h"
  4. #include "delay.h"
  5. extern u8 ascii_time[7];     //保存ascii格式數(shù)據(jù)

  6. extern u8 bcd_time[7];       //保存bcd碼數(shù)據(jù)

  7. typedef struct DS1302DATA
  8. {
  9.     u8 year;    //年
  10.     u8 month;   //月
  11.     u8 day;     //日
  12.     u8 hour;    //時
  13.     u8 min;     //分
  14.     u8 sec;     //秒
  15.     u8 week;    //周
  16. }DS1302DATA;

  17. extern struct DS1302DATA ds1302Data;

  18. #define DS1302_RST      PDout(12)
  19. #define DS1302_CLK      PDout(10)
  20. #define DS1302_DATIN    PDin(11)
  21. #define DS1302_DATOUT   PDout(11)

  22. #define DS1302_DAT_INPUT()     {GPIOD->CRH &= 0XFFFF0FFF;GPIOD->CRH|=8<<12;}
  23. #define DS1302_DAT_OUTPUT()    {GPIOD->CRH &= 0XFFFF0FFF;GPIOD->CRH|=3<<12;}

  24. //芯片寄存器地址定義 定義的寫地址,讀需要+1
  25. #define DS1302_SEC_REG                        0x80                //秒數(shù)據(jù)地址
  26. #define DS1302_MIN_REG                        0x82                //分數(shù)據(jù)地址
  27. #define DS1302_HR_REG                        0x84                //時數(shù)據(jù)地址
  28. #define DS1302_DATE_REG                        0x86                //日數(shù)據(jù)地址
  29. #define DS1302_MONTH_REG                0x88                //月數(shù)據(jù)地址
  30. #define DS1302_DAY_REG                        0x8a                //星期幾數(shù)據(jù)地址
  31. #define DS1302_YEAR_REG                        0x8c                //年數(shù)據(jù)地址
  32. #define DS1302_CONTROL_REG                0x8e                //寫保護寄存器地址
  33. #define DS1302_CHARGER_REG                0x90                 //涓流充電寄存器                         
  34. #define DS1302_CLKBURST_REG                0xbe             //脈沖串寄存器
  35. #define DS1302_RAM_BASE                 0X30            //RAM基礎(chǔ)地址

  36. #define CLOCKSTOP       0X80
  37. #define CLOCKSTART      0X00


  38. void Ds1302_Gpio_Init(void);
  39. void Ds1302_Write_Time_All(u8 start);
  40. void Ds1302_Readtime(void);
  41. void Time_correct();
  42. unsigned int  xDate2Seconds();
  43. void xSeconds2Date(unsigned int seconds);
  44. void Read_TimeStamp(void);
  45. void Write_TimeStamp(unsigned int secon);

  46. #endif
復(fù)制代碼
  需要注意的是 DS1302的秒寄存器需要最高位置0,DS1302才能正常工作。
另外DS1302預(yù)留有RAM 可以通過讀取可以上電判斷是否DS1302掉過電
,掉電則需要時鐘更新 (掉電后時間不準確)。



評分

參與人數(shù) 1黑幣 +100 收起 理由
admin + 100

查看全部評分

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

使用道具 舉報

沙發(fā)
ID:740359 發(fā)表于 2020-4-28 19:37 | 只看該作者
你好,請教一下:在void DS1302_WriteByte(u8 dat)中“DAT_OUT = data&0x01;”報錯是什么原因呢?
回復(fù)

使用道具 舉報

板凳
ID:564486 發(fā)表于 2022-9-13 10:33 | 只看該作者
年應(yīng)該用u16吧,u8不太夠
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 中文字幕一区二区三区在线乱码 | 午夜免费视频 | 在线观看国产视频 | pacopacomama在线 | 九色国产| 狠狠婷婷综合久久久久久妖精 | 天堂一区| 午夜视频一区二区三区 | 国产免费福利在线 | 欧美精品中文 | 在线黄色影院 | 成人h视频在线 | 午夜精品影院 | 亚洲第一av网站 | 国产精品99久久久久久人 | 99久久精品一区二区成人 | 日本午夜免费福利视频 | 欧美日韩国产一区二区三区 | 在线观看视频中文字幕 | 国产在线精品一区二区 | 久久综合狠狠综合久久综合88 | 精品一区二区三区中文字幕 | 国产精品一区二区久久久久 | 久操福利 | 精品乱码一区二区 | 亚洲一区二区三区免费视频 | 蜜桃传媒av | www.性色 | av网站在线播放 | 日韩在线免费视频 | 国产日韩欧美精品一区二区 | 中文字幕在线第二页 | 国产精品一区二区av | 亚洲国产一区二区三区 | 自拍偷拍视频网 | 国产精品7777777 | 天天综合永久 | 夜夜爽99久久国产综合精品女不卡 | 欧美性受 | 成人一级视频在线观看 | 国产高清精品一区二区三区 |