STM32 定时器(级联实现32位定时器)
在STM32F103微控制器中,通过主从定时器模式将两个16位定时器级联为32位定时器,可显著扩展定时范围(最长可达数天)。以下是实现原理、配置步骤及代码示例:
⚙️ 一、实现原理
级联核心机制
- 主定时器(如TIM2):配置为周期性更新事件(如1ms),通过内部触发线(ITRx)输出触发信号。
- 从定时器(如TIM3):工作于外部时钟模式(
TIM_SlaveMode_External1
),将主定时器的触发信号作为计数时钟源。 - 协同计数:主定时器每溢出一次,从定时器计数值加1,实现
主定时器周期 × 从定时器ARR值
的扩展定时。
32位扩展计算
- 主定时器周期:Tmaster=(PSCmaster+1)×(ARRmaster+1) / fclock
- 总定时周期:Ttotal=Tmaster×(ARRslave+1)
- 最大定时范围:若 ARRslave=65535(16位),则总定时范围扩展至32位(约49.7天 @72MHz)。
🔧 二、配置步骤与代码(标准库实现)
1. 硬件连接与时钟设置
- 内部触发线选择:
主定时器 从定时器 内部触发线(ITRx) TIM2 TIM3 ITR1 TIM3 TIM4 ITR2 - 使能时钟:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE);
2. 主定时器配置(TIM2)
void TIM2_Master_Config(uint32_t prescaler, uint32_t period)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;// 时基单元:1ms周期示例(72MHz时钟)TIM_TimeBaseStruct.TIM_Prescaler = prescaler; // 预分频值(72-1 → 1MHz)TIM_TimeBaseStruct.TIM_Period = period; // 重装载值(1000-1 → 1ms)TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStruct);// 触发输出:更新事件作为触发源TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);TIM_Cmd(TIM2, ENABLE);
}
3. 从定时器配置(TIM3)
void TIM3_Slave_Config(uint32_t slave_period)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;// 时基单元:计数主定时器的溢出次数TIM_TimeBaseStruct.TIM_Period = slave_period; // 从定时器ARR(扩展定时范围)TIM_TimeBaseStruct.TIM_Prescaler = 0; // 无分频TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStruct);// 从模式:外部时钟模式 + ITR1触发TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1); // TIM2触发TIM3TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_External1); // 外部信号驱动计数TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); // 使能更新中断TIM_Cmd(TIM3, ENABLE);
}
4. 中断配置(处理定时完成事件)
void NVIC_Config(void){NVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn; // TIM3中断通道NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStruct);
}// TIM3中断服务函数
void TIM3_IRQHandler(void)
{if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) {TIM_ClearITPendingBit(TIM3, TIM_IT_Update);// 此处执行定时完成后的任务(如翻转LED、触发操作)}
}
5. 主函数调用
int main(void)
{// 配置60秒定时:主定时器1ms周期,从定时器计数60,000次(60s/1ms)TIM2_Master_Config(72-1, 1000-1); // 1ms周期TIM3_Slave_Config(60000-1); // 60秒总定时NVIC_Config();while(1);
}
⚠️ 三、关键注意事项
触发模式匹配
- 主定时器需选择
TIM_TRGOSource_Update
(更新事件触发)。 - 从定时器必须选
TIM_SlaveMode_External1
(外部时钟模式)。
- 主定时器需选择
中断优化
- 仅需处理从定时器的更新中断,避免主定时器中断占用资源。
- 若需超高精度,禁用全局中断期间操作计数器。
预分频与周期计算
- 主定时器周期不宜过短(避免高频触发导致从定时器计数溢出)。
- 最大扩展周期公式:Tmax=72MHz(65535+1)×(65535+1)≈59.65小时
💡 四、应用场景
- 长周期任务:数据日志定时存储、设备状态巡检(小时/天级)。
- 步进电机控制:精确输出指定数量的PWM脉冲(如
实现3个脉冲输出)。 - 低功耗定时唤醒:休眠模式下由级联定时器唤醒系统。
通过此方案,可将STM32F103的定时能力扩展至32位,兼顾精度与灵活性。实际代码需根据时钟频率调整预分频和ARR值。