结合RTC实现的“智能定时任务系统”:设计与实战

嵌入式系统   作者:嵌入式芯视野 时间:2025-07-17来源:今日头条

在低功耗嵌入式系统中,定时唤醒执行任务是一个常见需求,比如定时上传数据、定时采集传感器信息、定时进入/退出低功耗模式等。STM32系列MCU内置RTC模块,不仅可提供实时时钟,还支持低功耗唤醒和带日期的定时调度。

本文将基于STM32平台,介绍如何构建一个支持用户可配置任务 + RTC定时唤醒 + 灵活唤醒处理的“智能定时任务系统”。并通过完整的实例代码进行剖析,具有较强实用性。


一、核心需求分析


二、系统结构设计

[ 配置接口 ]
    ↑[任务存储区] ←→ [RTC管理模块] ←→ [任务调度器] ←→ [用户任务处理]
                           ↑                   [低功耗控制模块]

三、RTC唤醒基础配置

使用STM32的RTC + Alarm A功能,作为唤醒触发源。

void RTC_AlarmAConfig(uint8_t hour, uint8_t min, uint8_t sec){
   RTC_AlarmTypeDef sAlarm = {0};

   sAlarm.AlarmTime.Hours   = hour;
   sAlarm.AlarmTime.Minutes = min;
   sAlarm.AlarmTime.Seconds = sec;
   sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY; // 只匹配时分秒
   sAlarm.Alarm = RTC_ALARM_A;

   HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN);
}

唤醒中断回调:

void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc){
   rtc_wakeup_flag = 1;
}

四、定时任务结构设计

定义任务数据结构,支持 Flash 存储和用户配置:

#define MAX_TASK_NUM 10typedef struct {
   uint8_t enable;    uint8_t hour;    uint8_t minute;    uint8_t repeat_day;   // 0x7F:每天,bit0=周日, bit1=周一...
   uint8_t task_id;      // 执行的任务编号} rtc_task_t;rtc_task_t g_task_list[MAX_TASK_NUM];

五、用户任务执行处理

根据任务 ID 执行实际操作:

void execute_user_task(uint8_t task_id){    switch (task_id) {        case 0: toggle_led(); break;        case 1: collect_sensor(); break;        case 2: send_data(); break;        default: break;
   }
}

六、RTC时间匹配调度器

每次系统被唤醒时,匹配当前 RTC 时间是否对应一个任务:

void check_and_run_rtc_tasks(void){
   RTC_TimeTypeDef time;
   RTC_DateTypeDef date;
   HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);
   HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN);

   uint8_t weekday_mask = 1 << date.WeekDay;

   for (int i = 0; i < MAX_TASK_NUM; i++) {
       if (!g_task_list[i].enable) continue;
       if (g_task_list[i].hour == time.Hours &&
           g_task_list[i].minute == time.Minutes) {
           if (g_task_list[i].repeat_day & weekday_mask) {
               execute_user_task(g_task_list[i].task_id);
           }
       }
   }}

七、低功耗进入与唤醒流程

1. 设置最近的下次任务时间

每次执行完任务后,根据任务表,找出最近的下一个任务时间点,并设置为 Alarm A:

void update_next_rtc_alarm(void){    // 简单示例:找出第一个启用任务作为下次 Alarm
   for (int i = 0; i < MAX_TASK_NUM; i++) {        if (g_task_list[i].enable) {
           RTC_AlarmAConfig(g_task_list[i].hour, g_task_list[i].minute, 0);            break;
       }
   }
}

可进一步排序任务时间并计算最接近当前时间的任务,提高效率。

2. 进入低功耗模式

void enter_stop_mode(void)
{    HAL_SuspendTick();    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);    HAL_ResumeTick();
}

唤醒后恢复系统时钟和功能:

void system_resume_from_stop(void){
   SystemClock_Config(); // 重新配置系统时钟}

八、任务配置接口(可选)

通过串口或屏幕提供简单配置接口:

// 示例:串口接收命令配置任务// 命令格式:TASK 1 08 30 7F 0// 含义:任务1,8:30,每天执行,执行任务编号0void parse_task_command(const char* cmd){    uint8_t idx, h, m, days, id;    if (sscanf(cmd, "TASK %hhu %hhu %hhu %hhx %hhu", &idx, &h, &m, &days, &id) == 5) {
       g_task_list[idx].enable = 1;
       g_task_list[idx].hour = h;
       g_task_list[idx].minute = m;
       g_task_list[idx].repeat_day = days;
       g_task_list[idx].task_id = id;        // 保存到Flash
       save_task_to_flash(g_task_list, sizeof(g_task_list));
   }
}

九、整体工作流程图

上电 → 加载任务 → 设置最近Alarm A → 进入STOP模式
       ↑                             ↓
   Flash配置 ← 用户设置 ← 串口/屏幕   ← RTC唤醒 → 执行匹配任务 → 更新Alarm → 进入STOP

十、工程建议与总结

  1. 任务存储:使用内部 Flash 或外部 EEPROM 保存任务表;

  2. 时间边界判断:可引入“分钟偏移判断”,避免误判;

  3. 唤醒延迟容忍:可通过软件 Timer 判断是否错过唤醒时间;

  4. 任务重复机制:可扩展支持一次性/周期任务等多类型。


结语

结合STM32的RTC功能,我们可以构建一个低功耗、高灵活性、可配置的定时任务系统,非常适用于IoT节点、远程采集设备、智能家电等场景。通过本文的接口定义、调度策略与实例演示,你可以轻松实现自己的RTC任务系统,并为后期扩展(如OTA配置、LCD显示)打下基础。

关键词: STM32 RTC定时唤醒

加入微信
获取电子行业最新资讯
搜索微信公众号:EEPW

或用微信扫描左侧二维码

相关文章

查看电脑版