APM32E030的RTC支持闹钟功能;
驱动代码如下:
- /* RTC初始化标记 */
- #define RTC_BKP_DATA (RTC_BAKP_DATA0)
- #define BKP_DATA (0x12345678)
- /* 报警处理函数 */
- static rtc_alarm_deal_func_f rtc_alarm_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_17 */
- EINT_ConfigStructInit(&eintConfig);
- eintConfig.line = EINT_LINE17;
- 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_17 */
- if (EINT_ReadIntFlag(EINT_LINE17) != RESET) {
- EINT_ClearIntFlag(EINT_LINE17);
- }
- /* 报警标志 */
- if (RTC_ReadIntFlag(RTC_INT_FLAG_ALR) != RESET) {
- /* 允许RTC寄存器可写 */
- PMU_EnableBackupAccess();
- RTC_ClearIntFlag(RTC_INT_FLAG_ALR);
- /* 禁止RTC寄存器可写 */
- PMU_DisableBackupAccess();
- (rtc_alarm_deal_func != NULL) ? rtc_alarm_deal_func() : NULL;
- }
- }
- /*
- * @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 设置RTC闹钟时间
- *
- * @param alarm_dt: 闹钟日期时间
- * alarm_mask: 闹钟屏蔽位
- *
- * @retval None
- *
- */
- void bsp_rtc_alarm_datetime_set(struct datetime_t *alarm_dt, struct alarm_mask_t *alarm_mask)
- {
- RTC_ALARM_T alarmStruct;
- uint32_t mask = 0;
-
- if (alarm_dt != NULL) {
- /* 允许RTC寄存器可写 */
- PMU_EnableBackupAccess();
- /* 先关闭闹钟才允许更新闹钟时间 */
- if (RTC_DisableAlarm() == SUCCESS) {
- mask |= (((alarm_mask->mask_second != 0) ? 1UL : 0) << 7);
- mask |= (((alarm_mask->mask_minute != 0) ? 1UL : 0) << 15);
- mask |= (((alarm_mask->mask_hour != 0) ? 1UL : 0) << 23);
- mask |= (((alarm_mask->mask_day != 0) ? 1UL : 0) << 31);
-
- RTC_ConfigAlarmStructInit(&alarmStruct);
- alarmStruct.time.hours = alarm_dt->hour;
- alarmStruct.time.minutes = alarm_dt->minute;
- alarmStruct.time.seconds = alarm_dt->second;
- alarmStruct.AlarmDateWeekDay = ((alarm_mask->specify_day_or_week != 0) ? alarm_dt->week : alarm_dt->day);
- alarmStruct.AlarmDateWeekDaySel = (RTC_WEEKDAY_SEL_T)alarm_mask->specify_day_or_week;
- alarmStruct.AlarmMask = mask;
- RTC_ConfigAlarm(RTC_FORMAT_BIN, &alarmStruct);
- RTC_ClearIntFlag(RTC_INT_FLAG_ALR);
- /* 使能报警中断 */
- RTC_EnableInterrupt(RTC_INT_ALR);
- RTC_EnableAlarm();
- }
-
- /* 禁止RTC寄存器可写 */
- PMU_DisableBackupAccess();
- }
- }
- /*
- * @brief 获取RTC闹钟时间
- *
- * @param alarm_dt: 闹钟日期时间
- *
- * @retval None
- *
- */
- void bsp_rtc_alarm_datetime_get(struct datetime_t *alarm_dt)
- {
- RTC_ALARM_T alarmStruct;
-
- if (alarm_dt != NULL) {
- memset(alarm_dt, 0, sizeof(struct datetime_t));
- RTC_ReadAlarm(RTC_FORMAT_BIN, &alarmStruct);
- alarm_dt->second = alarmStruct.time.seconds;
- alarm_dt->minute = alarmStruct.time.minutes;
- alarm_dt->hour = alarmStruct.time.hours;
- if (alarmStruct.AlarmDateWeekDaySel == RTC_WEEKDAY_SEL_DATE) {
- alarm_dt->day = alarmStruct.AlarmDateWeekDay;
- } else {
- alarm_dt->week = alarmStruct.AlarmDateWeekDay;
- }
- }
- }
- /*
- * @brief 关闭闹钟
- *
- * @param None
- *
- * @retval 0-失败, 1-成功
- *
- */
- uint8_t bsp_rtc_alarm_disable(void)
- {
- uint8_t ret = 0;
-
- /* 允许RTC寄存器可写 */
- PMU_EnableBackupAccess();
- RTC_DisableInterrupt(RTC_INT_ALR);
- ret = RTC_DisableAlarm();
- /* 禁止RTC寄存器可写 */
- PMU_DisableBackupAccess();
-
- return (ret == SUCCESS);
- }
- /*
- * @brief 注册报警处理函数
- *
- * @param func: 报警处理函数
- *
- * @retval None
- *
- */
- void bsp_rtc_alarm_deal_func_register(rtc_alarm_deal_func_f func)
- {
- rtc_alarm_deal_func = func;
- }
测试代码如下:
- struct datetime_t datetime_get;
- struct datetime_t datetime_set;
- uint8_t flag_datetime_set;
- struct datetime_t app_alarm_datetime;
- struct datetime_t app_alarm_datetime_get;
- struct alarm_mask_t app_alarm_mask;
- uint8_t wait_for_alarm;
- void test_gpio_init(void)
- {
- GPIO_Config_T gpioConfig;
- RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);
- GPIO_ConfigStructInit(&gpioConfig);
- gpioConfig.pin = GPIO_PIN_5;
- gpioConfig.mode = GPIO_MODE_OUT;
- gpioConfig.outtype = GPIO_OUT_TYPE_PP;
- gpioConfig.speed = GPIO_SPEED_50MHz;
- gpioConfig.pupd = GPIO_PUPD_NO;
- GPIO_Config(GPIOA, &gpioConfig);
- }
- void test_gpio_toggle(void)
- {
- (GPIO_ReadOutputBit(GPIOA, GPIO_PIN_5) == BIT_SET) ? \
- GPIO_ClearBit(GPIOA, GPIO_PIN_5) : \
- GPIO_SetBit(GPIOA, GPIO_PIN_5);
- wait_for_alarm = 2;
- }
- // 应用初始化
- void app_init(void)
- {
- bsp_rtc_alarm_deal_func_register(test_gpio_toggle);
- bsp_rtc_init();
- }
- // 应用任务
- void app_task(void)
- {
- /* 日期时间 */
- bsp_rtc_datetime_get(&datetime_get);
- if (flag_datetime_set != 0) {
- flag_datetime_set = 0;
- bsp_rtc_datetime_set(&datetime_set);
- }
- /* 闹钟 */
- if ((wait_for_alarm == 0) && (datetime_get.second < 30)) {
- app_alarm_datetime = datetime_get;
- app_alarm_datetime.second += 5;
- bsp_rtc_alarm_datetime_set(&app_alarm_datetime, &app_alarm_mask);
- bsp_rtc_alarm_datetime_get(&app_alarm_datetime_get);
- wait_for_alarm = 1;
- } else if (wait_for_alarm == 2) {
- bsp_rtc_alarm_disable();
- }
- }
详细代码,请查看附件!
Alarm.zip
(2.14 MB, 下载次数: 0)
|