用STM32F1的定时器玩点花的:PWM呼吸灯、编码器测速、输入捕获测频率占空比一站式搞定
STM32F1定时器高级应用实战PWM呼吸灯、编码器测速与信号捕获全解析1. 定时器功能深度挖掘在嵌入式开发领域STM32系列微控制器因其丰富的外设资源而备受青睐。其中定时器TIM模块堪称最灵活多变的外设之一远超简单的定时功能范畴。STM32F1系列芯片搭载了从基本定时器到高级定时器的完整谱系本文将聚焦通用定时器的高级应用场景。定时器的三大核心能力时基生成基础计时功能支持从纳秒到分钟级定时输入捕获精确测量外部信号的时间参数输出比较生成复杂波形与精准时序控制不同于基础教程中对定时器功能的泛泛而谈我们将通过三个典型工程案例展示如何充分发挥定时器潜力动态PWM呼吸灯效果实现旋转编码器精准测速方案外部信号频率与占空比测量系统提示本文所有代码示例基于标准外设库开发可直接移植到HAL库环境。实验平台为STM32F103C8T6最小系统板时钟配置为72MHz。2. PWM呼吸灯实现2.1 PWM原理与硬件连接脉宽调制PWM通过调节占空比来控制平均电压是LED调光的理想方案。下图展示PWM波形与亮度关系占空比LED亮度表现0%完全熄灭30%低亮度70%高亮度100%最大亮度硬件连接方案/* * LED正极 - 限流电阻 - PA6(TIM3_CH1) * LED负极 - GND */ GPIO_InitStructure.GPIO_Pin GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; // 复用推挽输出 GPIO_Init(GPIOA, GPIO_InitStructure);2.2 定时器PWM模式配置配置TIM3通道1为PWM模式1的关键步骤// 时基单元配置 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Period 999; // ARR值 TIM_TimeBaseStructure.TIM_Prescaler 71; // 72分频(1MHz) TIM_TimeBaseStructure.TIM_ClockDivision 0; TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, TIM_TimeBaseStructure); // PWM通道配置 TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse 500; // 初始占空比50% TIM_OCInitStructure.TIM_OCPolarity TIM_OCPolarity_High; TIM_OC1Init(TIM3, TIM_OCInitStructure); TIM_Cmd(TIM3, ENABLE);2.3 动态亮度调节算法实现呼吸效果需要动态调整CCR值可采用以下两种方式方案对比表方案优点缺点线性变化实现简单视觉效果不够平滑正弦波变化渐变自然计算量稍大指数曲线符合人眼感知特性需要浮点运算推荐使用查表法实现正弦变化const uint16_t breathTable[100] { // 预计算好的正弦波样本值 500500*sin(2*3.1416*i/100) // i从0到99 }; void TIM3_IRQHandler(void) { static uint8_t index 0; if(TIM_GetITStatus(TIM3, TIM_IT_Update)) { TIM_SetCompare1(TIM3, breathTable[index]); index (index 1) % 100; TIM_ClearITPendingBit(TIM3, TIM_IT_Update); } }3. 编码器接口测速3.1 正交编码器工作原理工业级编码器通常输出A、B两相正交信号其相位关系决定旋转方向正转时 A相上升沿 - B相低电平 B相上升沿 - A相高电平 反转时 B相上升沿 - A相低电平 A相上升沿 - B相高电平3.2 定时器编码器模式配置STM32定时器内置编码器接口可自动识别方向并计数// 编码器接口配置 TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, // 双通道计数模式 TIM_ICPolarity_Rising, // 上升沿触发 TIM_ICPolarity_Rising); // 时基单元特殊配置 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Period 65535; // 最大计数值 TIM_TimeBaseStructure.TIM_Prescaler 0; TIM_TimeBaseStructure.TIM_ClockDivision 0; TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, TIM_TimeBaseStructure); TIM_Cmd(TIM2, ENABLE);3.3 速度计算与滤波处理测速算法需要考虑采样周期和机械抖动int16_t GetSpeedRPM(void) { static int32_t lastCount 0; int32_t currentCount TIM_GetCounter(TIM2); int32_t delta currentCount - lastCount; // 处理计数器溢出 if(delta 32768) delta - 65536; else if(delta -32768) delta 65536; lastCount currentCount; // 转换为RPM (假设编码器500线采样周期100ms) return (delta * 10 * 60) / (500 * 4); }注意实际工程中应添加滑动平均滤波抑制机械振动带来的噪声。4. 输入捕获测频技术4.1 输入捕获原理定时器输入捕获可以精确测量信号频率周期时间脉冲宽度占空比测量方法对比方法适用场景精度影响因素测频法高频信号(1kHz)闸门时间精度测周法低频信号(1kHz)参考时钟频率4.2 PWMI模式配置使用TIM4通道1和通道2实现同时测量频率和占空比// 输入捕获单元配置 TIM_ICInitTypeDef TIM_ICInitStructure; TIM_ICInitStructure.TIM_Channel TIM_Channel_1; TIM_ICInitStructure.TIM_ICPolarity TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICSelection TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter 0x0F; // 最大滤波 TIM_ICInit(TIM4, TIM_ICInitStructure); // 配置从模式自动复位 TIM_SelectInputTrigger(TIM4, TIM_TS_TI1FP1); TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset); // 启用捕获中断 TIM_ITConfig(TIM4, TIM_IT_CC1 | TIM_IT_CC2, ENABLE);4.3 频率与占空比计算在中断服务程序中完成测量计算void TIM4_IRQHandler(void) { static uint32_t lastPeriod 0; if(TIM_GetITStatus(TIM4, TIM_IT_CC1)) { uint32_t period TIM_GetCapture1(TIM4); float frequency 72000000.0f / period; // 72MHz时钟 lastPeriod period; TIM_ClearITPendingBit(TIM4, TIM_IT_CC1); } if(TIM_GetITStatus(TIM4, TIM_IT_CC2)) { uint32_t pulseWidth TIM_GetCapture2(TIM4); float dutyCycle (pulseWidth * 100.0f) / lastPeriod; TIM_ClearITPendingBit(TIM4, TIM_IT_CC2); } }5. 工程优化技巧5.1 定时器级联技术当需要超长定时或更高精度时可采用主从定时器级联TIM2(主) - TRGO - TIM3(从)配置代码示例// 主定时器配置输出触发 TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); // 从定时器配置ITRx输入 TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1); // ITR1对应TIM2 TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated);5.2 DMA联动方案对于高频PWM或连续采集场景使用DMA减轻CPU负担// PWM波形DMA传输配置 DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)TIM3-CCR1; DMA_InitStructure.DMA_MemoryBaseAddr (uint32_t)pwmBuffer; DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize BUFFER_SIZE; DMA_Init(DMA1_Channel6, DMA_InitStructure); TIM_DMACmd(TIM3, TIM_DMA_CC1, ENABLE);5.3 低功耗设计合理配置定时器在低功耗模式下的行为// 配置定时器在睡眠模式下保持运行 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); PWR_ClockCmd(ENABLE); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); TIM_Cmd(TIM2, ENABLE);在调试PWM输出异常时发现输出波形不稳定。经过逻辑分析仪捕获发现是GPIO速度配置不足导致。将GPIO_Speed从10MHz提升到50MHz后波形边沿变得陡峭系统稳定性显著提高。这个案例提醒我们外设性能配置需要匹配实际应用场景。