一、关于软件定时器模拟任务运行总结

一、说明:

示意图

总结:

通过回调函数,与任务块在定时器中断里进行循环检测,当到达设定时间,就置为ready,调用回调,执行对应的任务。

这里使用一个例子:

串口输出,

led,iwdg,

显示信息,

来反映这个模型。

c 复制代码
// ==================== 任务调度相关全局变量 ====================
volatile uint32_t system_tick_ms = 0;     // 系统时间计数器(每1ms+1)

// 任务控制块结构体
typedef struct {
    void (*task_func)(void);   // 任务函数指针
    uint32_t period_ms;        // 任务周期(毫秒)
    uint32_t remain_ms;        // 当前倒计时剩余值
    uint8_t ready_flag;        // 就绪标志(1=可执行)
    uint8_t is_running;        // 正在执行标志(防止重入)
    uint32_t exec_count;       // 任务执行次数统计(用于状态显示)
} Task_Control_Block;


// 任务列表(4个任务)
#define TASK_NUM 4
Task_Control_Block task_list[TASK_NUM] = {
    { .task_func = Task_LED_Blink,          .period_ms = 100,  .remain_ms = 100, .ready_flag = 0, .is_running = 0, .exec_count = 0 },
    { .task_func = Task_UART_Communication, .period_ms = 200,  .remain_ms = 200, .ready_flag = 0, .is_running = 0, .exec_count = 0 },
    { .task_func = Task_FeedWatchdog,       .period_ms = 50,   .remain_ms = 50,  .ready_flag = 0, .is_running = 0, .exec_count = 0 },
    { .task_func = Task_StatusDisplay,      .period_ms = 1000, .remain_ms = 1000,.ready_flag = 0, .is_running = 0, .exec_count = 0 }
};



/**
 * @brief 中断服务更新函数(由TIM4中断每1ms调用一次)
 *        仅负责递减计数器、置位就绪标志,绝不执行任务函数
 */
void Timer_Service_Update(void) {
    system_tick_ms++;  // 系统时间累加
    for (uint8_t i = 0; i < TASK_NUM; i++) {
        // 只处理未就绪且未运行的任务(避免干扰正在执行的任务)
        if (!task_list[i].ready_flag && !task_list[i].is_running) {
            if (task_list[i].remain_ms > 0) {
                task_list[i].remain_ms--;
            }
            if (task_list[i].remain_ms == 0) {
                task_list[i].ready_flag = 1;                       // 置位就绪
                task_list[i].remain_ms = task_list[i].period_ms;   // 重载周期
            }
        }
    }
}

/**
 * @brief 主循环调度函数(在while(1)中反复调用)
 *        轮询就绪任务,按数组顺序执行
 */
void Scheduler_Run(void) {
    for (uint8_t i = 0; i < TASK_NUM; i++) {
        if (task_list[i].ready_flag && !task_list[i].is_running) {
            task_list[i].is_running = 1;
            task_list[i].ready_flag = 0;    // 清除就绪标志

            // 执行任务
            task_list[i].task_func();
            task_list[i].exec_count++;      // 统计执行次数

            task_list[i].is_running = 0;
        }
    }
}
main()
{
  while (1)
  { // 启动TIM的1ms中断

    Scheduler_Run();   // 主循环调度
    // 空闲时可执行低优先级后台任务或进入低功耗模式

  }
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM4) {
        Timer_Service_Update();   // 每1ms调用一次更新函数
    }
}

运行结果:

源码:

https://gitee.com/c_y_l_N_H/tmp_pit/tree/master

相关推荐
不悔哥1 天前
开源OV-Watch:怎么做一个智能手表
单片机·开源·嵌入式
XiHongShi20161 天前
STM32F407 RTC定时器例程,建议保存
stm32·单片机·学习
深圳老胡1 天前
STM32F407 控制 L6470 步进电机驱动 —— 控制过程简介
笔记·stm32·单片机·嵌入式硬件·代码规范
女神下凡2 天前
嵌入式设计的各种存储芯片的硬件/软件设计规范,非常全面。
arm开发·单片机·嵌入式硬件
梅梅9662 天前
一款mipi转lvds的lcd调试(LT8912B)
单片机·计算机外设·电脑·显示器·pd芯片
开发笔记-阿牛2 天前
蓝牙音乐灯拆解,又一次拆到蓝牙音乐灯芯片CK6865L
人工智能·单片机·嵌入式硬件·音视频·音频
从零开始的嵌入式之旅2 天前
day47
arm开发·经验分享·笔记·嵌入式硬件
恒锐丰科技林技术员2 天前
EG1164 高压大电流升压同步整流芯片解析
经验分享·嵌入式硬件·硬件工程
CHENKONG_CK2 天前
破解制鞋打磨痛点:RFID赋能去毛刺工序自动化升级
网络·单片机·嵌入式硬件·网络协议·tcp/ip
祖力552 天前
ARM时钟
嵌入式硬件·arm·时钟·imx6ull