大理水控初始版本
diff --git a/sys_hw/rtc.c b/sys_hw/rtc.c
new file mode 100644
index 0000000..61f263c
--- /dev/null
+++ b/sys_hw/rtc.c
@@ -0,0 +1,165 @@
+#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);
+}