You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于STM32的C语言时间调度器设计求助(定时器/状态机)

基于定时器+状态机实现时间调度器的解决方案

核心思路

利用你已完成的TIM2 1us计时基础(初始化代码将定时器分频为1MHz,每个tick对应1us),通过状态机跟踪当前调度阶段,配合动态修改定时器周期,实现4ms周期内的任务调度逻辑:

  1. 每4ms触发主请求
  2. 主请求后等待1ms周转延迟
  3. 在剩余3ms内,每500µs触发1次副请求,共6次
  4. 完成后回到主周期等待,循环执行

1. 定义状态机与全局跟踪变量

添加状态枚举和全局变量,用于记录当前调度阶段、副请求发送次数:

// 状态机枚举
typedef enum {
    STATE_MAIN_WAIT,          // 等待4ms主周期触发
    STATE_MAIN_DELAY,         // 主请求后等待1ms延迟
    STATE_SUB_REQUEST         // 发送副请求阶段
} SchedulerState;

SchedulerState current_state = STATE_MAIN_WAIT;
uint8_t sub_request_count = 0;  // 副请求计数器,最多6次

2. 修改定时器中断处理逻辑

重写TIM2_IRQHandler函数,根据当前状态执行任务并切换状态,动态调整定时器周期:

void TIM2_IRQHandler(void)
{
    // 清除更新中断标志
    __HAL_TIM_CLEAR_IT(&htim2, TIM_IT_UPDATE);

    switch(current_state)
    {
        case STATE_MAIN_WAIT:
            // 执行主请求任务
            execute_main_request();
            
            // 切换到1ms延迟状态,修改定时器周期为1000us
            current_state = STATE_MAIN_DELAY;
            changeTIM2Timeout(1000);
            break;

        case STATE_MAIN_DELAY:
            // 延迟结束,切换到副请求发送状态,设置周期为500us
            current_state = STATE_SUB_REQUEST;
            sub_request_count = 0;
            changeTIM2Timeout(500);
            break;

        case STATE_SUB_REQUEST:
            // 执行副请求任务
            execute_sub_request(sub_request_count);
            
            sub_request_count++;
            if(sub_request_count >= 6)
            {
                // 6次副请求完成,回到主周期等待,设置周期为4000us
                current_state = STATE_MAIN_WAIT;
                changeTIM2Timeout(4000);
            }
            // 否则保持500us周期,继续下一次副请求
            break;

        default:
            // 异常状态,重置为主等待
            current_state = STATE_MAIN_WAIT;
            changeTIM2Timeout(4000);
            break;
    }
}

3. 补充任务执行函数

根据实际需求实现主、副请求的具体逻辑:

void execute_main_request(void)
{
    // 此处编写主请求的具体代码,比如发送指令、触发硬件动作等
}

void execute_sub_request(uint8_t req_index)
{
    // 此处编写副请求的具体代码,req_index可区分第几次副请求(0-5)
}

4. 初始化与启动

调用初始化函数时,直接传入主周期的4000us(4ms):

// 启动调度器
TIM2_Init(4000);

关键说明

  • 定时器周期修改:changeTIM2Timeout直接操作ARR寄存器,因你已关闭AutoReloadPreload,修改后立即生效
  • 状态流转:每个状态对应一个定时器周期,中断触发时完成任务并切换状态/周期,确保严格的时间间隔
  • 副请求计数:通过sub_request_count跟踪发送次数,达到6次后自动回到主周期

内容的提问来源于stack exchange,提问作者PierreP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 19:21:08