|
由于公司項目原因 用到了DS1302 其中時間是由時間戳轉(zhuǎn)換成日期存到DS1302的 在網(wǎng)上查找過一些代碼 再加上自己的一些理解 將代碼提供出來
適用于 DS1302 的讀寫驅(qū)動 以及 時間戳轉(zhuǎn)日期 日期轉(zhuǎn)時間戳 DS1302是否掉電等問題。有需要的可以了解一下。 DS1302.c
- #include "ds1302.h"
- char PowerDown=0; //掉電標志 如果為 1 說明掉過電
- extern volatile u32 system_time; //系統(tǒng)時間
- struct DS1302DATA ds1302Data = {0,0,0,0,0,0,0};
- u8 ascii_time[7] = {0}; //保存ascii格式數(shù)據(jù)
-
- u8 bcd_time[7] = {0}; //保存bcd碼數(shù)據(jù)
-
- static u8 AsciiToBcd(u8 asciiData)
- {
- u8 bcdData = 0;
- bcdData = (((asciiData/10)<<4)|((asciiData%10)));
- return bcdData;
- }
- static u8 BcdToAscii(u8 bcdData)
- {
- u8 asciiData = 0;
- asciiData = (((bcdData&0xf0)>>4)*10 + (bcdData&0x0f));
- return asciiData;
- }
-
- //IO口初始化
- void Ds1302_Gpio_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
-
- //RST
- GPIO_InitStructure.GPIO_Pin =GPIO_Pin_12;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
- GPIO_Init(GPIOD, &GPIO_InitStructure);
-
- //CLK
- GPIO_InitStructure.GPIO_Pin =GPIO_Pin_10;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
- GPIO_Init(GPIOD, &GPIO_InitStructure);
-
- //IO
- GPIO_InitStructure.GPIO_Pin =GPIO_Pin_11;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
- GPIO_Init(GPIOD, &GPIO_InitStructure);
- }
-
- //讀取一個字節(jié)的時序
- u8 Ds1302_ReadByte(void)
- {
- u8 i = 0, dat = 0;
- DS1302_DAT_INPUT();
- delay_us(5);
- for(i = 0; i <8; i++)
- {
- dat >>= 1;
- if(DS1302_DATIN == 1)dat |= 0x80;
- DS1302_CLK = 1;
- delay_us(2);
- DS1302_CLK = 0;
- delay_us(2);
- }
- return dat;
- }
-
- //寫入一個字節(jié)的時序
- void Ds1302_WriteByte(u8 dat)
- {
- u8 i = 0, data = dat;
- DS1302_DAT_OUTPUT();
- DS1302_CLK = 0;
- delay_us(2);
- for(i = 0; i < 8; i++)
- {
- DS1302_DATOUT = data&0x01;
- delay_us(2);
- DS1302_CLK = 1;
- delay_us(2);
- DS1302_CLK = 0;
- data >>= 1;
- }
- }
-
- //寫入一個寄存器
- void Ds1302_Write(u8 address,u8 dat)
- {
- DS1302_RST = 0;
- DS1302_CLK = 0;
- DS1302_RST = 1;
- Ds1302_WriteByte(address);
- Ds1302_WriteByte(dat);
- DS1302_CLK = 1;
- DS1302_RST = 0;
- }
-
- //單個寫入時間
- void Ds1302_Write_Time_Singel(u8 address,u8 dat)
- {
- Ds1302_Write(DS1302_CONTROL_REG,0x00); //取消寫保護
- Ds1302_Write(address,dat);
- Ds1302_Write(DS1302_CONTROL_REG,0x80); //打開寫保護
- }
-
- //一次完成所有時間更新
- //start當(dāng)前時鐘運行還是停止
- void Ds1302_Write_Time_All(u8 start)
- {
- Ds1302_Write(DS1302_CONTROL_REG,0x00); //取消寫保護
- Ds1302_Write(DS1302_SEC_REG,(AsciiToBcd(ds1302Data.sec)|start));
- Ds1302_Write(DS1302_MIN_REG,AsciiToBcd(ds1302Data.min));
- Ds1302_Write(DS1302_HR_REG,AsciiToBcd(ds1302Data.hour));
- Ds1302_Write(DS1302_DATE_REG,AsciiToBcd(ds1302Data.day));
- Ds1302_Write(DS1302_MONTH_REG,AsciiToBcd(ds1302Data.month));
- Ds1302_Write(DS1302_DAY_REG,AsciiToBcd(ds1302Data.week));
- Ds1302_Write(DS1302_YEAR_REG,AsciiToBcd(ds1302Data.year));
- Ds1302_Write(DS1302_CONTROL_REG,0x80); //打開寫保護
- }
-
-
- //讀取一個字節(jié)
- u8 Ds1302_Read(u8 address)
- {
- u8 data = 0;
- DS1302_RST = 0;
- DS1302_CLK = 0;
- DS1302_RST = 1;
- Ds1302_WriteByte(address|0x01); //讀取地址需要與0x01相或,最低為變成1
- data = Ds1302_ReadByte();
- DS1302_CLK = 1;
- DS1302_RST = 0;
- return data;
- }
-
- //讀取時間的時候默認讓時間走起來
- void Ds1302_Readtime(void)
- {
- ds1302Data.sec = BcdToAscii(Ds1302_Read(DS1302_SEC_REG)); //秒
- ds1302Data.min = BcdToAscii(Ds1302_Read(DS1302_MIN_REG)); //分
- ds1302Data.hour = BcdToAscii(Ds1302_Read(DS1302_HR_REG)); //小時
- ds1302Data.day = BcdToAscii(Ds1302_Read(DS1302_DATE_REG)); //日
- ds1302Data.month = BcdToAscii(Ds1302_Read(DS1302_MONTH_REG)); //月
- ds1302Data.week = BcdToAscii(Ds1302_Read(DS1302_DAY_REG)); //星期幾
- ds1302Data.year = BcdToAscii(Ds1302_Read(DS1302_YEAR_REG)); //年
- }
- //判斷DS1302是否掉過電
- void Time_correct()
- {
-
- if(Ds1302_Read(DS1302_RAM_BASE)!=0x55) //掉過電
- {
- Ds1302_Readtime();
- PowerDown=1;
- }
- // Ds1302_Write(DS1302_RAM_BASE,0x55); // RAM中掉電會丟失
-
- }
-
- //UNIX轉(zhuǎn)為UTC 已進行時區(qū)轉(zhuǎn)換 北京時間UTC+8
- void xSeconds2Date(unsigned int seconds)
- {
- static unsigned int month[12]={
- /*01月*/31,
- /*02月*/28,
- /*03月*/31,
- /*04月*/30,
- /*05月*/31,
- /*06月*/30,
- /*07月*/31,
- /*08月*/31,
- /*09月*/30,
- /*10月*/31,
- /*11月*/30,
- /*12月*/31
- };
- unsigned int days;
- unsigned short leap_y_count;
- ds1302Data.sec=seconds%60;//獲得秒
- seconds/=60;
- ds1302Data.min=seconds%60;//獲得分
- seconds+=8*60 ; //時區(qū)矯正 轉(zhuǎn)為UTC+8 bylzs
- seconds/=60;
- ds1302Data.hour=seconds % 24;//獲得時
- days=seconds/24;//獲得總天數(shù)
- leap_y_count=(days + 365)/1461;//過去了多少個閏年(4年一閏)
- if(((days + 366)%1461)==0)
- {//閏年的最后1天
- ds1302Data.year=1970+(days/366);//獲得年
- ds1302Data.month=12; //調(diào)整月
- ds1302Data.day=31;
- return;
- }
- days-=leap_y_count;
- ds1302Data.year=1970+(days/365); //獲得年
- days%=365; //今年的第幾天
- days=01+days; //1日開始
- if((ds1302Data.year%4)==0)
- {
- if(days>60)--days; //閏年調(diào)整
- else
- {
- if(days == 60)
- {
- ds1302Data.month=2;
- ds1302Data.day=29;
- return;
- }
- }
- }
- for(ds1302Data.month= 0;month[ds1302Data.month]<days;ds1302Data.month++)
- {
- days-=month[ds1302Data.month];
- }
- ++ds1302Data.month; //調(diào)整月
- ds1302Data.day=days; //獲得日
- }
- typedef struct t_xtime {
- int year; int month; int day;
- int hour; int minute; int second;
- } _xtime ;
-
- #define xMINUTE (60) //1分的秒數(shù)
- #define xHOUR (60*xMINUTE) //1小時的秒數(shù)
- #define xDAY (24*xHOUR) //1天的秒數(shù)
- #define xYEAR (365*xDAY) //1年的秒數(shù)
- unsigned int xDate2Seconds()
- {
- static unsigned int month[12]={
- /*01月*/xDAY*(0),
- /*02月*/xDAY*(31),
- /*03月*/xDAY*(31+28),
- /*04月*/xDAY*(31+28+31),
- /*05月*/xDAY*(31+28+31+30),
- /*06月*/xDAY*(31+28+31+30+31),
- /*07月*/xDAY*(31+28+31+30+31+30),
- /*08月*/xDAY*(31+28+31+30+31+30+31),
- /*09月*/xDAY*(31+28+31+30+31+30+31+31),
- /*10月*/xDAY*(31+28+31+30+31+30+31+31+30),
- /*11月*/xDAY*(31+28+31+30+31+30+31+31+30+31),
- /*12月*/xDAY*(31+28+31+30+31+30+31+31+30+31+30)
- };
- unsigned int seconds = 0;
- unsigned int year = 0;
- year=ds1302Data.year-1970; //不考慮2100年千年蟲問題
- seconds = xYEAR*year + xDAY*((year+1)/4); //前幾年過去的秒數(shù)
- seconds += month[ds1302Data.month-1]; //加上今年本月過去的秒數(shù)
- if( (ds1302Data.month > 2) && (((year+2)%4)==0) )//2008年為閏年
- seconds += xDAY; //閏年加1天秒數(shù)
- seconds += xDAY*(ds1302Data.day-1); //加上本天過去的秒數(shù)
- seconds += xHOUR*ds1302Data.hour; //加上本小時過去的秒數(shù)
- seconds += xMINUTE*ds1302Data.min; //加上本分鐘過去的秒數(shù)
- seconds += ds1302Data.sec; //加上當(dāng)前秒數(shù)<br> seconds -= 8 * xHOUR;
- return seconds;
- }
- //讀取日期轉(zhuǎn)時間戳 本地時間
- void Read_TimeStamp(void)
- {
- Ds1302_Readtime();
- system_time=xDate2Seconds();
- }
- //時間戳轉(zhuǎn)日期 寫入DS1302
- void Write_TimeStamp(unsigned int secon)
- {
- xSeconds2Date(secon);
-
- Ds1302_Write_Time_All(0);
- PowerDown=0;
- Ds1302_Write(DS1302_RAM_BASE,0x55); // RAM中掉電會丟失
- }
復(fù)制代碼 DS1302.h
- #ifndef __DS1302_H
- #define __DS1302_H
- #include "stm32f10x.h"
- #include "delay.h"
- extern u8 ascii_time[7]; //保存ascii格式數(shù)據(jù)
-
- extern u8 bcd_time[7]; //保存bcd碼數(shù)據(jù)
-
- typedef struct DS1302DATA
- {
- u8 year; //年
- u8 month; //月
- u8 day; //日
- u8 hour; //時
- u8 min; //分
- u8 sec; //秒
- u8 week; //周
- }DS1302DATA;
-
- extern struct DS1302DATA ds1302Data;
-
- #define DS1302_RST PDout(12)
- #define DS1302_CLK PDout(10)
- #define DS1302_DATIN PDin(11)
- #define DS1302_DATOUT PDout(11)
-
- #define DS1302_DAT_INPUT() {GPIOD->CRH &= 0XFFFF0FFF;GPIOD->CRH|=8<<12;}
- #define DS1302_DAT_OUTPUT() {GPIOD->CRH &= 0XFFFF0FFF;GPIOD->CRH|=3<<12;}
-
- //芯片寄存器地址定義 定義的寫地址,讀需要+1
- #define DS1302_SEC_REG 0x80 //秒數(shù)據(jù)地址
- #define DS1302_MIN_REG 0x82 //分數(shù)據(jù)地址
- #define DS1302_HR_REG 0x84 //時數(shù)據(jù)地址
- #define DS1302_DATE_REG 0x86 //日數(shù)據(jù)地址
- #define DS1302_MONTH_REG 0x88 //月數(shù)據(jù)地址
- #define DS1302_DAY_REG 0x8a //星期幾數(shù)據(jù)地址
- #define DS1302_YEAR_REG 0x8c //年數(shù)據(jù)地址
- #define DS1302_CONTROL_REG 0x8e //寫保護寄存器地址
- #define DS1302_CHARGER_REG 0x90 //涓流充電寄存器
- #define DS1302_CLKBURST_REG 0xbe //脈沖串寄存器
- #define DS1302_RAM_BASE 0X30 //RAM基礎(chǔ)地址
-
- #define CLOCKSTOP 0X80
- #define CLOCKSTART 0X00
-
-
- void Ds1302_Gpio_Init(void);
- void Ds1302_Write_Time_All(u8 start);
- void Ds1302_Readtime(void);
- void Time_correct();
- unsigned int xDate2Seconds();
- void xSeconds2Date(unsigned int seconds);
- void Read_TimeStamp(void);
- void Write_TimeStamp(unsigned int secon);
- #endif
復(fù)制代碼 需要注意的是 DS1302的秒寄存器需要最高位置0,DS1302才能正常工作。
另外DS1302預(yù)留有RAM 可以通過讀取可以上電判斷是否DS1302掉過電
,掉電則需要時鐘更新 (掉電后時間不準確)。
|
評分
-
查看全部評分
|