blob: 61f263ccfab76600be857e6eeee4c47518f2996c [file] [log] [blame]
#include "rtc.h"
#include "time.h"
#include "data_tools.h"
#include "string.h"
#include "timer.h"
uint32_t CrystalStartErrFlag;
static uint8_t rtc_wait_flag(uint32_t* reg, uint32_t mask, uint32_t flag, uint32_t timeout)
{
uint32_t t = timeout/100;
while(((*reg)&mask) != flag)
{
delay_ms(100);
t --;
if(t == 0)
return 1;
}
return 0;
}
uint32_t rtc_get_counter(void)
{
return (uint32_t)((RTC->CNTH << 16) | RTC->CNTL);
}
static uint8_t rtc_set_counter(uint32_t cnt)
{
PWR->CR |= PWR_CR_DBP; // ʹÄÜ·ÃÎÊRTC, BDC ¼Ä´æÆ÷
RTC->CRL |=RTC_CRL_CNF; // ÉèÖÃRTCÅäÖñê¼Ç,ÔÊÐíÅäÖÃ
RTC->CNTH = (cnt>>16)&0xffff;
RTC->CNTL = cnt&0xffff ;
RTC->CRL &= ~RTC_CRL_CNF; // ÉèÖÃRTCÅäÖñê¼Ç,²»ÔÊÐíÅäÖÃ
if(rtc_wait_flag((uint32_t*)&RTC->CRL, RTC_FLAG_RTOFF, RTC_FLAG_RTOFF, 4000ul)) //µÈ´ýÅäÖÃÍê³É
{
PWR->CR &= ~PWR_CR_DBP; // ²»ÔÊÐíÅäÖÃRTC¡¢BDC¼Ä´æÆ÷
return 1;
}
PWR->CR &= ~PWR_CR_DBP; // ²»ÔÊÐíÅäÖÃRTC¡¢BDC¼Ä´æÆ÷
return 0;
}
void rtc_init(void)
{
CrystalStartErrFlag = 0;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
//RTCÊ×´ÎÉϵç»òʱÖÓ¶ªÊ§
if(BKP_ReadBackupRegister(BKP_DR1) != 0x5A5A)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
BKP_DeInit();
RCC_LSEConfig(RCC_LSE_ON);
//²ÎÕÕstm32f10x datasheet£¬LES startup time
//tsu(lse) = 3S (Typ)
//´Ë´¦µÈ´ýLSEÆðÕñÑÓʱԼ4S
if(rtc_wait_flag((uint32_t*)&RCC->BDCR, 0x02, 0x02, 4000ul))
CrystalStartErrFlag = 1;
if(!CrystalStartErrFlag)
{
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
/* Clear RSF flag */
RTC->CRL &= (u16)~RTC_FLAG_RSF;
/* Loop until RSF flag is set */
if(rtc_wait_flag((uint32_t*)&RTC->CRL, RTC_FLAG_RSF, RTC_FLAG_RSF, 4000ul))
CrystalStartErrFlag = 1;
//rtc wait for last task
if(rtc_wait_flag((uint32_t*)&RTC->CRL, RTC_FLAG_RTOFF, RTC_FLAG_RTOFF, 4000ul))
CrystalStartErrFlag = 1;
RTC_SetPrescaler(32767);
//rtc wait for last task
if(rtc_wait_flag((uint32_t*)&RTC->CRL, RTC_FLAG_RTOFF, RTC_FLAG_RTOFF, 4000ul))
CrystalStartErrFlag = 1;
BKP_WriteBackupRegister(BKP_DR1, 0x5A5A);
}
PWR_BackupAccessCmd(DISABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, DISABLE);
}
else
{
/* Clear RSF flag */
RTC->CRL &= (u16)~RTC_FLAG_RSF;
/* Loop until RSF flag is set */
if(rtc_wait_flag((uint32_t*)&RTC->CRL, RTC_FLAG_RSF, RTC_FLAG_RSF, 4000ul))
CrystalStartErrFlag = 1;
else
{
//0x386D4380ul 2000Äê1ÔÂ1ÈÕÃëÊý
if(rtc_get_counter()<0x386D4380ul)
{
rtc_set_counter(0x386D4380ul);
}
// rtc_get_time(&SystemTime);
}
}
}
uint32_t rtc_mk_time(_SystemTime* t)
{
struct tm temp_time;
_SystemTime temp_time_hex;
memcpy(&temp_time_hex, t, sizeof(_SystemTime));
bcd2hex(&temp_time_hex, sizeof(temp_time_hex));
temp_time.tm_year = temp_time_hex.year+100; //´Ó1900Ä꿪ʼ
temp_time.tm_mon = temp_time_hex.month-1;
temp_time.tm_mday = temp_time_hex.day;
temp_time.tm_wday = temp_time_hex.week;
temp_time.tm_hour = temp_time_hex.hour;
temp_time.tm_min = temp_time_hex.minute;
temp_time.tm_sec = temp_time_hex.second;
return mktime(&temp_time);
}
uint8_t rtc_set_time(_SystemTime* t)
{
uint8_t ret = 0;
time_t seconds = rtc_mk_time(t);
ret = rtc_set_counter(seconds);
return ret;
}
uint8_t rtc_get_time(_SystemTime* t)
{
struct tm* temp_time;
_SystemTime temp_time_bcd;
time_t seconds = rtc_get_counter();
temp_time = localtime(&seconds);
if(temp_time->tm_year<100)
temp_time_bcd.year = 0;
else
temp_time_bcd.year = temp_time->tm_year - 100;
temp_time_bcd.month = temp_time->tm_mon+1;
temp_time_bcd.day = temp_time->tm_mday;
temp_time_bcd.week = temp_time->tm_wday;
temp_time_bcd.hour = temp_time->tm_hour;
temp_time_bcd.minute = temp_time->tm_min;
temp_time_bcd.second = temp_time->tm_sec;
hex2bcd(&temp_time_bcd, sizeof(temp_time_bcd));
memcpy(t, &temp_time_bcd, sizeof(temp_time_bcd));
return 0;
}
uint32_t rtc_time_diff(void* t1, void* t2)
{
uint32_t t1_sec = rtc_mk_time((_SystemTime*)t1);
uint32_t t2_sec = rtc_mk_time((_SystemTime*)t2);
return (t1_sec-t2_sec);
}