[APM32F4] APM32F427的RTC驱动(日历、闹钟和时间戳)

[复制链接]
38|0
口天土立口 发表于 2025-11-20 14:51 | 显示全部楼层 |阅读模式
本帖最后由 口天土立口 于 2025-11-20 14:52 编辑

#技术资源# #申请原创#

@21小跑堂

1. 外设介绍
9411691eb89ae7778.png
日历时间在很多产品中,都是必备的功能,而APM32F427拥有硬件RTC,无需再软件实现日历时间的功能。而备份域的加入,为程序的复位判断提供比较好的依据,可以辅助程序判断复位后是否需要重新初始化RTC为默认时间。
实际产品应用中,有高精度日历时间需求的话,会在电路上再配置一颗专业的RTC独立芯片,此芯片一般能做到24小时的误差小于1秒,同时再每天定时联网校准一次时间,可基本忽略时间的误差,例如南方电网或国家电网给用户安装的电表就是类似的操作。而允许时间日历误差较大的产品中,MCU内置的RTC就能满足需求,同时结合定时联网校准时间,误差也不至于偏差太离谱,当然在这种场景中,请尽量加入Vbat供电和LSE作为RTC的时钟。
RTC的使用,一般会提供Vbat供电,此供电一般为焊接在电路板上的电池(纽扣电池或小容量锂电池),像在电脑的主板上就有一颗纽扣电池,用于提供在产品主电源断电之后的RTC持续工作电源,以防止时间复位。而LSERTC提供精准的时钟源,同时外部晶振相对受环境影响较小,减少RTC的误差。

2. 硬件
APM32F427ZG TINY

3. 驱动介绍
RTC寄存器默认处于禁止写入状态,需要使能PMU模块,并开启PMU对应寄存器内的使能写备份区域位才允许写入RTCif (RTC_ReadBackup(RTC_BKP_DATA) != BKP_DATA)的操作,判断RTC的配置是否需要重新初始化,在MCU不断电而产生的复位情况下,备份区域和RTC的配置都不会丢失,所以不需要重新初始化,初始化反而导致日历时间倒退不是最新的时间。只有MCU完全断电再上电的场景,会导致备份区域的数据丢失,判断不一致后进入RTC初始化流程。
  1. /* RTC初始化标记 */
  2. #define RTC_BKP_DATA    (RTC_BAKP_REG_0)
  3. #define BKP_DATA        (0x12345678)

  4. /*
  5. * @brief       RTC初始化
  6. *
  7. * @param       None
  8. *
  9. * @retval      None
  10. *
  11. */
  12. void bsp_rtc_init(void)
  13. {
  14.     RTC_Config_T RtcStruct;
  15.     RTC_TimeConfig_T timeConfig;
  16.     RTC_DateConfig_T dateConfig;
  17.    
  18.     /* 使能RTC区域写, 否则无法开启LSE */
  19.     RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU);
  20.     PMU_EnableBackupAccess();
  21.    
  22.     /* 备份值一致则无需重复初始化 */
  23.     if (RTC_ReadBackup(RTC_BKP_DATA) != BKP_DATA) {   
  24.         /* 复位RTC域 */
  25.         RCM_EnableBackupReset();
  26.         __NOP();__NOP();__NOP();__NOP();
  27.         RCM_DisableBackupReset();
  28.         
  29.         /* 开启LSE */
  30.         RCM_ConfigLSE(RCM_LSE_OPEN);
  31.         while (RCM_ReadStatusFlag(RCM_FLAG_LSERDY) != SET);
  32.         /* RTC 时钟为LSE */
  33.         RCM_ConfigRTCCLK(RCM_RTCCLK_LSE);
  34.         RCM_EnableRTCCLK();
  35.         
  36.         /* 配置RTC */
  37.         RTC_Reset();
  38.         RTC_ConfigStructInit(&RtcStruct);
  39.         RtcStruct.format = RTC_HOURFORMAT_24;
  40.         /* 时钟先异步分配,再同步分频到RTC使用
  41.          * 1HZ = 32768 / 256 / 128
  42.          */
  43.         RtcStruct.synchPrediv = 256 - 1;
  44.         RtcStruct.asynchPrediv = 128 - 1;
  45.         RTC_Config(&RtcStruct);
  46.         /* 配置默认时间 */
  47.         RTC_ConfigTimeStructInit(&timeConfig);
  48.         timeConfig.hours = 12;
  49.         timeConfig.minutes = 10;
  50.         timeConfig.seconds = 10;
  51.         timeConfig.h12 = RTC_H12_AM;
  52.         if (RTC_ConfigTime(RTC_FORMAT_BIN, &timeConfig) == SUCCESS) {
  53.             /* 配置默认日期 */
  54.             RTC_ConfigDateStructInit(&dateConfig);
  55.             dateConfig.weekday = RTC_WEEKDAY_TUESDAY;
  56.             dateConfig.date = 23;
  57.             dateConfig.month = RTC_MONTH_SEPTEMBER;
  58.             dateConfig.year = 25;
  59.             RTC_ConfigDate(RTC_FORMAT_BIN, &dateConfig);
  60.         }
  61.         RTC_WriteBackup(RTC_BKP_DATA, BKP_DATA);
  62.     }
  63.    
  64.     /* 禁止RTC寄存器可写 */
  65.     PMU_DisableBackupAccess();
  66. }

读取RTC时间,需注意要连续读两次,确保两次读到的时间日期数据都一致的才使用。因为读数据过程中,RTC依然保持在运行,同时时间和日期是两个寄存器,存在数据读取的先后顺序,而读取的过程中,会存在时间和日期跨秒、跨分、跨时、跨日、跨月和跨年的问题,例如:本来应该读取到的时间寄存器数据为23:59:59,日期寄存器为241231日,但因为刚读完时间寄存器为23:59:59,日期寄存器就加了1秒进入了2511日,所以如果不重复连续再读一遍才确认使用的话,就存在本来应该是为24123123:59:59的日期时间,变成了251123:59:59
  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_TimeConfig_T timeConfig;
  12.     RTC_TimeConfig_T timeConfig2;
  13.     RTC_DateConfig_T dateConfig;
  14.     RTC_DateConfig_T dateConfig2;
  15.    
  16.     if (dt != NULL) {   
  17.         do {
  18.             RTC_ReadTime(RTC_FORMAT_BIN, &timeConfig);
  19.             RTC_ReadTime(RTC_FORMAT_BIN, &timeConfig2);
  20.             RTC_ReadDate(RTC_FORMAT_BIN, &dateConfig);
  21.             RTC_ReadDate(RTC_FORMAT_BIN, &dateConfig2);
  22.             /* 确保两次读取的数据完全一致,避免卡跨时间点位置导致时间错乱 */
  23.             if ((memcmp(&timeConfig, &timeConfig2, sizeof(RTC_TimeConfig_T)) == 0) && \
  24.                 (memcmp(&dateConfig, &dateConfig2, sizeof(RTC_DateConfig_T)) == 0)) {
  25.                 dt->second = timeConfig.seconds;
  26.                 dt->minute = timeConfig.minutes;
  27.                 dt->hour = timeConfig.hours;
  28.                 dt->day = dateConfig.date;
  29.                 dt->month = (dateConfig.month < RTC_MONTH_OCTOBER) ? \
  30.                         dateConfig.month : (dateConfig.month - RTC_MONTH_OCTOBER + 10);
  31.                 dt->year = 2000 + dateConfig.year;
  32.                 dt->week = dateConfig.weekday;
  33.                 break;
  34.             }
  35.         } while (1);
  36.     }
  37. }

同样的,配置日期时间也是需要注意配置进去再读取回来是一致的,否则跨时间点问题会导致配置与预期不一致。
另外,更改RTC相关寄存器,都要先使能PMU模块的备份区域写使能位。
  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_TimeConfig_T timeConfig;
  12.     RTC_TimeConfig_T timeConfig2;
  13.     RTC_DateConfig_T dateConfig;
  14.     RTC_DateConfig_T dateConfig2;
  15.     uint8_t state;
  16.     uint8_t state2;
  17.    
  18.     /* 填充数据 */
  19.     timeConfig.seconds = dt->second;
  20.     timeConfig.minutes = dt->minute;   
  21.     timeConfig.hours = dt->hour;
  22.     dateConfig.date = dt->day;
  23.     dateConfig.month = (RTC_MONTH_T)((dt->month < 10) ? dt->month : (dt->month - 10 + RTC_MONTH_OCTOBER));
  24.     dateConfig.year = dt->year % 100;
  25.     dateConfig.weekday = (RTC_WEEKDAY_T)dt->week;
  26.    
  27.     if (dt != NULL) {   
  28.         do {
  29.             /* 允许RTC寄存器可写 */
  30.             PMU_EnableBackupAccess();
  31.             /* 配置时间日期 */
  32.             state = RTC_ConfigTime(RTC_FORMAT_BIN, &timeConfig);
  33.             state2 = RTC_ConfigDate(RTC_FORMAT_BIN, &dateConfig);
  34.             if ((state != SUCCESS) || (state2 != SUCCESS)) {
  35.                 continue;
  36.             }
  37.             RTC_ReadTime(RTC_FORMAT_BIN, &timeConfig2);
  38.             RTC_ReadDate(RTC_FORMAT_BIN, &dateConfig2);
  39.             /* 确保读取的数据与写入的完全一致 */
  40.             if ((memcmp(&timeConfig, &timeConfig2, sizeof(RTC_TimeConfig_T)) == 0) && \
  41.                 (memcmp(&dateConfig, &dateConfig2, sizeof(RTC_DateConfig_T)) == 0)) {
  42.                 break;
  43.             }
  44.         } while (1);
  45.         /* 禁止RTC寄存器可写 */
  46.         PMU_DisableBackupAccess();
  47.     }
  48. }

RTC的闹钟中断功能与EINT的中断线17绑定,使用时,需同时使能EINT以及初始化中断线17
  1. /*
  2. * @brief       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_TimeConfig_T timeConfig;
  13.     RTC_DateConfig_T dateConfig;
  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.         /* RTC 时钟为LSE */
  31.         RCM_ConfigRTCCLK(RCM_RTCCLK_LSE);
  32.         RCM_EnableRTCCLK();
  33.         
  34.         /* 配置RTC */
  35.         RTC_Reset();
  36.         RTC_ConfigStructInit(&RtcStruct);
  37.         RtcStruct.format = RTC_HOURFORMAT_24;
  38.         /* 时钟先异步分配,再同步分频到RTC使用
  39.          * 1HZ = 32768 / 128 / 256
  40.          */
  41.         RtcStruct.asynchPrediv = 128 - 1;   /* 异步 */
  42.         RtcStruct.synchPrediv = 256 - 1;    /* 同步 */
  43.         RTC_Config(&RtcStruct);
  44.         /* 配置默认时间 */
  45.         RTC_ConfigTimeStructInit(&timeConfig);
  46.         timeConfig.hours = 12;
  47.         timeConfig.minutes = 10;
  48.         timeConfig.seconds = 10;
  49.         timeConfig.h12 = RTC_H12_AM;
  50.         if (RTC_ConfigTime(RTC_FORMAT_BIN, &timeConfig) == SUCCESS) {
  51.             /* 配置默认日期 */
  52.             RTC_ConfigDateStructInit(&dateConfig);
  53.             dateConfig.weekday = RTC_WEEKDAY_TUESDAY;
  54.             dateConfig.date = 23;
  55.             dateConfig.month = RTC_MONTH_SEPTEMBER;
  56.             dateConfig.year = 25;
  57.             RTC_ConfigDate(RTC_FORMAT_BIN, &dateConfig);
  58.         }
  59.         RTC_WriteBackup(RTC_BKP_DATA, BKP_DATA);
  60.     }
  61.    
  62.     /* EINT */
  63.     /* 闹钟为EINT_17 */
  64.     EINT_ConfigStructInit(&eintConfig);
  65.     eintConfig.line    = EINT_LINE_17;
  66.     eintConfig.mode    = EINT_MODE_INTERRUPT;
  67.     eintConfig.trigger = EINT_TRIGGER_RISING;
  68.     eintConfig.lineCmd = ENABLE;
  69.     EINT_Config(&eintConfig);
  70.    
  71.     /* 使能中断 */
  72.     NVIC_EnableIRQRequest(RTC_Alarm_IRQn, 0, 0);
  73.    
  74.     /* 禁止RTC寄存器可写 */
  75.     PMU_DisableBackupAccess();
  76. }

RTC的中断服务函数不止一个,闹钟中断服务函数为RTC_Alarm_IRQHandler
  1. /*
  2. * @brief       中断
  3. *
  4. * @param       None
  5. *
  6. * @retval      None
  7. *
  8. */
  9. void RTC_Alarm_IRQHandler(void)
  10. {
  11.     /* EINT_17 */
  12.     if (EINT_ReadIntFlag(EINT_LINE_17) != RESET) {
  13.         EINT_ClearIntFlag(EINT_LINE_17);
  14.     }
  15.     /* 报警标志 */
  16.     if (RTC_ReadIntFlag(RTC_INT_FLAG_ALRA) != RESET) {
  17.         /* 允许RTC寄存器可写 */
  18.         PMU_EnableBackupAccess();
  19.         RTC_ClearIntFlag(RTC_INT_FLAG_ALRA);
  20.         /* 禁止RTC寄存器可写 */
  21.         PMU_DisableBackupAccess();
  22.         (rtc_alarm_deal_func != NULL) ? rtc_alarm_deal_func() : NULL;
  23.     }
  24. }

RTC闹钟的时间配置和读取只需要执行一次即可,不存在跨时间点的问题。
  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_AlarmConfig_T alarmConfig;
  13.     uint32_t mask = 0;
  14.    
  15.     if (alarm_dt != NULL) {
  16.         /* 允许RTC寄存器可写 */
  17.         PMU_EnableBackupAccess();
  18.         /* 先关闭闹钟才允许更新闹钟时间 */
  19.         if (RTC_DisableAlarmA() == 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(&alarmConfig);
  26.             alarmConfig.time.hours = alarm_dt->hour;
  27.             alarmConfig.time.minutes = alarm_dt->minute;
  28.             alarmConfig.time.seconds = alarm_dt->second;
  29.             alarmConfig.time.h12 = RTC_H12_AM;
  30.             alarmConfig.alarmDateWeekDay = ((alarm_mask->specify_day_or_week != 0) ? alarm_dt->week : alarm_dt->day);
  31.             alarmConfig.alarmDateWeekDaySel = (RTC_WEEKDAY_SEL_T)alarm_mask->specify_day_or_week;
  32.             alarmConfig.alarmMask= mask;
  33.             RTC_ConfigAlarm(RTC_FORMAT_BIN, RTC_ALARM_A, &alarmConfig);
  34.             RTC_ClearIntFlag(RTC_INT_FLAG_ALRA);
  35.             /* 使能报警中断 */
  36.             RTC_EnableInterrupt(RTC_INT_ALRA);
  37.             RTC_EnableAlarmA();
  38.         }
  39.         
  40.         /* 禁止RTC寄存器可写 */
  41.         PMU_DisableBackupAccess();
  42.     }
  43. }

中断处理函数采用注册方式的好处是,能实现底层与应用层的分离,不管应用层的处理函数内部代码如何改动,底层驱动的代码都完全不用调整。
  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. }

RTC的时间戳功能可以用于记录外部事件,其中断功能与EINT的中断线21绑定,使用时,需同时使能EINT以及初始化中断线21
  1. /*
  2. * @brief       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_TimeConfig_T timeConfig;
  13.     RTC_DateConfig_T dateConfig;
  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.         /* RTC 时钟为LSE */
  31.         RCM_ConfigRTCCLK(RCM_RTCCLK_LSE);
  32.         RCM_EnableRTCCLK();
  33.         
  34.         /* 配置RTC */
  35.         RTC_Reset();
  36.         RTC_ConfigStructInit(&RtcStruct);
  37.         RtcStruct.format = RTC_HOURFORMAT_24;
  38.         /* 时钟先异步分配,再同步分频到RTC使用
  39.          * 1HZ = 32768 / 128 / 256
  40.          */
  41.         RtcStruct.asynchPrediv = 128 - 1;   /* 异步 */
  42.         RtcStruct.synchPrediv = 256 - 1;    /* 同步 */
  43.         RTC_Config(&RtcStruct);
  44.         /* 配置默认时间 */
  45.         RTC_ConfigTimeStructInit(&timeConfig);
  46.         timeConfig.hours = 12;
  47.         timeConfig.minutes = 10;
  48.         timeConfig.seconds = 10;
  49.         timeConfig.h12 = RTC_H12_AM;
  50.         if (RTC_ConfigTime(RTC_FORMAT_BIN, &timeConfig) == SUCCESS) {
  51.             /* 配置默认日期 */
  52.             RTC_ConfigDateStructInit(&dateConfig);
  53.             dateConfig.weekday = RTC_WEEKDAY_TUESDAY;
  54.             dateConfig.date = 23;
  55.             dateConfig.month = RTC_MONTH_SEPTEMBER;
  56.             dateConfig.year = 25;
  57.             RTC_ConfigDate(RTC_FORMAT_BIN, &dateConfig);
  58.         }
  59.         RTC_WriteBackup(RTC_BKP_DATA, BKP_DATA);
  60.     }
  61.    
  62.     /* EINT */
  63.     /* 时间戳为EINT_21 */
  64.     EINT_ConfigStructInit(&eintConfig);
  65.     eintConfig.line    = EINT_LINE_21;
  66.     eintConfig.mode    = EINT_MODE_INTERRUPT;
  67.     eintConfig.trigger = EINT_TRIGGER_RISING;
  68.     eintConfig.lineCmd = ENABLE;
  69.     EINT_Config(&eintConfig);
  70.    
  71.     /* 使能中断 */
  72.     NVIC_EnableIRQRequest(TAMP_STAMP_IRQn, 0, 0);
  73.    
  74.     /* 禁止RTC寄存器可写 */
  75.     PMU_DisableBackupAccess();
  76. }

同时,RTC的时间戳中断服务函数为TAMP_STAMP_IRQHandler
  1. /*
  2. * @brief       中断
  3. *
  4. * @param       None
  5. *
  6. * @retval      None
  7. *
  8. */
  9. void TAMP_STAMP_IRQHandler(void)
  10. {
  11.     /* EINT_21 */
  12.     if (EINT_ReadIntFlag(EINT_LINE_21) != RESET) {
  13.         EINT_ClearIntFlag(EINT_LINE_21);
  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. }

而时间戳功能用到PC13引脚作为检测,需要同时配置为复用模式。
  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_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOC);
  15.     GPIO_ConfigStructInit(&gpioConfig);
  16.     gpioConfig.pin     = GPIO_PIN_13;
  17.     gpioConfig.mode    = GPIO_MODE_AF;
  18.     gpioConfig.otype   = GPIO_OTYPE_PP;
  19.     gpioConfig.speed   = GPIO_SPEED_50MHz;
  20.     gpioConfig.pupd    = GPIO_PUPD_NOPULL;
  21.     GPIO_Config(GPIOC, &gpioConfig);
  22.    
  23.     /* 允许RTC寄存器可写 */
  24.     PMU_EnableBackupAccess();
  25.    
  26.     RTC_DisableTimeStamp();
  27.     /* 时间戳上降沿触发 */
  28.     RTC_EnableTimeStamp(RTC_TIMESTAMP_EDGE_RISING);
  29.     /* 使能时间戳中断 */
  30.     RTC_EnableInterrupt(RTC_INT_TS);
  31.    
  32.     /* 禁止RTC寄存器可写 */
  33.     PMU_DisableBackupAccess();
  34. }

4. 测试
测试使用PA5引脚短接PC13进行触发,但PA5拉高时,触发PC13产生RTC时间戳。
  1. // 应用初始化
  2. void app_init(void)
  3. {   
  4.     test_gpio_init();
  5.     bsp_rtc_alarm_deal_func_register(timestamp_get);
  6.     bsp_rtc_init();
  7.     bsp_rtc_timestamp_enable();
  8. }

  9. // 应用任务
  10. void app_task(void)
  11. {   
  12.     /* 日期时间 */
  13.     bsp_rtc_datetime_get(&datetime_get);
  14.     if (flag_datetime_set != 0) {
  15.         flag_datetime_set = 0;
  16.         bsp_rtc_datetime_set(&datetime_set);
  17.     }
  18.     /* 触发时间戳 */
  19.     if (flag_timestamp_set != 0) {
  20.         flag_timestamp_set = 0;
  21.         GPIO_SetBit(GPIOA, GPIO_PIN_5);
  22.     }
  23. }

5. 移植说明
APM32F427RTC实际上有2个闹钟,移植时可参考当前代码扩展为2个闹钟。

6. 详细代码
Alarm.zip (6.71 MB, 下载次数: 0)
Clock.zip (6.54 MB, 下载次数: 0)
Timestamp.zip (6.71 MB, 下载次数: 0)
您需要登录后才可以回帖 登录 | 注册

本版积分规则

34

主题

64

帖子

0

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