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);
/* 在此处执行插补计算(位置、速度规划等) */
/* 例如:插补点计算、轨迹增量输出 */
}
}
运行与验证
- 依赖配置:需在CubeMX中使能TIM6,时钟源设为内部时钟;确认APB1定时器时钟为80MHz(若不同需调整预分频值)。
- 创建任务:在RTOS启动后创建插补任务,栈大小建议≥512字节,优先级设为高于普通任务但低于中断。
- 编译烧录:编译工程并下载至目标板。
验证方法与通过标准
- 逻辑分析仪/示波器:将某个GPIO在插补任务中翻转,测量脉冲间隔。若间隔稳定在1ms±10μs内,说明定时器周期准确。
- 计数验证:在插补任务中累加计数器,用另一低速定时器(如1s)读取计数值,应接近1000(允许±2误差)。
- 中断延迟观察:在中断回调中置位GPIO,测量从中断触发到任务开始执行的时间差,应小于50μs(取决于系统负载)。
若测量结果符合上述范围,则判定定时器配置正确,插补周期中断功能通过验证。