APM32E030的RTC支持记录时间戳功能;
驱动代码如下:
- /* RTC初始化标记 */
- #define RTC_BKP_DATA (RTC_BAKP_DATA0)
- #define BKP_DATA (0x12345678)
- /* 报警处理函数 */
- static rtc_timestamp_deal_func_f rtc_timestamp_deal_func;
- /*
- * [url=/u/brief]@brief[/url] RTC初始化
- *
- * @param None
- *
- * @retval None
- *
- */
- void bsp_rtc_init(void)
- {
- RTC_Config_T RtcStruct;
- RTC_TIME_T timeStruct;
- RTC_DATE_T dateStruct;
- EINT_Config_T eintConfig;
-
- /* 使能RTC区域写, 否则无法开启LSE */
- RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU);
- PMU_EnableBackupAccess();
-
- /* 备份值一致则无需重复初始化 */
- if (RTC_ReadBackup(RTC_BKP_DATA) != BKP_DATA) {
- /* 复位RTC域 */
- RCM_EnableBackupReset();
- __NOP();__NOP();__NOP();__NOP();
- RCM_DisableBackupReset();
-
- /* 开启LSE */
- RCM_ConfigLSE(RCM_LSE_OPEN);
- while (RCM_ReadStatusFlag(RCM_FLAG_LSERDY) != SET);
- RCM_ConfigDriveLSE(RCM_LSE_DRIVE_High);
- /* RTC 时钟为LSE */
- RCM_ConfigRTCCLK(RCM_RTCCLK_LSE);
- RCM_EnableRTCCLK();
-
- /* 配置RTC */
- RTC_Reset();
- RTC_ConfigStructInit(&RtcStruct);
- RtcStruct.format = RTC_HourFormat_24;
- /* 时钟先异步分配,再同步分频到RTC使用
- * 1HZ = 32768 / 128 / 256
- */
- RtcStruct.AsynchPrediv = 128 - 1; /* 异步 */
- RtcStruct.SynchPrediv = 256 - 1; /* 同步 */
- RTC_Config(&RtcStruct);
- /* 配置默认时间 */
- RTC_ConfigTimeStructInit(&timeStruct);
- timeStruct.hours = 12;
- timeStruct.minutes = 10;
- timeStruct.seconds = 10;
- timeStruct.H12 = RTC_H12_AM;
- if (RTC_ConfigTime(RTC_FORMAT_BIN, &timeStruct) == SUCCESS) {
- /* 配置默认日期 */
- RTC_ConfigDateStructInit(&dateStruct);
- dateStruct.weekday = RTC_WEEKDAY_TUESDAY;
- dateStruct.date = 23;
- dateStruct.month = RTC_MONTH_SEPTEMBER;
- dateStruct.year = 25;
- RTC_ConfigDate(RTC_FORMAT_BIN, &dateStruct);
- }
- RTC_WriteBackup(RTC_BKP_DATA, BKP_DATA);
- }
-
- /* EINT */
- /* 时间戳为EINT_19 */
- EINT_ConfigStructInit(&eintConfig);
- eintConfig.line = EINT_LINE19;
- eintConfig.mode = EINT_MODE_INTERRUPT;
- eintConfig.trigger = EINT_TRIGGER_RISING;
- eintConfig.lineCmd = ENABLE;
- EINT_Config(&eintConfig);
-
- /* 使能中断 */
- NVIC_SetPriority(RTC_IRQn, 0);
- NVIC_EnableIRQ(RTC_IRQn);
-
- /* 禁止RTC寄存器可写 */
- PMU_DisableBackupAccess();
- }
- /*
- * @brief 中断
- *
- * @param None
- *
- * @retval None
- *
- */
- void RTC_IRQHandler(void)
- {
- /* EINT_19 */
- if (EINT_ReadIntFlag(EINT_LINE19) != RESET) {
- EINT_ClearIntFlag(EINT_LINE19);
- }
- /* 时间戳标志 */
- if (RTC_ReadIntFlag(RTC_INT_FLAG_TS) != RESET) {
- /* 需先读出数据再清除标志 */
- (rtc_timestamp_deal_func != NULL) ? rtc_timestamp_deal_func() : NULL;
- /* 允许RTC寄存器可写 */
- PMU_EnableBackupAccess();
- RTC_ClearIntFlag(RTC_INT_FLAG_TS);
- /* 禁止RTC寄存器可写 */
- PMU_DisableBackupAccess();
- }
- }
- /*
- * @brief 获取RTC时间
- *
- * @param dt: 日期时间
- *
- * @retval None
- *
- */
- void bsp_rtc_datetime_get(struct datetime_t *dt)
- {
- RTC_TIME_T timeStruct;
- RTC_TIME_T timeStruct2;
- RTC_DATE_T dateStruct;
- RTC_DATE_T dateStruct2;
-
- if (dt != NULL) {
- do {
- RTC_ReadTime(RTC_FORMAT_BIN, &timeStruct);
- RTC_ReadTime(RTC_FORMAT_BIN, &timeStruct2);
- RTC_ReadDate(RTC_FORMAT_BIN, &dateStruct);
- RTC_ReadDate(RTC_FORMAT_BIN, &dateStruct2);
- /* 确保两次读取的数据完全一致,避免卡跨时间点位置导致时间错乱 */
- if ((memcmp(&timeStruct, &timeStruct2, sizeof(RTC_TIME_T)) == 0) && \
- (memcmp(&dateStruct, &dateStruct2, sizeof(RTC_DATE_T)) == 0)) {
- dt->second = timeStruct.seconds;
- dt->minute = timeStruct.minutes;
- dt->hour = timeStruct.hours;
- dt->day = dateStruct.date;
- dt->month = dateStruct.month;
- dt->year = 2000 + dateStruct.year;
- dt->week = dateStruct.weekday;
- break;
- }
- } while (1);
- }
- }
- /*
- * @brief 设置RTC时间
- *
- * @param dt: 日期时间
- *
- * @retval None
- *
- */
- void bsp_rtc_datetime_set(struct datetime_t *dt)
- {
- RTC_TIME_T timeStruct;
- RTC_TIME_T timeStruct2;
- RTC_DATE_T dateStruct;
- RTC_DATE_T dateStruct2;
- uint8_t state;
- uint8_t state2;
-
- /* 填充数据 */
- timeStruct.seconds = dt->second;
- timeStruct.minutes = dt->minute;
- timeStruct.hours = dt->hour;
- dateStruct.date = dt->day;
- dateStruct.month = dt->month;
- dateStruct.year = dt->year % 100;
- dateStruct.weekday = dt->week;
-
- if (dt != NULL) {
- do {
- /* 允许RTC寄存器可写 */
- PMU_EnableBackupAccess();
- /* 配置时间日期 */
- state = RTC_ConfigTime(RTC_FORMAT_BIN, &timeStruct);
- state2 = RTC_ConfigDate(RTC_FORMAT_BIN, &dateStruct);
- if ((state != SUCCESS) || (state2 != SUCCESS)) {
- continue;
- }
- RTC_ReadTime(RTC_FORMAT_BIN, &timeStruct2);
- RTC_ReadDate(RTC_FORMAT_BIN, &dateStruct2);
- /* 确保读取的数据与写入的完全一致 */
- if ((memcmp(&timeStruct, &timeStruct2, sizeof(RTC_TIME_T)) == 0) && \
- (memcmp(&dateStruct, &dateStruct2, sizeof(RTC_DATE_T)) == 0)) {
- break;
- }
- } while (1);
- /* 禁止RTC寄存器可写 */
- PMU_DisableBackupAccess();
- }
- }
- /*
- * @brief 时间戳使能
- *
- * @param None
- *
- * @retval None
- *
- */
- void bsp_rtc_timestamp_enable(void)
- {
- GPIO_Config_T gpioConfig;
-
- /* RTC_TS -> PC13 */
- RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOC);
- GPIO_ConfigStructInit(&gpioConfig);
- gpioConfig.pin = GPIO_PIN_13;
- gpioConfig.mode = GPIO_MODE_AF;
- gpioConfig.outtype = GPIO_OUT_TYPE_PP;
- gpioConfig.speed = GPIO_SPEED_50MHz;
- gpioConfig.pupd = GPIO_PUPD_NO;
- GPIO_Config(GPIOC, &gpioConfig);
-
- /* 允许RTC寄存器可写 */
- PMU_EnableBackupAccess();
-
- /* 关闭输出 */
- RTC_ConfigOutput(RTC_OPSEL_DISABLE, RTC_OPP_LOW);
- /* 关闭校准输出 */
- RTC_DisableCalibOutput();
-
- /* 时间戳上降沿触发 */
- RTC_EnableTimeStamp(RTC_TIME_STAMPEDGE_RISING);
- /* 使能时间戳中断 */
- RTC_EnableInterrupt(RTC_INT_TS);
-
- /* 禁止RTC寄存器可写 */
- PMU_DisableBackupAccess();
- }
|