欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
C語言日期與時間戳轉換 STM32F103 DS1302
[打印本頁]
作者:
1直到世界盡頭
時間:
2020-3-2 16:58
標題:
C語言日期與時間戳轉換 STM32F103 DS1302
由于公司項目原因 用到了DS1302
其中時間是由時間戳轉換成日期存到DS1302的 在網上查找過一些代碼 再加上自己的一些理解 將代碼提供出來
適用于 DS1302 的讀寫驅動 以及 時間戳轉日期 日期轉時間戳 DS1302是否掉電等問題。有需要的可以了解一下。
DS1302.c
#include "ds1302.h"
char PowerDown=0; //掉電標志 如果為 1 說明掉過電
extern volatile u32 system_time; //系統時間
struct DS1302DATA ds1302Data = {0,0,0,0,0,0,0};
u8 ascii_time[7] = {0}; //保存ascii格式數據
u8 bcd_time[7] = {0}; //保存bcd碼數據
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);
}
//讀取一個字節的時序
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;
}
//寫入一個字節的時序
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當前時鐘運行還是停止
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); //打開寫保護
}
//讀取一個字節
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轉為UTC 已進行時區轉換 北京時間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 ; //時區矯正 轉為UTC+8 bylzs
seconds/=60;
ds1302Data.hour=seconds % 24;//獲得時
days=seconds/24;//獲得總天數
leap_y_count=(days + 365)/1461;//過去了多少個閏年(4年一閏)
if(((days + 366)%1461)==0)
{//閏年的最后1天
ds1302Data.year=1970+(days/366);//獲得年
ds1302Data.month=12; //調整月
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; //閏年調整
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; //調整月
ds1302Data.day=days; //獲得日
}
typedef struct t_xtime {
int year; int month; int day;
int hour; int minute; int second;
} _xtime ;
#define xMINUTE (60) //1分的秒數
#define xHOUR (60*xMINUTE) //1小時的秒數
#define xDAY (24*xHOUR) //1天的秒數
#define xYEAR (365*xDAY) //1年的秒數
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); //前幾年過去的秒數
seconds += month[ds1302Data.month-1]; //加上今年本月過去的秒數
if( (ds1302Data.month > 2) && (((year+2)%4)==0) )//2008年為閏年
seconds += xDAY; //閏年加1天秒數
seconds += xDAY*(ds1302Data.day-1); //加上本天過去的秒數
seconds += xHOUR*ds1302Data.hour; //加上本小時過去的秒數
seconds += xMINUTE*ds1302Data.min; //加上本分鐘過去的秒數
seconds += ds1302Data.sec; //加上當前秒數<br> seconds -= 8 * xHOUR;
return seconds;
}
//讀取日期轉時間戳 本地時間
void Read_TimeStamp(void)
{
Ds1302_Readtime();
system_time=xDate2Seconds();
}
//時間戳轉日期 寫入DS1302
void Write_TimeStamp(unsigned int secon)
{
xSeconds2Date(secon);
Ds1302_Write_Time_All(0);
PowerDown=0;
Ds1302_Write(DS1302_RAM_BASE,0x55); // RAM中掉電會丟失
}
復制代碼
DS1302.h
#ifndef __DS1302_H
#define __DS1302_H
#include "stm32f10x.h"
#include "delay.h"
extern u8 ascii_time[7]; //保存ascii格式數據
extern u8 bcd_time[7]; //保存bcd碼數據
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 //秒數據地址
#define DS1302_MIN_REG 0x82 //分數據地址
#define DS1302_HR_REG 0x84 //時數據地址
#define DS1302_DATE_REG 0x86 //日數據地址
#define DS1302_MONTH_REG 0x88 //月數據地址
#define DS1302_DAY_REG 0x8a //星期幾數據地址
#define DS1302_YEAR_REG 0x8c //年數據地址
#define DS1302_CONTROL_REG 0x8e //寫保護寄存器地址
#define DS1302_CHARGER_REG 0x90 //涓流充電寄存器
#define DS1302_CLKBURST_REG 0xbe //脈沖串寄存器
#define DS1302_RAM_BASE 0X30 //RAM基礎地址
#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
復制代碼
需要注意的是 DS1302的秒寄存器需要最高位置0,DS1302才能正常工作。
另外DS1302預留有RAM 可以通過讀取可以上電判斷是否DS1302掉過電
,掉電則需要時鐘更新 (掉電后時間不準確)。
作者:
喂豬兒
時間:
2020-4-28 19:37
你好,請教一下:在void DS1302_WriteByte(u8 dat)中“DAT_OUT = data&0x01;”報錯是什么原因呢?
作者:
Crazy·
時間:
2022-9-13 10:33
年應該用u16吧,u8不太夠
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1