4. 插补周期定时器配置

任务说明

在运动控制系统中,插补周期决定了轨迹规划的实时性与平滑度。本案例目标是在RTOS环境下配置一个硬件定时器,使其以固定周期(如1ms)产生中断,用于驱动插补任务周期性执行。要求中断周期精确、抖动小,且与RTOS任务调度协同工作。

实现方案

采用硬件定时器+中断信号量的方式:定时器溢出中断中仅做“给信号量”操作,将耗时处理放在RTOS任务中,避免在中断上下文执行复杂逻辑。以STM32 HAL库 + CMSIS-RTOS2接口为例,定时器时钟源为APB1(80MHz),需配置预分频与自动重载值以得到1ms周期。

关键完整代码

/* 硬件定时器初始化(TIM6基本定时器,挂载APB1) */
#include "cmsis_os2.h"
#include "stm32h7xx_hal.h"

static osSemaphoreId_t插补Sem;
static TIM_HandleTypeDef htim6;

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim == &htim6) {
        osSemaphoreRelease(插补Sem);   /* 仅释放信号量,快速退出中断 */
    }
}

void 插补定时器_Init(void)
{
    /* 创建二值信号量,初始为0 */
    插补Sem = osSemaphoreNew(1, 0, NULL);

    /* 使能TIM6时钟 */
    __HAL_RCC_TIM6_CLK_ENABLE();

    htim6.Instance = TIM6;
    htim6.Init.Prescaler = 80 - 1;        /* 80MHz/80 = 1MHz */
    htim6.Init.Period = 1000 - 1;         /* 1MHz/1000 = 1kHz → 1ms周期 */
    htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    HAL_TIM_Base_Init(&htim6);

    /* 使能更新中断 */
    HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);
    HAL_TIM_Base_Start_IT(&htim6);
}

/* 中断服务函数(在启动文件中已声明) */
void TIM6_DAC_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&htim6);
}

/* 插补任务:等待信号量后执行插补运算 */
void 插补任务(void *argument)
{
    while (1) {
        osSemaphoreAcquire(插补Sem, osWaitForever);
        /* 在此处执行插补计算(位置、速度规划等) */
        /* 例如:插补点计算、轨迹增量输出 */
    }
}

运行与验证

  1. 依赖配置:需在CubeMX中使能TIM6,时钟源设为内部时钟;确认APB1定时器时钟为80MHz(若不同需调整预分频值)。
  2. 创建任务:在RTOS启动后创建插补任务,栈大小建议≥512字节,优先级设为高于普通任务但低于中断。
  3. 编译烧录:编译工程并下载至目标板。

验证方法与通过标准

  • 逻辑分析仪/示波器:将某个GPIO在插补任务中翻转,测量脉冲间隔。若间隔稳定在1ms±10μs内,说明定时器周期准确。
  • 计数验证:在插补任务中累加计数器,用另一低速定时器(如1s)读取计数值,应接近1000(允许±2误差)。
  • 中断延迟观察:在中断回调中置位GPIO,测量从中断触发到任务开始执行的时间差,应小于50μs(取决于系统负载)。

若测量结果符合上述范围,则判定定时器配置正确,插补周期中断功能通过验证。