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

一、说明:

示意图

总结:

通过回调函数,与任务块在定时器中断里进行循环检测,当到达设定时间,就置为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

相关推荐
硅基手札7 分钟前
【Linux 内核专栏 19】20 · 嵌入式子系统 — GPIO·pinctrl·clock·regulator
linux·运维·单片机·linux内核·嵌入式开发·调试定位
何粥学2 小时前
Vivado 2024.2 开发记录(AC820 Zynq-7020)——软件使用,点亮led灯
单片机·嵌入式硬件·zynq
Sakura_j_h_3 小时前
51 单片机驱动四位数码管:动态扫描、限流电阻与消影的取舍
单片机·嵌入式硬件·51单片机·嵌入式·数码管·动态扫描·限流电阻
HANDY092004 小时前
从“不照人”到“剂量达标”:扇叶遮挡式UV-C空气消毒的工程边界与可验证评估框架
开发语言·人工智能·嵌入式硬件·智能家居
飞凌嵌入式6 小时前
千次静电放电试炼,守住飞凌嵌入式硬件可靠底线
嵌入式硬件
蹊黎15 小时前
Linux 下用 C 语言实现进度条
linux·c语言·单片机
无敌贵点大王19 小时前
从寄存器层面重学STM32(6)——串口USART实战部分
stm32·单片机·嵌入式硬件
庙堂龙吟奈我何19 小时前
二进制和十六进制
stm32·单片机
国科安芯21 小时前
长期在轨的计算底座:商业空间站与在轨服务飞行器健康管理中的抗辐射MCU—— 面向可维护空间平台的分层容错与安全通信综述
人工智能·单片机·嵌入式硬件·安全·低轨卫星·抗辐射
不昀1 天前
RMII切到10Mbps,50MHz参考时钟也要降到5MHz吗?
单片机·嵌入式硬件·硬件设计·以太网接口