[APM32E0] APM32E030的RTC驱动(闹钟)

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

APM32E030的RTC支持闹钟功能;

驱动代码如下:
  1. /* RTC初始化标记 */
  2. #define RTC_BKP_DATA    (RTC_BAKP_DATA0)
  3. #define BKP_DATA        (0x12345678)
  4. /* 报警处理函数 */
  5. static rtc_alarm_deal_func_f rtc_alarm_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_17 */
  65.     EINT_ConfigStructInit(&eintConfig);
  66.     eintConfig.line    = EINT_LINE17;
  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_17 */
  12.     if (EINT_ReadIntFlag(EINT_LINE17) != RESET) {
  13.         EINT_ClearIntFlag(EINT_LINE17);
  14.     }
  15.     /* 报警标志 */
  16.     if (RTC_ReadIntFlag(RTC_INT_FLAG_ALR) != RESET) {
  17.         /* 允许RTC寄存器可写 */
  18.         PMU_EnableBackupAccess();
  19.         RTC_ClearIntFlag(RTC_INT_FLAG_ALR);
  20.         /* 禁止RTC寄存器可写 */
  21.         PMU_DisableBackupAccess();
  22.         (rtc_alarm_deal_func != NULL) ? rtc_alarm_deal_func() : NULL;
  23.     }
  24. }
  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       设置RTC闹钟时间
  3. *
  4. * @param       alarm_dt: 闹钟日期时间
  5. *              alarm_mask: 闹钟屏蔽位
  6. *
  7. * @retval      None
  8. *
  9. */
  10. void bsp_rtc_alarm_datetime_set(struct datetime_t *alarm_dt, struct alarm_mask_t *alarm_mask)
  11. {
  12.     RTC_ALARM_T alarmStruct;
  13.     uint32_t mask = 0;
  14.    
  15.     if (alarm_dt != NULL) {
  16.         /* 允许RTC寄存器可写 */
  17.         PMU_EnableBackupAccess();
  18.         /* 先关闭闹钟才允许更新闹钟时间 */
  19.         if (RTC_DisableAlarm() == SUCCESS) {
  20.             mask |= (((alarm_mask->mask_second != 0) ? 1UL : 0) << 7);
  21.             mask |= (((alarm_mask->mask_minute != 0) ? 1UL : 0) << 15);
  22.             mask |= (((alarm_mask->mask_hour != 0) ? 1UL : 0) << 23);
  23.             mask |= (((alarm_mask->mask_day != 0) ? 1UL : 0) << 31);
  24.             
  25.             RTC_ConfigAlarmStructInit(&alarmStruct);
  26.             alarmStruct.time.hours = alarm_dt->hour;
  27.             alarmStruct.time.minutes = alarm_dt->minute;
  28.             alarmStruct.time.seconds = alarm_dt->second;
  29.             alarmStruct.AlarmDateWeekDay = ((alarm_mask->specify_day_or_week != 0) ? alarm_dt->week : alarm_dt->day);
  30.             alarmStruct.AlarmDateWeekDaySel = (RTC_WEEKDAY_SEL_T)alarm_mask->specify_day_or_week;
  31.             alarmStruct.AlarmMask = mask;
  32.             RTC_ConfigAlarm(RTC_FORMAT_BIN, &alarmStruct);
  33.             RTC_ClearIntFlag(RTC_INT_FLAG_ALR);
  34.             /* 使能报警中断 */
  35.             RTC_EnableInterrupt(RTC_INT_ALR);
  36.             RTC_EnableAlarm();
  37.         }
  38.         
  39.         /* 禁止RTC寄存器可写 */
  40.         PMU_DisableBackupAccess();
  41.     }
  42. }
  1. /*
  2. * @brief       获取RTC闹钟时间
  3. *
  4. * @param       alarm_dt: 闹钟日期时间
  5. *
  6. * @retval      None
  7. *
  8. */
  9. void bsp_rtc_alarm_datetime_get(struct datetime_t *alarm_dt)
  10. {
  11.     RTC_ALARM_T alarmStruct;
  12.    
  13.     if (alarm_dt != NULL) {   
  14.         memset(alarm_dt, 0, sizeof(struct datetime_t));        
  15.         RTC_ReadAlarm(RTC_FORMAT_BIN, &alarmStruct);
  16.         alarm_dt->second = alarmStruct.time.seconds;
  17.         alarm_dt->minute = alarmStruct.time.minutes;
  18.         alarm_dt->hour = alarmStruct.time.hours;
  19.         if (alarmStruct.AlarmDateWeekDaySel == RTC_WEEKDAY_SEL_DATE) {
  20.             alarm_dt->day = alarmStruct.AlarmDateWeekDay;
  21.         } else {
  22.             alarm_dt->week = alarmStruct.AlarmDateWeekDay;
  23.         }
  24.     }
  25. }
  1. /*
  2. * @brief       关闭闹钟
  3. *
  4. * @param       None
  5. *
  6. * @retval      0-失败, 1-成功
  7. *
  8. */
  9. uint8_t bsp_rtc_alarm_disable(void)
  10. {
  11.     uint8_t ret = 0;
  12.    
  13.     /* 允许RTC寄存器可写 */
  14.     PMU_EnableBackupAccess();
  15.     RTC_DisableInterrupt(RTC_INT_ALR);
  16.     ret = RTC_DisableAlarm();
  17.     /* 禁止RTC寄存器可写 */
  18.     PMU_DisableBackupAccess();
  19.    
  20.     return (ret == SUCCESS);
  21. }
  1. /*
  2. * @brief       注册报警处理函数
  3. *
  4. * @param       func: 报警处理函数
  5. *
  6. * @retval      None
  7. *
  8. */
  9. void bsp_rtc_alarm_deal_func_register(rtc_alarm_deal_func_f func)
  10. {
  11.     rtc_alarm_deal_func = func;
  12. }


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

  4. struct datetime_t app_alarm_datetime;
  5. struct datetime_t app_alarm_datetime_get;
  6. struct alarm_mask_t app_alarm_mask;
  7. uint8_t wait_for_alarm;
  1. void test_gpio_init(void)
  2. {
  3.     GPIO_Config_T gpioConfig;
  4.     RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);
  5.     GPIO_ConfigStructInit(&gpioConfig);
  6.     gpioConfig.pin     = GPIO_PIN_5;
  7.     gpioConfig.mode    = GPIO_MODE_OUT;
  8.     gpioConfig.outtype = GPIO_OUT_TYPE_PP;
  9.     gpioConfig.speed   = GPIO_SPEED_50MHz;
  10.     gpioConfig.pupd    = GPIO_PUPD_NO;
  11.     GPIO_Config(GPIOA, &gpioConfig);
  12. }
  1. void test_gpio_toggle(void)
  2. {
  3.     (GPIO_ReadOutputBit(GPIOA, GPIO_PIN_5) == BIT_SET) ? \
  4.         GPIO_ClearBit(GPIOA, GPIO_PIN_5) : \
  5.         GPIO_SetBit(GPIOA, GPIO_PIN_5);
  6.     wait_for_alarm = 2;
  7. }
  1. // 应用初始化
  2. void app_init(void)
  3. {   
  4.     bsp_rtc_alarm_deal_func_register(test_gpio_toggle);
  5.     bsp_rtc_init();
  6. }
  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 ((wait_for_alarm == 0) && (datetime_get.second < 30)) {
  12.         app_alarm_datetime = datetime_get;
  13.         app_alarm_datetime.second += 5;
  14.         bsp_rtc_alarm_datetime_set(&app_alarm_datetime, &app_alarm_mask);
  15.         bsp_rtc_alarm_datetime_get(&app_alarm_datetime_get);
  16.         wait_for_alarm = 1;
  17.     } else if (wait_for_alarm == 2) {
  18.         bsp_rtc_alarm_disable();
  19.     }
  20. }


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

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

本版积分规则

26

主题

54

帖子

0

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