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的示例,在示例中有详细的说明。