//C文件
/*************************************************************************************************************
?*?文件名: PCF8563.c
?*?功能: STM32?PCF8563?高精度?RTC?芯片驅動
?*?作者: cp1300@139.com
?*?創(chuàng)建時間: 2017-07-10
?*?最后修改時間: 2017-07-10
?*?詳細: 使用軟件IIC接口驅動
2017-07-13:通過寫入PCF8563_REG_CLKOUT與讀取PCF8563_REG_CLKOUT寄存器,發(fā)現(xiàn)某些不用的位會亂跳,最終發(fā)現(xiàn)時間寄存器也有同樣的問題,需要把不用的位都屏蔽掉
*************************************************************************************************************/
#include?"system.h"
#include?"delay.h"
#include?"PCF8563.h"
#include?"stdio.h"
#include?"SoftwareIIC.h"
//月修正數(shù)據(jù)表
static?u8?const?table_week[12]?=?{0,3,3,6,1,4,6,2,5,0,3,5};? ??
//平年的月份日期表
static?u8?const?mon_table[12]?=?{31,28,31,30,31,30,31,31,30,31,30,31};
static?bool?Is_Leap_Year(u16?year);
rtc_timer?ext_timer; //外部RTC時鐘
static?SIIC_HANDLE?IIC_Handel;
#define?PCF8563_SDA_GPIOx? GPIOC
#define?PCF8563_SCL_GPIOx? GPIOC
#define?PCF8563_SDA_Bit? 1
#define?PCF8563_SCL_Bit ? 13
//調試宏開關
#define?PCF8563_DBUG 1
#if?PCF8563_DBUG
#include?"system.h"
#define?PCF8563_Debug(format,...) uart_printf(format,##__VA_ARGS__)
#else
#define?PCF8563_Debug(format,...) /
/
#endif //PCF8563_DBUG
//PCF8563?iic總線地址
#define?PCF8563_IIC_W_ADDR 0xA2
#define?PCF8563_IIC_R_ADDR 0xA3
static?u8?GetWeek(u16?year,u8?month,u8?day); //獲取2000-2099年之間的日期對應的星期
static?u32?DECtoBCD(?u8?DEC); //將數(shù)字轉換為壓縮BCD格式,最大支持99
static?u32?BCDtoDEC(u8?BCD); //將壓縮BCD轉為DEC,最大支持99
bool?PCF8563_ReadReg(PCF8563_REG_TYPE?RegIndex,?u8?*pData,?u8?RegNum)?; //讀取PCF8563寄存器
bool?PCF8563_WriteReg(PCF8563_REG_TYPE?RegIndex,?u8?*pData,?u8?RegNum)?; //寫入PCF8563寄存器
bool?PCF8563_WriteOneReg(PCF8563_REG_TYPE?RegIndex,?u8?Data); //寫單個寄存器
/*************************************************************************************************************************
*函數(shù)???????? : bool?PCF8563_Init(void)
*功能???????? : 初始化PCF8563
*參數(shù)???????? : 無
*返回???????? : FALSE:失敗;TRUE:成功
*依賴 :? 底層宏定義
*作者??????? : cp1300@139.com
*時間????? : 2017-07-10
*最后修改時間 : 2017-07-10
*說明???????? : 無
*************************************************************************************************************************/
bool?PCF8563_Init(void)
{
u8?data;
memset(&ext_timer,0,sizeof(rtc_timer));
if(SIIC_Init(&IIC_Handel,PCF8563_SDA_GPIOx,?PCF8563_SCL_GPIOx,?PCF8563_SDA_Bit,?PCF8563_SCL_Bit,?1)?==?FALSE)
{
PCF8563_Debug("**********************PCF8563?初始化失敗,IIC接口初始化失??!rn");
return?FALSE;
}
if(PCF8563_WriteOneReg(PCF8563_REG_CONTROL1,?0x08)?==?FALSE) //啟動時鐘,開啟掉電檢測
{
PCF8563_Debug("**********************PCF8563?初始化失敗,開啟掉電監(jiān)測功能失?。n");
return?FALSE;
}
if(PCF8563_ReadReg(PCF8563_REG_SECONDS,?&data,?1)?==?FALSE)
{
PCF8563_Debug("**********************PCF8563?初始化失敗,讀取秒寄存器失??!rn");
return?FALSE;
}
if(data?&?0x80) //秒?最高位為1,時鐘芯片沒有初始化?integrity?of?the?clock?information?is?no?longer?guaranteed
{
//初始化時鐘芯片與時間
PCF8563_Debug("時鐘芯片沒有初始化,需要重新初始化時鐘!rn");
if(PCF8563_SetTimer(2017,6,6,6,6,6)==FALSE)
{
PCF8563_Debug("時鐘芯片沒有初始化,需要重新初始化時鐘!rn");
}
}
PCF8563_GetTimer(); //更新時間
return?TRUE;
}
/*************************************************************************************************************************
*函數(shù)???????? : bool?PCF8563_ReadReg(PCF8563_REG_TYPE?RegIndex,?u8?*pData,?u8?RegNum)?
*功能???????? : 讀取PCF8563多個寄存器
*參數(shù)???????? : RegIndex:寄存器地址,pData:讀取到的值,RegNum:讀取的寄存器數(shù)量
*返回???????? : TRUE:通信成功;FALSE:通信失敗
*依賴 :? 底層宏定義
*作者??????? : cp1300@139.com
*時間????? : 2017-07-10
*最后修改時間 : 2017-07-10
*說明???????? : 無
*************************************************************************************************************************/
bool?PCF8563_ReadReg(PCF8563_REG_TYPE?RegIndex,?u8?*pData,?u8?RegNum)?
{
u8?i;
if(RegNum?<?1)?RegNum?=?1;
if(RegNum?>?16)?RegNum?=?16; //限制讀取的最大數(shù)量
SIIC_Start(&IIC_Handel); //發(fā)送起始信號
if(SIIC_SendByte(&IIC_Handel,?PCF8563_IIC_W_ADDR)==FALSE) //發(fā)送寫地址
{
PCF8563_Debug("PCF8563?發(fā)送寫地址?ACK錯誤rn");
return?FALSE;
}
if(SIIC_SendByte(&IIC_Handel,?RegIndex)==FALSE) //發(fā)送要讀取的寄存器地址
{
PCF8563_Debug("PCF8563?發(fā)送要讀取的寄存器地址2?ACK錯誤rn");
return?FALSE;
}
SIIC_Start(&IIC_Handel); //發(fā)送起始信號
if(SIIC_SendByte(&IIC_Handel,?PCF8563_IIC_R_ADDR)==FALSE) //發(fā)送讀取地址
{
PCF8563_Debug("PCF8563?發(fā)送讀取地址?ACK錯誤rn");
return?FALSE;
}
for(i?=?0;i?<?RegNum;i?++)
{
if(i?==?(RegNum-1)) //最后一字節(jié)
{
pData[i]?=?SIIC_ReadByte(&IIC_Handel,?FALSE); //讀取數(shù)據(jù)-最后一字節(jié)不發(fā)送ACK
}
else
{
pData[i]?=?SIIC_ReadByte(&IIC_Handel,?TRUE); //讀取數(shù)據(jù)
}
}
SIIC_Stop(&IIC_Handel); //發(fā)送結束
return?TRUE;
}
/*************************************************************************************************************************
*函數(shù)???????? : bool?PCF8563_ReadOneReg(PCF8563_REG_TYPE?RegIndex,?u8?*pData)?
*功能???????? : 讀取PCF8563單個寄存器
*參數(shù)???????? : RegIndex:寄存器地址,pData:讀取到的值
*返回???????? : TRUE:通信成功;FALSE:通信失敗
*依賴 :? 底層宏定義
*作者??????? : cp1300@139.com
*時間????? : 2017-07-10
*最后修改時間 : 2017-07-13
*說明???????? : 無
*************************************************************************************************************************/
bool?PCF8563_ReadOneReg(PCF8563_REG_TYPE?RegIndex,?u8?*pData)?
{
SIIC_Start(&IIC_Handel); //發(fā)送起始信號
if(SIIC_SendByte(&IIC_Handel,?PCF8563_IIC_W_ADDR)==FALSE) //發(fā)送寫地址
{
PCF8563_Debug("PCF8563?發(fā)送寫地址?ACK錯誤rn");
return?FALSE;
}
if(SIIC_SendByte(&IIC_Handel,?RegIndex)==FALSE) //發(fā)送要讀取的寄存器地址
{
PCF8563_Debug("PCF8563?發(fā)送要讀取的寄存器地址2?ACK錯誤rn");
return?FALSE;
}
SIIC_Start(&IIC_Handel); //發(fā)送起始信號
if(SIIC_SendByte(&IIC_Handel,?PCF8563_IIC_R_ADDR)==FALSE) //發(fā)送讀取地址
{
PCF8563_Debug("PCF8563?發(fā)送讀取地址?ACK錯誤rn");
return?FALSE;
}
*pData?=?SIIC_ReadByte(&IIC_Handel,?FALSE); //讀取數(shù)據(jù)-最后一字節(jié)不發(fā)送ACK
SIIC_Stop(&IIC_Handel); //發(fā)送結束
return?TRUE;
}
/*************************************************************************************************************************
*函數(shù)???????? : bool?PCF8563_WriteReg(PCF8563_REG_TYPE?RegIndex,?u8?*pData,?u8?RegNum)?
*功能???????? : 寫PCF8563多個寄存器
*參數(shù)???????? : RegIndex:寄存器地址,pData:寫入的值,RegNum:寫入的寄存器數(shù)量
*返回???????? : TRUE:通信成功;FALSE:通信失敗
*依賴 :? 底層宏定義
*作者??????? : cp1300@139.com
*時間????? : 2017-07-10
*最后修改時間 : 2017-07-10
*說明???????? : 無
*************************************************************************************************************************/
bool?PCF8563_WriteReg(PCF8563_REG_TYPE?RegIndex,?u8?*pData,?u8?RegNum)?
{
u8?i;
SIIC_Start(&IIC_Handel); //發(fā)送起始信號
if(SIIC_SendByte(&IIC_Handel,?PCF8563_IIC_W_ADDR)==FALSE) //發(fā)送寫地址
{
PCF8563_Debug("PCF8563?發(fā)送寫地址?ACK錯誤rn");
return?FALSE;
}
/*if(SIIC_SendByte(&IIC_Handel,?0)==FALSE) //發(fā)送要讀取的寄存器地址
{
PCF8563_Debug("PCF8563?發(fā)送要讀取的寄存器地址2?ACK錯誤rn");
return?FALSE;
}*/
if(SIIC_SendByte(&IIC_Handel,?RegIndex)==FALSE) //發(fā)送要寫的寄存器地址
{
PCF8563_Debug("PCF8563?發(fā)送要讀取的寄存器地址2?ACK錯誤rn");
return?FALSE;
}
/*SIIC_Start(&IIC_Handel); //發(fā)送起始信號
if(SIIC_SendByte(&IIC_Handel,?PCF8563_IIC_W_ADDR)==FALSE) //發(fā)送寫地址
{
PCF8563_Debug("PCF8563?發(fā)送讀取地址?ACK錯誤rn");
return?FALSE;
}*/
for(i?=?0;i?<?RegNum;i?++)
{
SIIC_SendByte(&IIC_Handel,?pData[i]); //發(fā)送數(shù)據(jù)
}
SIIC_Stop(&IIC_Handel); //發(fā)送結束
???
return?TRUE;
}
/*************************************************************************************************************************
*函數(shù)???????? : bool?PCF8563_WriteOneReg(PCF8563_REG_TYPE?RegIndex,?u8?Data)??
*功能???????? : 寫PCF8563單個寄存器
*參數(shù)???????? : RegIndex:寄存器地址,Data:寫入的值
*返回???????? : TRUE:通信成功;FALSE:通信失敗
*依賴 :? 底層宏定義
*作者??????? : cp1300@139.com
*時間????? : 2017-07-10
*最后修改時間 : 2017-07-13
*說明???????? : 無
*************************************************************************************************************************/
bool?PCF8563_WriteOneReg(PCF8563_REG_TYPE?RegIndex,?u8?Data)?
{
SIIC_Start(&IIC_Handel); //發(fā)送起始信號
if(SIIC_SendByte(&IIC_Handel,?PCF8563_IIC_W_ADDR)==FALSE) //發(fā)送寫地址
{
PCF8563_Debug("PCF8563?發(fā)送寫地址?ACK錯誤rn");
return?FALSE;
}
if(SIIC_SendByte(&IIC_Handel,?RegIndex)==FALSE) //發(fā)送要寫的寄存器地址
{
PCF8563_Debug("PCF8563?發(fā)送要讀取的寄存器地址2?ACK錯誤rn");
return?FALSE;
}
SIIC_SendByte(&IIC_Handel,?Data); //發(fā)送數(shù)據(jù)
SIIC_Stop(&IIC_Handel); //發(fā)送結束
???
return?TRUE;
}
/*************************************************************************************************************************
*?函數(shù) : bool?PCF8563_GetTimer(void)
*?功能 : PCF8563獲取時間
*?參數(shù) : 無
*?返回 : TRUE:成功,FALSE:失敗
*?依賴 : 底層宏定義
*?作者 : cp1300@139.com
*?時間 : 2017-07-11
*?最后修改時間? :? 2017-07-11
*?說明 :? 獲取到的時間會更新到全局ext_timer
*************************************************************************************************************************/
bool?PCF8563_GetTimer(void)
{
u8?data[7];
u8?retry;
u8?temp;
for(retry?=?0;retry?<?3;retry?++)
{
if(PCF8563_ReadReg(PCF8563_REG_SECONDS,?data,?7)?==?TRUE) //設置時間
{
if(data[0]?&?0x80) //時間無效
{
PCF8563_Debug("PCF8563?時間無效,需要重新初始化!rn");
PCF8563_SetTimer(2017,6,6,6,6,6); //初始化設置時間
}
else
{
//uart_printf("%02X,%02X,%02X,%02X,%02X,%02X,%02Xrn",data[0],data[1],data[2],data[3],data[4],data[5],data[6]);
temp?=?BCDtoDEC(data[0]&0x7F);
if(temp?>?59)?continue; //秒鐘范圍不對
ext_timer.sec?=?temp;
temp?=?BCDtoDEC(data[1]&0x7F);
if(temp?>?59)?continue; //分鐘范圍不對
ext_timer.min?=?temp;
temp?=?BCDtoDEC(data[2]&0x3F);
if(temp?>?23)?continue; //小時范圍不對
ext_timer.hour?=?temp;
temp?=?BCDtoDEC(data[3]&0x3F);
if(temp?>?31||temp==0)?continue; //日期范圍不對
ext_timer.date?=?temp;
temp?=?BCDtoDEC(data[4]&0x07);
if(temp?>?6)?continue; //星期范圍不對
ext_timer.week?=?temp+1;
temp?=?BCDtoDEC(data[5]&0x1F);
if(temp?>?12||temp==0)?continue; //月份范圍不對
ext_timer.month?=?temp;
ext_timer.year?=?BCDtoDEC(data[6])+2000;
return?TRUE;
}
}
else
{
PCF8563_Debug("PCF8563?讀取時間失??!rn");
}
}
return?FALSE;
}
/*************************************************************************************************************************
*?函數(shù) : bool?PCF8563_SetTimer(u16?year,u8?month,u8?date,u8?hour,u8?min,u8?sec)
*?功能 : PCF8563時間設置
*?參數(shù) : year,month,date:年(2000~2099),月(1~12),日(1~31),hour,min,sec:小時24小時,分鐘,秒鐘
*?返回 : TRUE:成功,FALSE:失敗
*?依賴 : 底層宏定義
*?作者 : cp1300@139.com
*?時間 : 2017-07-11
*?最后修改時間? :? 2017-07-11
*?說明 :?
*************************************************************************************************************************/
bool?PCF8563_SetTimer(u16?year,u8?month,u8?date,u8?hour,u8?min,u8?sec)
{
u8?data[7];
if(year?<?2000)?year?=?2000;
if(year?>?2099)?year?=?2099;
data[0]?=?DECtoBCD(sec); //秒
data[1]?=?DECtoBCD(min); //分
data[2]?=?DECtoBCD(hour); //小時
data[3]?=?DECtoBCD(date); //日
data[4]?=?GetWeek(year,?month,?date)-1; //星期
year?-=?2000;
data[5]?=?DECtoBCD(month); //月
data[6]?=?DECtoBCD(year); //年
PCF8563_WriteReg(PCF8563_REG_SECONDS,?&data[0],?7); //設置時間
if(PCF8563_WriteOneReg(PCF8563_REG_CONTROL1,?0x08)?==?FALSE) //啟動時鐘,開啟掉電檢測
{
PCF8563_Debug("**********************PCF8563?設置失敗,啟動時鐘失??!rn");
return?FALSE;
}
return?TRUE;
}
/*************************************************************************************************************************
*?函數(shù) : u32?PCF8563_TimeToSec(u16?syear,u8?smon,u8?sday,u8?hour,u8?min,u8?sec)
*?功能 : PCF8563時間轉換為秒(從1970開始)(注意:不可重入,請注意調用沖突)
*?參數(shù) : year,month,date:年(2000~2099),月(1~12),日(1~31),hour,min,sec:小時24小時,分鐘,秒鐘
*?返回 : TRUE:成功,FALSE:失敗
*?依賴 : 底層宏定義
*?作者 : cp1300@139.com
*?時間 : 2017-07-11
*?最后修改時間? :? 2017-07-17
*?說明 :? 只能計算從2000年之后的秒,修改如果年,月,日不變,則無需重新計算,提高效率
注意:不可重入,請注意調用沖突
*************************************************************************************************************************/
u32?PCF8563_TimeToSec(u16?syear,u8?smon,u8?sday,u8?hour,u8?min,u8?sec)
{
u16?t;
u32?seccount?=?0;
static?u32?LastYearSec?=?0; //之前年對應的秒,如果年不變,則不用重新計算
static?u32?LastMonSec?=?0; //當前年月份對應的秒數(shù),如果月份不變,則不需要重新計算
static?u32?LastDaySec?=?0; //當前日期對應的秒,如果日期不變,則不需要重新計算
static?u16?LastYear?=?0; //之前的年如果不變,則只計算今年的秒
static?u8?LastMon?=?0; //當前年之前的月份
static?u8?LastDay?=?0; //之前的日期
if(syear?<?2000?||?syear?>?2099)
return?0;
//年變化了才重新計算
if(LastYear?!=?syear) //年發(fā)生了變化,重新計算
{
LastYear?=?syear; //記錄本次的年
LastYearSec?=?0;
for(t?=?1970;t?<?syear;t?++) //把所有年份的秒鐘相加
{
if(Is_Leap_Year(t))
LastYearSec?+=?31622400; //閏年的秒鐘數(shù)
else?
LastYearSec?+=?31536000; ??//平年的秒鐘數(shù)
}
}
//月變化了才重新計算
if(LastMon?!=?smon) //月份有變化
{
LastMon?=?smon; //記錄本次的月份
smon?-=?1;
LastMonSec?=?0;
for(t?=?0;t?<?smon;t?++) ??? //把前面月份的秒鐘數(shù)相加
{
LastMonSec?+=?(u32)mon_table[t]?*?86400; //月份秒鐘數(shù)相加
if(Is_Leap_Year(syear)?&&?t?==?1)
LastMonSec?+=?86400; //閏年2月份增加一天的秒鐘數(shù) ???
}
}
//日期變化了才重新計算
if(LastDay?!=?sday)
{
LastDay?=?sday; //記錄本次的日期
LastDaySec?=?(u32)(sday?-?1)?*?86400; //把前面日期的秒鐘數(shù)相加?
}
seccount?=?LastYearSec+LastMonSec+LastDaySec; //直接獲取年對應的秒,不用每次計算
seccount?+=?(u32)hour?*?3600; //小時秒鐘數(shù)
????seccount?+=?(u32)min?*?60; ? //分鐘秒鐘數(shù)
seccount?+=?sec; //最后的秒鐘加上去
return?seccount;
}
??
/*************************************************************************************************************************
*?函數(shù) : bool?Is_Leap_Year(u16?year)
*?功能 : 判斷是否是閏年函數(shù)
*?參數(shù) : year:年份
*?返回 : TRUE:是閏年,FALSE:不是閏年
*?依賴 : 無
*?作者 : cp1300@139.com
*?時間 : 2014-05-30
*?最后修改時間 : 2014-05-30
*?說明 :?
月份???1??2??3??4??5??6??7??8??9??10?11?12
閏年???31?29?31?30?31?30?31?31?30?31?30?31
非閏年?31?28?31?30?31?30?31?31?30?31?30?31
*************************************************************************************************************************/
static?bool?Is_Leap_Year(u16?year)
{ ??
if(year?%?4?==?0)?//必須能被4整除
{?
if(year?%?100?==?0)?
{?
if(year?%?400?==?0)
return?TRUE;//如果以00結尾,還要能被400整除? ???
else?
return?FALSE;???
}else?
return?TRUE;???
}else?
return?FALSE;
}
//獲取2000-2099年之間的日期對應的星期
//功能描述:輸入公歷日期得到星期(只允許1901-2099年)
//year,month,day:公歷年月日?
//返回值:星期號(1~7,代表周1~周日) ?
static?u8?GetWeek(u16?year,u8?month,u8?day)
{
u16?temp2;
u8?yearH,yearL;
yearH=year/100; yearL=year%100;?
//?如果為21世紀,年份數(shù)加100??
if?(yearH>19)yearL+=100;
//?所過閏年數(shù)只算1900年之后的??
temp2=yearL+yearL/4;
temp2=temp2%7;?
temp2=temp2+day+table_week[month-1];
if?(yearL%4==0&&month<3)temp2--;
temp2%=7;
if(temp2==0)temp2=7;
return?temp2;
}
//將數(shù)字轉換為壓縮BCD格式,最大支持99
static?u32?DECtoBCD(?u8?DEC)?
{
return?((u8)(DEC/10)<>4)*10+(BCD&0x0f);
}
//使能系統(tǒng)命令行
#if?SYS_CMD_EN_
#include?"cmd.h"
#include?"string.h"
const?CMD_TYPE??CMD_GET_ExtTIME = {"TIME?",?0xCC5C410A,?CMD_ExtGetTime,?"tt獲取系統(tǒng)時間"};
const?CMD_TYPE??CMD_GET_ExtDATE = {"DATE?",?0xB2704461,?CMD_ExtGetDate,?"tt獲取系統(tǒng)日期"};
const?CMD_TYPE??CMD_SET_ExtTIME = {"TIME=",?0xCC5C4108,?CMD_ExtSetTime,?"tt設置系統(tǒng)時間?如(12:32:54):TIME=12?32?54"};
const?CMD_TYPE??CMD_SET_ExtDATE = {"DATE=",?0xB270445F,?CMD_ExtSetDate,?"tt設置系統(tǒng)日期?如(2014?6?8):TIME=2014?6?8"};
//獲取時間
void?CMD_ExtGetTime(char?*pStr)
{
//PCF8563_GetTimer(); //更新時間
cmd_printf("[獲取時間成功]:%02d:%02d:%02drn",ext_timer.hour,?ext_timer.min,?ext_timer.sec);
}
//獲取日期
void?CMD_ExtGetDate(char?*pStr)
{
//PCF8563_GetTimer(); //更新時間
cmd_printf("[獲取日期成功]:%04d-%02d-%02drn",ext_timer.year,?ext_timer.month,?ext_timer.date);
}
//設置時間
void?CMD_ExtSetTime(char?*pStr)
{
u8?hour,min,sec;
u8?len;
char?*p;
u8?num;
len?=?strlen(pStr); //獲取長度
if(isStrNumAndSpc(pStr,?len,?2)?==?FALSE)
{
cmd_printf("[時間設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
//小時
p?=?strstr(pStr,"?"); //搜索空格
if(p?==?NULL)
{
cmd_printf("[時間設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
num?=?p?-?pStr;
if((num?>?2)?||?(num?==?0))
{
cmd_printf("[時間設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
hour?=?CMD_StringToDec(pStr,?num);
if(hour>23)
{
cmd_printf("[時間設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
//分鐘
pStr?=?p+1;
p?=?strstr(pStr,"?"); //搜索空格
if(p?==?NULL)
{
cmd_printf("[時間設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
num?=?p?-?pStr;
if((num?>?2)?||?(num?==?0))
{
cmd_printf("[時間設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
min?=?CMD_StringToDec(pStr,?num);
if(min>59)
{
cmd_printf("[時間設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
//秒鐘
pStr?=?p+1;
num?=?strlen(pStr);
if((num?>?2)?||?(num?==?0))
{
cmd_printf("[時間設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
sec?=?CMD_StringToDec(pStr,?num);
if(sec>59)
{
cmd_printf("[時間設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
PCF8563_GetTimer(); //更新時間
if(PCF8563_SetTimer(ext_timer.year,?ext_timer.month,?ext_timer.date,hour,?min,?sec)?==?FALSE)
{
PCF8563_GetTimer(); //更新時間
cmd_printf("[時間設置失敗]:%02d:%02d:%02drn",ext_timer.hour,?ext_timer.min,?ext_timer.sec);
}
else
{
PCF8563_GetTimer(); //更新時間
cmd_printf("[時間設置成功]:%02d:%02d:%02drn",ext_timer.hour,?ext_timer.min,?ext_timer.sec);
}
}?
//設置日期
void?CMD_ExtSetDate(char?*pStr)
{
u16?year;
u8?month,?date;
u8?len;
char?*p;
u8?num;
len?=?strlen(pStr); //獲取長度
if(isStrNumAndSpc(pStr,?len,?2)?==?FALSE)
{
cmd_printf("[日期設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
//年
p?=?strstr(pStr,"?"); //搜索空格
if(p?==?NULL)
{
cmd_printf("[日期設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
num?=?p?-?pStr;
if((num?>?4)?||?(num?==?0))
{
cmd_printf("[日期設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
year?=?CMD_StringToDec(pStr,?num);
if(year>9999)
{
cmd_printf("[日期設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
//月
pStr?=?p+1;
p?=?strstr(pStr,"?"); //搜索空格
if(p?==?NULL)
{
cmd_printf("[日期設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
num?=?p?-?pStr;
if((num?>?2)?||?(num?==?0))
{
cmd_printf("[日期設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
month?=?CMD_StringToDec(pStr,?num);
if(month>12)
{
cmd_printf("[日期設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
//日
pStr?=?p+1;
num?=?strlen(pStr);
if((num?>?2)?||?(num?==?0))
{
cmd_printf("[日期設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
date?=?CMD_StringToDec(pStr,?num);
if(date>31)
{
cmd_printf("[日期設置錯誤]:格式不對或非法參數(shù)!rn");
return;
}
PCF8563_GetTimer(); //更新時間
if(PCF8563_SetTimer(year,?month,?date,?ext_timer.hour,?ext_timer.min,?ext_timer.sec)?==?FALSE)
{
PCF8563_GetTimer(); //更新時間
cmd_printf("[日期設置失敗]:%04d-%02d-%02drn",ext_timer.year,?ext_timer.month,?ext_timer.date);
}
else
{
PCF8563_GetTimer(); //更新時間
cmd_printf("[日期設置成功]:%04d-%02d-%02drn",ext_timer.year,?ext_timer.month,?ext_timer.date);
}
}?
#endif?//SYS_CMD_EN_
//,H文件
/*************************************************************************************************************
?*?文件名: PCF8563.h
?*?功能: STM32?PCF8563?高精度?RTC?芯片驅動
?*?作者: cp1300@139.com
?*?創(chuàng)建時間: 2017-07-10
?*?最后修改時間: 2017-07-10
?*?詳細: 使用軟件IIC接口驅動
*************************************************************************************************************/
#ifndef?_PCF8563_H_
#define?_PCF8563_H_
#include?"system.h"
#if(BOARD_SUPPORT) //需要板級支持
#include?"board.h"?
#else //默認支持
#endif
//時間結構體
typedef??struct?
{
u8 hour;? //小時
u8 min; ? //分鐘
u8 sec; //秒
u8??month; //月
u8??date; //日
u8??week; //星期
u16?year; ? //年
}rtc_timer;
extern?rtc_timer?ext_timer; //外部RTC時鐘
//PCF8563?寄存器
typedef?enum
{
PCF8563_REG_CONTROL1 = 0x00, //控制寄存器1
PCF8563_REG_CONTROL2 = 0x01, //控制寄存器2
PCF8563_REG_SECONDS = 0x02, //秒?seconds?00?to?59?coded?in?BCD
PCF8563_REG_MINUTES = 0x03, //分?minutes?00?to?59?coded?in?BCD
PCF8563_REG_HOURS = 0x04, //小時?hours?00?to?23?coded?in?BCD
PCF8563_REG_DAYS = 0x05, //日?days?01?to?31?coded?in?BCD
PCF8563_REG_WEEK = 0x06, //星期?weekdays?0?to?6?in?BCD
PCF8563_REG_MONTHS = 0x07, //月份?months?01?to?12?coded?in?BCD
PCF8563_REG_YEARS = 0x08, //年份?years?00?to?99?coded?in?BCD
PCF8563_REG_ALARM_MINUTE = 0x09, //鬧鐘,分鐘?minute?alarm?00?to?59?coded?in?BCD
PCF8563_REG_ALARM_HOUR = 0x0A, //鬧鐘,小時?hour?alarm?00?to?23?coded?in?BCD
PCF8563_REG_ALARM_DAY = 0x0B, //鬧鐘,日?day?alarm?01?to?31?coded?in?BCD
PCF8563_REG_ALARM_WEEK = 0x0C, //鬧鐘,星期?weekday?alarm?0?to?6?in?BCD
PCF8563_REG_CLKOUT = 0x0D, //時鐘輸出設置
PCF8563_REG_TIME_CONTROL = 0x0E, //定時器設置
PCF8563_REG_TIME = 0x0F, //定時器倒計數(shù)值
}PCF8563_REG_TYPE;
bool?PCF8563_Init(void); //PCF8563初始化
bool?PCF8563_SetTimer(u16?year,u8?month,u8?date,u8?hour,u8?min,u8?sec); //PCF8563時間設置
bool?PCF8563_GetTimer(void); //更新時間
u32?PCF8563_TimeToSec(u16?syear,u8?smon,u8?sday,u8?hour,u8?min,u8?sec); //時間轉換為秒,注意:不可重入,請注意調用沖突
//使能系統(tǒng)命令行
#if?SYS_CMD_EN_
#include?"cmd.h"
#include?"string.h"
extern?const?CMD_TYPE??CMD_GET_ExtTIME;
extern?const?CMD_TYPE??CMD_GET_ExtDATE;
extern?const?CMD_TYPE??CMD_SET_ExtTIME;
extern?const?CMD_TYPE??CMD_SET_ExtDATE;
//獲取時間
void?CMD_ExtGetTime(char?*pStr);
//獲取日期
void?CMD_ExtGetDate(char?*pStr);
//設置時間
void?CMD_ExtSetTime(char?*pStr);
//設置日期
void?CMD_ExtSetDate(char?*pStr);
#endif?//SYS_CMD_EN_
#endif?/*_PCF8563_H_*/




