TIM中断的七十二变:STM32定时器的五种创意用法
在嵌入式开发领域,定时器(TIM)堪称最灵活的外设之一。对于STM32F103C8T6这类主流MCU而言,定时器不仅能完成基础的计时功能,更能通过巧妙配置实现各种意想不到的应用场景。本文将带你探索五种突破常规的TIM用法,从PWM呼吸灯到低功耗唤醒系统,每个案例都配有CubeMX配置技巧和中断服务函数优化建议。
1. 动态PWM呼吸灯:让灯光"活"起来
呼吸灯效果是展示PWM调光最直观的方式。传统实现往往依赖delay函数,但使用TIM中断可以构建更优雅的解决方案。
CubeMX关键配置步骤:
- 启用TIM2时钟
- 配置通道1为PWM模式
- 设置预分频器(PSC)为71(72MHz/72=1MHz)
- 自动重载值(ARR)设为1000(1MHz/1000=1kHz PWM频率)
// 呼吸灯核心逻辑(中断服务函数) void TIM2_IRQHandler(void) { static uint16_t pwmVal = 0; static int8_t dir = 1; if(TIM_GetITStatus(TIM2, TIM_IT_Update)) { pwmVal += dir; if(pwmVal >= 1000) dir = -1; else if(pwmVal <= 0) dir = 1; TIM_SetCompare1(TIM2, pwmVal); TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } }性能优化技巧:
- 使用DMA自动更新CCR值可减少CPU干预
- 调整ARR和PSC组合可获得不同平滑度的呼吸效果
- 结合多个定时器可实现多通道同步呼吸
2. 超声波测距系统:精准测量无需专用芯片
利用TIM的输入捕获功能,我们可以用普通GPIO实现超声波测距。HC-SR04模块的Trig引脚由普通GPIO控制,Echo引脚连接到TIM的输入捕获通道。
硬件连接方案:
| 模块引脚 | STM32连接 | 备注 |
|---|---|---|
| VCC | 5V | 供电 |
| Trig | PA1 | 普通GPIO输出 |
| Echo | PA6 | TIM3_CH1输入捕获 |
| GND | GND | 共地 |
测距实现代码框架:
// 超声波测距核心逻辑 void TIM3_IRQHandler(void) { static uint32_t capture1 = 0, capture2 = 0; static float distance = 0; if(TIM_GetITStatus(TIM3, TIM_IT_CC1)) { if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6)) { // 上升沿 capture1 = TIM_GetCapture1(TIM3); } else { // 下降沿 capture2 = TIM_GetCapture1(TIM3); distance = (capture2 - capture1) * 34000 / 2 / 72; // 单位:cm } TIM_ClearITPendingBit(TIM3, TIM_IT_CC1); } }精度提升要点:
- 使用72MHz系统时钟时,理论分辨率可达0.47mm
- 通过多次测量取平均值提高稳定性
- 在温度变化大的环境中需考虑声速补偿
3. 机械按键消抖:硬件级解决方案
传统软件消抖需要循环检测,占用CPU资源。利用TIM的从模式特性,可以实现硬件级消抖。
CubeMX配置秘籍:
- 配置TIM4为从模式,触发源选择TI1FP1
- 设置滤波器为8个时钟周期(约111ns)
- 分频器设为7199(72MHz/7200=10kHz)
- 使能更新中断
// 按键消抖中断处理 void TIM4_IRQHandler(void) { if(TIM_GetITStatus(TIM4, TIM_IT_Update)) { uint8_t key_state = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0); // 处理按键逻辑... TIM_ClearITPendingBit(TIM4, TIM_IT_Update); } }对比传统消抖方案:
| 消抖方式 | CPU占用 | 响应速度 | 实现复杂度 |
|---|---|---|---|
| 软件延时 | 高 | 慢 | 低 |
| 状态机 | 中 | 中 | 中 |
| TIM硬件消抖 | 低 | 快 | 高 |
4. 简易数字示波器:捕捉瞬态信号
虽然STM32F103没有内置ADC DMA,但通过TIM触发ADC采样,配合输入捕获功能,可以构建简易单通道示波器。
系统架构设计:
- TIM2配置为PWM模式,产生固定频率的采样时钟
- ADC配置为外部触发模式,由TIM2触发
- TIM3配置为输入捕获模式,测量信号周期
- 使用片内SRAM作为采样缓冲区
关键代码片段:
// ADC采样缓冲区 #define BUF_SIZE 256 uint16_t adc_buf[BUF_SIZE]; uint8_t buf_pos = 0; // TIM2中断处理采样触发 void TIM2_IRQHandler(void) { if(TIM_GetITStatus(TIM2, TIM_IT_Update)) { ADC_SoftwareStartConvCmd(ADC1, ENABLE); TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } } // ADC中断存储数据 void ADC1_2_IRQHandler(void) { if(ADC_GetITStatus(ADC1, ADC_IT_EOC)) { adc_buf[buf_pos++] = ADC_GetConversionValue(ADC1); if(buf_pos >= BUF_SIZE) buf_pos = 0; ADC_ClearITPendingBit(ADC1, ADC_IT_EOC); } }性能参数估算:
| 参数 | 数值 |
|---|---|
| 最高采样率 | 1MHz(理论值) |
| 分辨率 | 12位 |
| 存储深度 | 256点(可扩展) |
| 测量频率范围 | 0-50kHz |
5. 低功耗系统唤醒:精准休眠控制
在电池供电设备中,合理使用TIM定时唤醒可以大幅降低系统功耗。STM32的TIM在停止模式下仍可由内部低速时钟(LSI)驱动。
低功耗配置流程:
- 选择TIM4作为唤醒定时器(基本定时器耗电更低)
- 时钟源选择LSI(约40kHz)
- 配置预分频器和ARR值计算唤醒间隔
- 使能更新中断和唤醒中断
// 低功耗模式设置 void enter_stop_mode(uint32_t sleep_seconds) { uint16_t arr_value = sleep_seconds * (LSI_FREQ / (PSC_VALUE + 1)); TIM_SetAutoreload(TIM4, arr_value); TIM_Cmd(TIM4, ENABLE); PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); // 唤醒后系统时钟需要重新配置 SystemInit(); } // TIM4唤醒中断 void TIM4_IRQHandler(void) { if(TIM_GetITStatus(TIM4, TIM_IT_Update)) { TIM_ClearITPendingBit(TIM4, TIM_IT_Update); // 唤醒后的处理逻辑 } }功耗对比数据:
| 工作模式 | 典型电流消耗 |
|---|---|
| 正常运行模式 | 12mA |
| 睡眠模式 | 5mA |
| 停止模式+TIM唤醒 | 20μA |
| 待机模式 | 2μA |
这些创意应用展示了STM32定时器的强大灵活性。通过深入理解TIM模块的各种工作模式,开发者可以突破常规思维,设计出既高效又新颖的硬件解决方案。