MAX78000有RTC来实现日期时间,这一篇将如何快速配置RTC并实现时间的打印。
1、在工程中引用rtc.h
2、MAX78000的RTC读取的是一个32位的时间戳,单位为秒,另一个寄存器为16位的时间戳但是有效时间为低12位,单位为亚秒。
读取他们值,在sdk库中已经给出了:
int MXC_RTC_GetSubSeconds(uint32_t *ssec); int MXC_RTC_GetSeconds(uint32_t *sec);
3、在初始化中,sdk给出了初始化的函数:
/** * @brief Initialize the sec and ssec registers and enable RTC (Blocking function) * @param sec set the RTC Sec counter (32-bit) * @param ssec set the RTC Sub-second counter (12-bit) * @retval returns Success or Fail, see \ref MXC_ERROR_CODES */ int MXC_RTC_Init(uint32_t sec, uint16_t ssec);
【注】在此篇中,我们不需要读取亚秒,因此只需要传入32位的时间戳即可。
【辅助函数】
为了转化时间戳,我添加了如下函数:
#define MSEC_TO_RSSA(x) \
(0 - ((x * 4096) / \
1000)) /* Converts a time in milleseconds to the equivalent RSSA register value. */
#define SECS_PER_MIN 60
#define SECS_PER_HR (60 * SECS_PER_MIN)
#define SECS_PER_DAY (24 * SECS_PER_HR)
TaskHandle_t xTask1Handle = NULL;
extern BloodData g_blooddata ;
/* 任务函数声明 */
void vTask1(void *pvParameters);
// 判断是否为闰年
int isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
// 获取指定年份中每个月的天数
void getDaysInMonth(int year, int daysInMonth[]) {
daysInMonth[0] = 0; // 不使用索引0
daysInMonth[1] = 31;
daysInMonth[2] = isLeapYear(year) ? 29 : 28; // 闰年2月29天
daysInMonth[3] = 31;
daysInMonth[4] = 30;
daysInMonth[5] = 31;
daysInMonth[6] = 30;
daysInMonth[7] = 31;
daysInMonth[8] = 31;
daysInMonth[9] = 30;
daysInMonth[10] = 31;
daysInMonth[11] = 30;
daysInMonth[12] = 31;
}
// 将从2000年1月1日起的时间戳转换为日期时间
void timestampToDateTime(long timestamp, int *year, int *month, int *day, int *hour, int *minute, int *second) {
long sec = timestamp;
// 计算时、分、秒(已有代码)
// 计算天数(从2000年1月1日起)
long dayCount = sec / SECS_PER_DAY;
sec -= dayCount * SECS_PER_DAY; // 剩余秒数用于计算时、分、秒
// 计算时、分、秒
*hour = sec / SECS_PER_HR;
sec -= *hour * SECS_PER_HR;
*minute = sec / SECS_PER_MIN;
sec -= *minute * SECS_PER_MIN;
*second = sec;
// 计算天数(从2000年1月1日起)
// 计算年份
*year = 2000;
while (1) {
int daysInYear = isLeapYear(*year) ? 366 : 365;
if (dayCount < daysInYear) break;
dayCount -= daysInYear;
(*year)++;
}
// 计算月份和日期
int daysInMonth[13];
getDaysInMonth(*year, daysInMonth);
*month = 1;
while (*month <= 12) {
if (dayCount < daysInMonth[*month]) break;
dayCount -= daysInMonth[*month];
(*month)++;
}
*day = (int)dayCount + 1; // +1是因为天数从0开始计数,而日期从1开始
}
// 计算从2000年1月1日起的天数
int daysSince2000(int year, int month, int day) {
int days = 0;
int i;
// 计算完整年份的天数
for (i = 2000; i < year; i++) {
days += isLeapYear(i) ? 366 : 365;
}
// 计算当年到目标月份的天数
int daysInMonth[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (isLeapYear(year)) {
daysInMonth[2] = 29; // 闰年2月29天
}
for (i = 1; i < month; i++) {
days += daysInMonth[i];
}
// 加上当月的天数
days += day;
return days;
}
void printTime(void)
{
int year, month, day, hour, minute, second,err;
uint32_t rtc_readout;
// do {
// err = MXC_RTC_GetSubSeconds(&rtc_readout);
// } while (err != E_NO_ERROR);
// subsec = rtc_readout / 4096.0;
do {
err = MXC_RTC_GetSeconds(&rtc_readout);
} while (err != E_NO_ERROR);
// 转换时间戳为日期时间
timestampToDateTime(rtc_readout, &year, &month, &day, &hour, &minute, &second);
printf("timestamp %ld datetime: %04d-%02d-%02d %02d:%02d:%02d\n",
rtc_readout, year, month, day, hour, minute, second);
}以上辅助函数功能为由给出的年月日函数转化为时间戳,或者是读出的时间戳转化为时间。
【测试】
在初始化中,给出初始的时间,然后转化为时间戳,通过rtcinit写入RTC寄存器,然后在任务函数中读取并通过串口输出:
int year = 2025;
int month = 6;
int day = 27;
int hour = 16;
int minute = 7;
int second = 0;
// 计算从2000年1月1日起的总秒数
int totalDays = daysSince2000(year, month, day);
long timestamp = (long)totalDays * SECS_PER_DAY +
hour * SECS_PER_HR +
minute * SECS_PER_MIN +
second;
printf("从2000年1月1日00:00:00到%04d-%02d-%02d %02d:%02d:%02d的时间戳为: %ld\n",
year, month, day, hour, minute, second, timestamp);
if (MXC_RTC_Init(timestamp, 0) != E_NO_ERROR) {
printf("Failed RTC Initialization\n");
printf("Example Failed\n");
while (1) {}
}
if (MXC_RTC_Start() != E_NO_ERROR) {
printf("Failed RTC_Start\n");
printf("Example Failed\n");
while (1) {}
}
printf("RTC started\n");打印时间:

实现效果:

【总结】
在MAX78000的sdk中给出了RTC封装好的函数,非常简单的就可以实现RTC的功能,当然如果想实现中断,还需要一简单的配置,大家可以创建一个RTC的示例,在示例中有详细的说明。
我要赚赏金
