1. 定时器基础概念回顾
在嵌入式开发领域,定时器(Timer)是最基础也最核心的外设模块之一。简单来说,定时器就是一个能够精确计时的数字电路,它通过计数时钟脉冲来实现时间测量和控制功能。现代微控制器通常都集成多个定时器单元,每个定时器包含独立的计数寄存器、预分频器和自动重装载寄存器等组件。
以STM32系列MCU为例,其定时器主要分为三类:基本定时器(TIM6/TIM7)、通用定时器(TIM2-TIM5)和高级定时器(TIM1/TIM8)。不同级别的定时器功能复杂度不同,但核心工作原理相似——都是通过时钟源驱动计数器进行递增或递减计数。
提示:初学者常混淆定时器与延时函数的概念。硬件定时器是独立运行的物理外设,不占用CPU资源;而软件延时是通过CPU空循环实现的,会阻塞程序执行。
2. PWM模式详解与应用
2.1 PWM工作原理
脉宽调制(Pulse Width Modulation,PWM)是定时器最典型的应用之一。其核心是通过调节输出信号的占空比(高电平时间与周期的比值)来模拟不同电压等级。例如在LED调光应用中,虽然PWM输出的实际电压只有0V或3.3V两种状态,但通过快速切换和占空比调节,人眼会感知到亮度变化。
PWM的硬件实现依赖于定时器的比较功能。以STM32的通用定时器为例,配置步骤通常包括:
- 设置定时器时钟源和预分频值(决定计数频率)
- 配置自动重装载值ARR(决定PWM周期)
- 设置比较寄存器CCRx(决定占空比)
- 选择PWM模式(通常为PWM模式1或2)
- 使能通道输出
c复制// STM32标准库PWM配置示例
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
// 时基单元配置
TIM_TimeBaseStructure.TIM_Period = 999; // ARR值
TIM_TimeBaseStructure.TIM_Prescaler = 71; // 预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// PWM通道配置
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 500; // CCRx值,占空比50%
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_Cmd(TIM3, ENABLE);
2.2 关键参数计算
PWM应用中需要特别注意三个核心参数的计算关系:
- PWM频率 = 定时器时钟源 / ((ARR + 1) * (PSC + 1))
- 例如:72MHz时钟,PSC=71,ARR=999 → 频率=72MHz/(1000*72)=1kHz
- 占空比 = (CCRx + 1) / (ARR + 1) * 100%
- 上例中CCRx=499时占空比为50%
- 分辨率 = log₂(ARR + 1)
- ARR=999时分辨率约为10位(2¹⁰=1024)
注意事项:PWM频率选择需权衡响应速度与系统开销。电机控制通常需要10kHz以上频率以避免可闻噪声,而LED调光使用100Hz-1kHz即可。频率过高会导致CPU负载增加,过低则可能引起闪烁。
2.3 高级PWM应用技巧
在实际项目中,PWM的应用远不止简单的信号生成。以下是几种进阶用法:
-
互补输出与死区控制:在电机驱动等H桥电路中,需要配置互补的PWM通道并插入死区时间(Dead Time),防止上下管直通短路。高级定时器(如TIM1)硬件支持死区插入功能。
-
PWM输入模式:通过配置两个通道(通常IC1和IC2),可以测量外部PWM信号的频率和占空比。一个通道捕获上升沿,另一个捕获下降沿。
-
DMA控制PWM:对于需要频繁更新占空比的场景(如LED呼吸灯),可以使用DMA自动传输CCRx值,减轻CPU负担。
-
多通道同步:使用主从定时器模式,可以实现多个PWM输出的严格同步,这在多相电机控制中尤为重要。
3. 输入捕获模式深度解析
3.1 输入捕获基本原理
输入捕获(Input Capture)是定时器另一项重要功能,主要用于精确测量外部信号的脉宽或频率。其工作原理是:当检测到指定边沿(上升沿或下降沿)时,定时器会立即将当前计数值锁存到捕获寄存器中,并可选地产生中断。
典型应用场景包括:
- 旋转编码器脉冲计数
- 红外遥控信号解码
- 超声波测距回波检测
- 数字信号频率测量
输入捕获的硬件实现涉及定时器的输入通道、捕获/比较寄存器和边沿检测电路。以测量高电平脉宽为例,通常需要配置:
- 通道1捕获上升沿
- 通道2捕获下降沿
- 两次捕获值的差即为脉宽
3.2 捕获模式配置要点
在STM32中配置输入捕获需要注意以下关键点:
-
时基配置:根据待测信号频率范围选择合适的预分频值。频率越高,需要的定时器分辨率越低。
-
输入滤波:通过配置CCMRx寄存器中的ICxF位可以设置数字滤波器,消除信号抖动。滤波采样频率一般为定时器频率的1/2/4/8分频。
-
极性选择:在TIM_ICInitStructure中指定捕获边沿(上升沿、下降沿或双边沿)。
-
直接/间接映射:某些定时器支持通道与输入引脚重新映射(TIMx_REMAP)。
c复制// 输入捕获配置示例(测量高电平脉宽)
TIM_ICInitTypeDef TIM_ICInitStructure;
// 通道1配置为上升沿捕获
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 = 0x0;
TIM_ICInit(TIM3, &TIM_ICInitStructure);
// 通道2配置为下降沿捕获
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_IndirectTI;
TIM_ICInit(TIM3, &TIM_ICInitStructure);
// 使能捕获中断
TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2, ENABLE);
3.3 频率与占空比测量算法
基于输入捕获实现频率和占空比测量,主要有两种方法:
方法一:周期测量法
- 固定一个边沿(如上升沿)触发捕获
- 记录连续两次触发的时间差T
- 频率=1/T,需要处理计数器溢出
方法二:高/低电平分别捕获
- 上升沿和下降沿都触发捕获
- 高电平时间 = 下降沿捕获值 - 上升沿捕获值
- 周期 = 下一个上升沿捕获值 - 上一个上升沿捕获值
- 占空比 = 高电平时间 / 周期
避坑指南:测量高频信号时,定时器计数频率必须足够高(奈奎斯特采样定理)。例如测量1MHz信号,定时器时钟至少需要10MHz以上。同时要注意ARR值设置,防止在测量周期内发生多次计数器溢出。
4. 实战问题排查与优化
4.1 常见问题速查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| PWM无输出 | GPIO未配置为复用功能 | 检查GPIO_Mode配置为AF_PP |
| 占空比异常 | CCRx值超过ARR | 确保CCRx ≤ ARR |
| 输入捕获丢失边沿 | 信号变化过快 | 降低输入滤波系数 |
| 测量值波动大 | 信号存在抖动 | 启用硬件滤波或软件中值滤波 |
| 定时器不计数 | 时钟未使能 | 检查RCC_APB1PeriphClockCmd调用 |
4.2 精度优化技巧
-
时钟源选择:内部RC振荡器精度较差(±1%),对于高精度计时建议使用外部晶振或时钟输入。
-
中断延迟补偿:在输入捕获中断服务函数中,读取捕获寄存器前先检查状态标志,减少中断响应时间的影响。
-
多次测量平均:对于存在随机噪声的信号,采用多次测量取平均的方法提高��度。
-
溢出处理:在测量长周期信号时,需要扩展计数器范围。可以通过以下两种方式:
- 软件计数溢出次数
- 使用定时器级联(一个定时器作预分频器)
-
DMA辅助:对于高频信号测量,可以配置DMA在捕获发生时自动传输捕获值到内存缓冲区,降低中断频率。
4.3 低功耗设计考量
在电池供电设备中使用定时器时,功耗优化尤为重要:
-
时钟门控:不使用的定时器及时关闭时钟(RCC_APBxPeriphClockCmd)
-
动态重配置:根据实际需求动态调整预分频值。例如待机时使用低频率,需要精确测量时切换到高频率。
-
从模式利用:使用外部信号触发定时器启停(从模式配置为门控模式),避免持续运行消耗功率。
-
唤醒源配置:将定时器中断配置为唤醒源,配合低功耗模式使用。
5. 进阶应用案例
5.1 旋转编码器接口
增量式编码器通常输出两路相位差90°的方波(A/B相)。通过配置定时器的编码器接口模式,可以自动识别转向和计数:
- 配置TIMx_CH1和TIMx_CH2为输入捕获
- 设置TIM_EncoderInterfaceConfig为TI1/TI2模式
- 定时器会自动根据两相信号的相位关系递增/递减计数
c复制// 编码器模式配置示例
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12,
TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_SetCounter(TIM3, 0);
TIM_Cmd(TIM3, ENABLE);
5.2 超声波测距实现
HC-SR04等超声波模块通过测量回波高电平时间计算距离。典型实现流程:
- 触发引脚输出10μs以上高电平
- 配置输入捕获通道为上升沿触发(开始计时)
- 捕获到回波上升沿后,切换为下降沿触发
- 捕获下降沿时计算时间差Δt
- 距离 = (Δt * 声速) / 2
实测技巧:声速受温度影响明显(v=331.4+0.6T m/s,T为摄氏度),高精度应用需加入温度补偿。
5.3 多路PWM舵机控制
控制多个舵机需要多路独立的PWM信号(周期20ms,脉宽0.5-2.5ms)。实现方案:
- 使用一个定时器生成基准PWM(如1MHz)
- 配置多个从定时器工作在单脉冲模式(One Pulse Mode)
- 主定时器更新事件触发从定时器开始计数
- 每个从定时器设置不同的CCRx值实现相位差
这种方案比使用多个定时器更节省资源,且所有通道严格同步。
