📄 rtc.c
字号:
/**********************************************************************************************************************
文件名: UARTAPE.c
作者: Viboy 版本: V1.0 日期:2008-08-01
联系方式: QQ:64933886 WEBSITE: www.cortexmcu.com
函数列表说明:
1. RTC_Init ---> RTC模块初始化
2. RTC_Read ---> RTC读,返回年,月,日,星期,时,分,秒
3. RTC_Write ---> RTC写,设置当前年,月,日,时,分,秒
历史:
<作者> <日期> <版本> <说明>
Viboy 2008-08-01 V1.0 初版
***********************************************************************************************************************/
#include <stdio.h>
#include <string.h>
#include <LM3Sxxxx.H>
#include "RTC.h"
#include "config.h"
#define RTC_INFOR_OK 0
#define FORMAT_ERR 1
typedef struct
{
int month;
int total;
}DAY_TOTAL;
const DAY_TOTAL DayToatlBefor[12] =
{
{1,31}, {2,59},
{3,90}, {4,120},
{5,151},{6,181},
{7,212},{8,243},
{9,273},{10,304},
{11,334},{12,365}
};
const DAY_TOTAL Day[12] =
{
{1,31}, {2,28},
{3,31}, {4,30},
{5,31}, {6,30},
{7,31}, {8,31},
{9,30}, {10,31},
{11,30},{12,31}
};
/*********************************************************************************************************
函数名称: leap_year
功能描述: 闰年判断
输 入: year 待判断的年份
输 出: 1 闰年
0 平年
*********************************************************************************************************/
static INT8U leap_year(INT16U nYear)
{
if(nYear % 4 != 0) return 0;
if(nYear % 100 != 0) return 1;
return (INT8U)(nYear % 400 == 0);
}
/*********************************************************************************************************************
函数名称: WeekDayNum
功能描述: Determines the week number, the day number and the week day number
输 入 : nyear,nmonth,nday
输 出 : weekday
*********************************************************************************************************************/
static INT8U WeekDayNum(INT32U nyear, INT8U nmonth, INT8U nday)
{
INT32U weeknum = 0, weekday = 0, daycount = 0;
INT32U a = 0, b = 0, c = 0, s = 0, e = 0, f = 0, g = 0, d = 0;
INT32S n = 0;
if(nmonth < 3)
{
a = nyear - 1;
}
else
{
a = nyear;
}
b = (a/4) - (a/100) + (a/400);
c = ((a - 1)/4) - ((a - 1)/100) + ((a - 1)/400);
s = b - c;
if(nmonth < 3)
{
e = 0;
f = nday - 1 + 31 * (nmonth - 1);
}
else
{
e = s + 1;
f = nday + (153*(nmonth - 3) + 2)/5 + 58 + s;
}
g = (a + b) % 7;
d = (f + g - e) % 7;
n = f + 3 - d;
if (n < 0)
{
weeknum = 53 - ((g - s)/5);
}
else if (n > (364 + s))
{
weeknum = 1;
}
else
{
weeknum = (n/7) + 1;
}
weekday = d;
daycount = f + 1;
weeknum = weeknum; /* 一年中的第几个星期在此没有用上,防止编译警告 */
daycount = daycount; /* 同上 */
return (INT8U)weekday;
}
/*********************************************************************************************************************
函数名称: Date_Update
功能描述: Updates date when time is 23:59:59
输 入 : date_s
输 出 : None
*********************************************************************************************************************/
static void Date_Update(RTC_INFOR* date_s)
{
if(date_s->month == 1 || date_s->month == 3 || date_s->month == 5 || date_s->month == 7 ||
date_s->month == 8 || date_s->month == 10 || date_s->month == 12)
{
if(date_s->day < 31)
{
date_s->day++;
}
/* Date structure member: date_s.day = 31 */
else
{
if(date_s->month != 12)
{
date_s->month++;
date_s->day = 1;
}
/* Date structure member: date_s.day = 31 & date_s.month =12 */
else
{
date_s->month = 1;
date_s->day = 1;
date_s->year++;
}
}
}
else if(date_s->month == 4 || date_s->month == 6 || date_s->month == 9 ||
date_s->month == 11)
{
if(date_s->day < 30)
{
date_s->day++;
}
/* Date structure member: date_s.day = 30 */
else
{
date_s->month++;
date_s->day = 1;
}
}
else if(date_s->month == 2)
{
if(date_s->day < 28)
{
date_s->day++;
}
else if(date_s->day == 28)
{
/* Leap year */
if(leap_year(date_s->year))
{
date_s->day++;
}
else
{
date_s->month++;
date_s->day = 1;
}
}
else if(date_s->day == 29)
{
date_s->month++;
date_s->day = 1;
}
}
}
/*********************************************************************************************************************
函数名称: Time_Update
功能描述: Updates time when time is 59:59
输 入 : date_s
输 出 : None
*********************************************************************************************************************/
static void Time_Update(RTC_INFOR* date_s)
{
if(date_s->minute < 59)
{
date_s->minute++;
}
else
{
date_s->hour++;
date_s->minute = 0;
}
}
/*********************************************************************************************************************
函数名称: time_acount_gap
功能描述: 将年,月,日,时,分,秒转换成RTC的计数值
输 入: atime ---> 时间结构
err ---> 返回状态码
输 出: 计数值
*********************************************************************************************************************/
static INT32U time_acount_gap(RTC_INFOR atime, INT8S* err)
{
const INT8U month_days[] = {31,28,31,30,31,30,31,31,30,31,30,31};
INT8U year;
INT32U second = 0;
INT32U sec_temp= 0;
INT32U DayTotal= 0;
INT32U TotalDay = 0;
INT32U i;
*err = FORMAT_ERR;
/* 2008 ~ 2099 */
if(atime.year < 2008 || atime.year > 2099 || atime.month < 1 || atime.month > 12)
{
return 0;
}
if(atime.day < 1 || atime.day > month_days[atime.month - 1])
{
return 0;
}
if(atime.month == 2)
{
if(atime.year % 4 != 0)
{
if(atime.day == 29)return 0;
}
}
if(atime.hour > 23 || atime.minute > 59 || atime.second > 59)
{
return 0;
}
*err = RTC_INFOR_OK;
year = atime.year - 2008;
if (atime.month == 1)
{
DayTotal = atime.day - 1;
}
else
{
DayTotal = DayToatlBefor[atime.month-2].total + atime.day - 1;
}
if (atime.month>2)
{
if(leap_year(atime.year))
{
DayTotal = DayTotal + 1;
}
}
for (i=0;i<year;i++)
{
TotalDay = TotalDay + leap_year(2008+i);
}
TotalDay = TotalDay + year * 365 + DayTotal;
sec_temp = atime.hour * 3600 + atime.minute * 60 + atime.second;
second = TotalDay * 86400 + sec_temp;
return second;
}
/*********************************************************************************************************************
函数名称: acount_time_gap
功能描述: 读取当前年,月,日,时,分,秒
输 入: atime ---> 接收缓冲
acount ---> RTC计数值
输 出: 无
*********************************************************************************************************************/
static void acount_time_gap(RTC_INFOR* atime, INT32U acount)
{
INT32U sum_seconds = acount;
INT32U i;
RTC_INFOR init_rtc;
/* 基准时间为: 2008-01-01 00:00:00 */
init_rtc.year = 2008;
init_rtc.month = 1;
init_rtc.day = 1;
init_rtc.hour = 0;
init_rtc.minute = 0;
init_rtc.second = 0;
if( sum_seconds / 86400 != 0 )
{
for( i=0; i< (sum_seconds / 86400); i++ )
{
Date_Update(&init_rtc);
}
}
sum_seconds = sum_seconds % 86400;
if( sum_seconds / 60 != 0 )
{
for( i=0; i< (sum_seconds / 60); i++)
{
Time_Update(&init_rtc);
}
}
init_rtc.second = (INT8U)(sum_seconds % 60);
atime->year = init_rtc.year;
atime->month = init_rtc.month;
atime->day = init_rtc.day;
atime->hour = init_rtc.hour;
atime->minute = init_rtc.minute;
atime->second = init_rtc.second;
atime->Wday = WeekDayNum(init_rtc.year,init_rtc.month,init_rtc.day);
}
/*********************************************************************************************************************
函数名称: RTC_Read
功能描述:
输 入:
输 出:
*********************************************************************************************************************/
INT8S RTC_Read(RTC_INFOR* pdat)
{
INT32U tmr_cnt = 0;
// 获取RTC计数值
tmr_cnt = HibernateRTCGet();
acount_time_gap(pdat, tmr_cnt);
return TRUE;
}
/*********************************************************************************************************************
函数名称:
功能描述:
输 入:
输 出:
*********************************************************************************************************************/
INT8S RTC_Write(RTC_INFOR* pdat)
{
INT32U tmr_cnt = 0;
INT8S err;
tmr_cnt = time_acount_gap(*pdat, &err);
// 设置RTC的值
HibernateRTCSet(tmr_cnt);
// 设置RTC0的匹配值
HibernateRTCMatch0Set(HibernateRTCGet() + 5);
return TRUE;
}
/*********************************************************************************************************************
函数名称:
功能描述:
输 入:
输 出:
*********************************************************************************************************************/
#if 0
void HibernateHandler(void)
{
INT32U ulStatus;
ulStatus = HibernateIntStatus(1);
// 清除休眠模块中断状态
HibernateIntClear(ulStatus);
if(ulStatus & HIBERNATE_INT_RTC_MATCH_0)
{
HibernateRTCMatch0Set(HibernateRTCGet() + 5);
}
}
#endif
/*********************************************************************************************************************
函数名称: RTC_Init
功能描述: RTC模块初始化,在使用RTC之前需先调用
输 入: NONE
输 出: 0 --> sucess
*********************************************************************************************************************/
INT8S RTC_Init(void)
{
// 使能休眠模块
SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
HibernateEnableExpClk(SysCtlClockGet());
// 选择时钟源为4.194304MHz振荡器
HibernateClockSelect(HIBERNATE_CLOCK_SEL_DIV128);
// 设置冬眠模块RTC唤醒
HibernateWakeSet(HIBERNATE_WAKE_RTC);
// 设置RTC的匹配值
HibernateRTCMatch0Set(HibernateRTCGet() + 5);
// 使能RTC匹配0中断
// HibernateIntEnable(HIBERNATE_INT_RTC_MATCH_0);
// 清除所有中断状态
// HibernateIntClear(HIBERNATE_INT_PIN_WAKE | HIBERNATE_INT_LOW_BAT |HIBERNATE_INT_RTC_MATCH_0 | HIBERNATE_INT_RTC_MATCH_1);
// 注册中断句柄
// HibernateIntRegister(HibernateHandler);
// 使能RTC模块
HibernateRTCEnable();
HibernateRequest();
return 0;
}
/*********************************************************************************************************************
end file
**********************************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -