[APM32E0] APM32E030的RTC驱动(时间戳)

[复制链接]
24|0
口天土立口 发表于 2025-10-15 19:10 | 显示全部楼层 |阅读模式
584768ef807e87a58.png

APM32E030的RTC支持记录时间戳功能;

驱动代码如下:
  1. /* RTC初始化标记 */
  2. #define RTC_BKP_DATA    (RTC_BAKP_DATA0)
  3. #define BKP_DATA        (0x12345678)
  4. /* 报警处理函数 */
  5. static rtc_timestamp_deal_func_f rtc_timestamp_deal_func;
  1. /*
  2. * [url=/u/brief]@brief[/url]       RTC初始化
  3. *
  4. * @param       None
  5. *
  6. * @retval      None
  7. *
  8. */
  9. void bsp_rtc_init(void)
  10. {
  11.     RTC_Config_T RtcStruct;
  12.     RTC_TIME_T timeStruct;
  13.     RTC_DATE_T dateStruct;
  14.     EINT_Config_T eintConfig;
  15.    
  16.     /* 使能RTC区域写, 否则无法开启LSE */
  17.     RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU);
  18.     PMU_EnableBackupAccess();
  19.    
  20.     /* 备份值一致则无需重复初始化 */
  21.     if (RTC_ReadBackup(RTC_BKP_DATA) != BKP_DATA) {   
  22.         /* 复位RTC域 */
  23.         RCM_EnableBackupReset();
  24.         __NOP();__NOP();__NOP();__NOP();
  25.         RCM_DisableBackupReset();
  26.         
  27.         /* 开启LSE */
  28.         RCM_ConfigLSE(RCM_LSE_OPEN);
  29.         while (RCM_ReadStatusFlag(RCM_FLAG_LSERDY) != SET);
  30.         RCM_ConfigDriveLSE(RCM_LSE_DRIVE_High);
  31.         /* RTC 时钟为LSE */
  32.         RCM_ConfigRTCCLK(RCM_RTCCLK_LSE);
  33.         RCM_EnableRTCCLK();
  34.         
  35.         /* 配置RTC */
  36.         RTC_Reset();
  37.         RTC_ConfigStructInit(&RtcStruct);
  38.         RtcStruct.format = RTC_HourFormat_24;
  39.         /* 时钟先异步分配,再同步分频到RTC使用
  40.          * 1HZ = 32768 / 128 / 256
  41.          */
  42.         RtcStruct.AsynchPrediv = 128 - 1;   /* 异步 */
  43.         RtcStruct.SynchPrediv = 256 - 1;    /* 同步 */
  44.         RTC_Config(&RtcStruct);
  45.         /* 配置默认时间 */
  46.         RTC_ConfigTimeStructInit(&timeStruct);
  47.         timeStruct.hours = 12;
  48.         timeStruct.minutes = 10;
  49.         timeStruct.seconds = 10;
  50.         timeStruct.H12 = RTC_H12_AM;
  51.         if (RTC_ConfigTime(RTC_FORMAT_BIN, &timeStruct) == SUCCESS) {
  52.             /* 配置默认日期 */
  53.             RTC_ConfigDateStructInit(&dateStruct);
  54.             dateStruct.weekday = RTC_WEEKDAY_TUESDAY;
  55.             dateStruct.date = 23;
  56.             dateStruct.month = RTC_MONTH_SEPTEMBER;
  57.             dateStruct.year = 25;
  58.             RTC_ConfigDate(RTC_FORMAT_BIN, &dateStruct);
  59.         }
  60.         RTC_WriteBackup(RTC_BKP_DATA, BKP_DATA);
  61.     }
  62.    
  63.     /* EINT */
  64.     /* 时间戳为EINT_19 */
  65.     EINT_ConfigStructInit(&eintConfig);
  66.     eintConfig.line    = EINT_LINE19;
  67.     eintConfig.mode    = EINT_MODE_INTERRUPT;
  68.     eintConfig.trigger = EINT_TRIGGER_RISING;
  69.     eintConfig.lineCmd = ENABLE;
  70.     EINT_Config(&eintConfig);
  71.    
  72.     /* 使能中断 */
  73.     NVIC_SetPriority(RTC_IRQn, 0);
  74.     NVIC_EnableIRQ(RTC_IRQn);
  75.    
  76.     /* 禁止RTC寄存器可写 */
  77.     PMU_DisableBackupAccess();
  78. }
  1. /*
  2. * @brief       中断
  3. *
  4. * @param       None
  5. *
  6. * @retval      None
  7. *
  8. */
  9. void RTC_IRQHandler(void)
  10. {
  11.     /* EINT_19 */
  12.     if (EINT_ReadIntFlag(EINT_LINE19) != RESET) {
  13.         EINT_ClearIntFlag(EINT_LINE19);
  14.     }
  15.     /* 时间戳标志 */
  16.     if (RTC_ReadIntFlag(RTC_INT_FLAG_TS) != RESET) {
  17.         /* 需先读出数据再清除标志 */
  18.         (rtc_timestamp_deal_func != NULL) ? rtc_timestamp_deal_func() : NULL;
  19.         /* 允许RTC寄存器可写 */
  20.         PMU_EnableBackupAccess();
  21.         RTC_ClearIntFlag(RTC_INT_FLAG_TS);
  22.         /* 禁止RTC寄存器可写 */
  23.         PMU_DisableBackupAccess();
  24.     }
  25. }
  1. /*
  2. * @brief       获取RTC时间
  3. *
  4. * @param       dt: 日期时间
  5. *
  6. * @retval      None
  7. *
  8. */
  9. void bsp_rtc_datetime_get(struct datetime_t *dt)
  10. {
  11.     RTC_TIME_T timeStruct;
  12.     RTC_TIME_T timeStruct2;
  13.     RTC_DATE_T dateStruct;
  14.     RTC_DATE_T dateStruct2;
  15.    
  16.     if (dt != NULL) {   
  17.         do {
  18.             RTC_ReadTime(RTC_FORMAT_BIN, &timeStruct);
  19.             RTC_ReadTime(RTC_FORMAT_BIN, &timeStruct2);
  20.             RTC_ReadDate(RTC_FORMAT_BIN, &dateStruct);
  21.             RTC_ReadDate(RTC_FORMAT_BIN, &dateStruct2);
  22.             /* 确保两次读取的数据完全一致,避免卡跨时间点位置导致时间错乱 */
  23.             if ((memcmp(&timeStruct, &timeStruct2, sizeof(RTC_TIME_T)) == 0) && \
  24.                 (memcmp(&dateStruct, &dateStruct2, sizeof(RTC_DATE_T)) == 0)) {
  25.                 dt->second = timeStruct.seconds;
  26.                 dt->minute = timeStruct.minutes;
  27.                 dt->hour = timeStruct.hours;
  28.                 dt->day = dateStruct.date;
  29.                 dt->month = dateStruct.month;
  30.                 dt->year = 2000 + dateStruct.year;
  31.                 dt->week = dateStruct.weekday;
  32.                 break;
  33.             }
  34.         } while (1);
  35.     }
  36. }
  1. /*
  2. * @brief       设置RTC时间
  3. *
  4. * @param       dt: 日期时间
  5. *
  6. * @retval      None
  7. *
  8. */
  9. void bsp_rtc_datetime_set(struct datetime_t *dt)
  10. {
  11.     RTC_TIME_T timeStruct;
  12.     RTC_TIME_T timeStruct2;
  13.     RTC_DATE_T dateStruct;
  14.     RTC_DATE_T dateStruct2;
  15.     uint8_t state;
  16.     uint8_t state2;
  17.    
  18.     /* 填充数据 */
  19.     timeStruct.seconds = dt->second;
  20.     timeStruct.minutes = dt->minute;   
  21.     timeStruct.hours = dt->hour;
  22.     dateStruct.date = dt->day;
  23.     dateStruct.month = dt->month;
  24.     dateStruct.year = dt->year % 100;
  25.     dateStruct.weekday = dt->week;
  26.    
  27.     if (dt != NULL) {   
  28.         do {
  29.             /* 允许RTC寄存器可写 */
  30.             PMU_EnableBackupAccess();
  31.             /* 配置时间日期 */
  32.             state = RTC_ConfigTime(RTC_FORMAT_BIN, &timeStruct);
  33.             state2 = RTC_ConfigDate(RTC_FORMAT_BIN, &dateStruct);
  34.             if ((state != SUCCESS) || (state2 != SUCCESS)) {
  35.                 continue;
  36.             }
  37.             RTC_ReadTime(RTC_FORMAT_BIN, &timeStruct2);
  38.             RTC_ReadDate(RTC_FORMAT_BIN, &dateStruct2);
  39.             /* 确保读取的数据与写入的完全一致 */
  40.             if ((memcmp(&timeStruct, &timeStruct2, sizeof(RTC_TIME_T)) == 0) && \
  41.                 (memcmp(&dateStruct, &dateStruct2, sizeof(RTC_DATE_T)) == 0)) {
  42.                 break;
  43.             }
  44.         } while (1);
  45.         /* 禁止RTC寄存器可写 */
  46.         PMU_DisableBackupAccess();
  47.     }
  48. }
  1. /*
  2. * @brief       时间戳使能
  3. *
  4. * @param       None
  5. *
  6. * @retval      None
  7. *
  8. */
  9. void bsp_rtc_timestamp_enable(void)
  10. {   
  11.     GPIO_Config_T gpioConfig;
  12.    
  13.     /* RTC_TS -> PC13 */
  14.     RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOC);
  15.     GPIO_ConfigStructInit(&gpioConfig);
  16.     gpioConfig.pin     = GPIO_PIN_13;
  17.     gpioConfig.mode    = GPIO_MODE_AF;
  18.     gpioConfig.outtype = GPIO_OUT_TYPE_PP;
  19.     gpioConfig.speed   = GPIO_SPEED_50MHz;
  20.     gpioConfig.pupd    = GPIO_PUPD_NO;
  21.     GPIO_Config(GPIOC, &gpioConfig);
  22.    
  23.     /* 允许RTC寄存器可写 */
  24.     PMU_EnableBackupAccess();
  25.    
  26.     /* 关闭输出 */
  27.     RTC_ConfigOutput(RTC_OPSEL_DISABLE, RTC_OPP_LOW);
  28.     /* 关闭校准输出 */
  29.     RTC_DisableCalibOutput();
  30.         
  31.     /* 时间戳上降沿触发 */
  32.     RTC_EnableTimeStamp(RTC_TIME_STAMPEDGE_RISING);
  33.     /* 使能时间戳中断 */
  34.     RTC_EnableInterrupt(RTC_INT_TS);
  35.    
  36.     /* 禁止RTC寄存器可写 */
  37.     PMU_DisableBackupAccess();
  38. }
  1. /*
  2. * @brief       获取RTC时间戳
  3. *
  4. * @param       ts: 时间戳
  5. *
  6. * @retval      None
  7. *
  8. */
  9. void bsp_rtc_timestamp_get(struct timestamp_t *ts)
  10. {
  11.     RTC_TIME_T timeStruct;
  12.     RTC_DATE_T dateStruct;
  13.    
  14.     if (ts != NULL) {   
  15.         memset(ts, 0, sizeof(struct timestamp_t));        
  16.         RTC_ReadTimeDate(RTC_FORMAT_BIN, &timeStruct, &dateStruct);
  17.         ts->second = timeStruct.seconds;
  18.         ts->minute = timeStruct.minutes;
  19.         ts->hour = timeStruct.hours;
  20.         ts->timecfg = timeStruct.H12;
  21.         ts->day = dateStruct.date;
  22.         ts->month = dateStruct.month;
  23.         ts->week = dateStruct.weekday;
  24.         ts->millsecond = RTC_ReadTimeStampSubSecond();
  25.     }
  26. }
  1. /*
  2. * @brief       关闭时间戳
  3. *
  4. * @param       None
  5. *
  6. * @retval      None
  7. *
  8. */
  9. void bsp_rtc_timestamp_disable(void)
  10. {   
  11.     /* 允许RTC寄存器可写 */
  12.     PMU_EnableBackupAccess();
  13.     /* 关闭时间戳 */
  14.     RTC_DisableTimeStamp(RTC_TIME_STAMPEDGE_RISING);
  15.     /* 使能时间戳中断 */
  16.     RTC_DisableInterrupt(RTC_INT_TS);   
  17.     /* 禁止RTC寄存器可写 */
  18.     PMU_DisableBackupAccess();
  19. }
  1. /*
  2. * @brief       注册时间戳处理函数
  3. *
  4. * @param       func: 时间戳处理函数
  5. *
  6. * @retval      None
  7. *
  8. */
  9. void bsp_rtc_alarm_deal_func_register(rtc_timestamp_deal_func_f func)
  10. {
  11.     rtc_timestamp_deal_func = func;
  12. }


测试代码如下:
  1. struct datetime_t datetime_get;
  2. struct datetime_t datetime_set;
  3. uint8_t flag_datetime_set;
  4. uint8_t flag_timestamp_set;

  5. struct datetime_t app_alarm_datetime;
  6. struct datetime_t app_alarm_datetime_get;
  7. struct timestamp_t timestamp;
  1. /* PA5短接PC13 */
  2. void test_gpio_init(void)
  3. {
  4.     GPIO_Config_T gpioConfig;
  5.    
  6.     RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);
  7.     GPIO_ConfigStructInit(&gpioConfig);
  8.     gpioConfig.pin     = GPIO_PIN_5;
  9.     gpioConfig.mode    = GPIO_MODE_OUT;
  10.     gpioConfig.outtype = GPIO_OUT_TYPE_PP;
  11.     gpioConfig.speed   = GPIO_SPEED_50MHz;
  12.     gpioConfig.pupd    = GPIO_PUPD_NO;
  13.     GPIO_Config(GPIOA, &gpioConfig);
  14. }
  1. void timestamp_get(void)
  2. {
  3.     bsp_rtc_timestamp_get(&timestamp);
  4. }

  5. // 应用初始化
  6. void app_init(void)
  7. {   
  8.     test_gpio_init();
  9.     bsp_rtc_alarm_deal_func_register(timestamp_get);
  10.     bsp_rtc_init();
  11.     bsp_rtc_timestamp_enable();
  12. }
  1. // 应用任务
  2. void app_task(void)
  3. {   
  4.     /* 日期时间 */
  5.     bsp_rtc_datetime_get(&datetime_get);
  6.     if (flag_datetime_set != 0) {
  7.         flag_datetime_set = 0;
  8.         bsp_rtc_datetime_set(&datetime_set);
  9.     }
  10.     /* 触发时间戳 */
  11.     if (flag_timestamp_set != 0) {
  12.         flag_timestamp_set = 0;
  13.         GPIO_SetBit(GPIOA, GPIO_PIN_5);
  14.     }
  15. }


详细代码,请查看附件!
Timestamp.zip (2.15 MB, 下载次数: 0)




您需要登录后才可以回帖 登录 | 注册

本版积分规则

26

主题

54

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部