1. STM32定时器PWM测量实验概述
在嵌入式系统开发中,精确测量PWM信号的周期和占空比是常见需求。本次实验基于STM32F10x系列单片机,利用TIM3生成PWM信号,同时使用TIM1的输入捕获功能测量该PWM信号的参数。这种自测自量的方式不仅验证了定时器模块的正确性,也展示了STM32定时器的高级应用场景。
实验硬件平台采用常见的STM32F103C8T6最小系统板,通过PA6引脚(TIM3_CH1)输出PWM信号,PA8引脚(TIM1_CH1)接收同一信号进行测量。测量结果通过USART1以115200波特率发送至上位机显示。这种设计在电机控制、电源管理等场景中具有实用价值,比如无刷电机驱动时需要实时监测PWM参数确保系统稳定。
2. 硬件设计与时钟配置
2.1 时钟树配置分析
STM32的时钟系统是定时器精度的基础。本实验使用72MHz主频配置,APB1总线时钟为36MHz(定时器3所在总线),APB2总线时钟为72MHz(定时器1所在总线)。由于定时器挂在APB1上时会自动倍频,TIM3实际时钟也是72MHz。
注意:STM32F1系列中,当APB1预分频系数不为1时,定时器时钟会2倍频。这是很多初学者容易忽略的细节,直接导致定时器计算错误。
时钟配置代码如下:
c复制RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1 |
RCC_APB2Periph_TIM1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
2.2 引脚功能分配
- PA6 (TIM3_CH1):PWM输出引脚,配置为复用推挽输出
- PA8 (TIM1_CH1):输入捕获引脚,配置为浮空输入
- PA9 (USART1_TX):串口发送引脚,配置为复用推挽输出
GPIO速度设置差异值得注意:PWM输出引脚设为2MHz以降低噪声,而USART引脚设为10MHz确保通信稳定。这种根据功能需求调整GPIO速度的做法是实际工程中的常见优化手段。
3. PWM信号生成实现
3.1 TIM3基础配置
TIM3配置为向上计数模式,关键参数计算如下:
- 预分频值(Prescaler):71
- 定时器时钟72MHz / (71+1) = 1MHz
- 自动重载值(Period):999
- PWM频率 = 1MHz / (999+1) = 1kHz
- 初始占空比(Pulse):300
- 占空比 = 300/1000 = 30%
c复制TIM_TimeBaseInitStruct.TIM_Period = 999;
TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);
3.2 PWM模式细节
选用PWM模式1,极性为高电平有效。这种配置下:
- 当计数器值小于CCRx时输出有效电平(高)
- 当计数器值大于等于CCRx时输出无效电平(低)
特别需要注意MOE(Main Output Enable)位的使能,这是高级定时器才有的功能:
c复制TIM_CtrlPWMOutputs(TIM3, ENABLE); // 必须调用以输出PWM
4. PWM参数测量实现
4.1 TIM1输入捕获配置
TIM1配置为从模式,使用TI1FP1作为触发源,从模式设为Reset模式。这种配置下:
- 每次检测到上升沿时计数器复位
- 下降沿触发捕获CCR2的值
关键参数:
- 通道1:上升沿捕获,直接输入
- 通道2:下降沿捕获,间接输入
- 滤波器值设为0,不进行滤波
c复制TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInit(TIM1, &TIM_ICInitStruct);
4.2 测量原理与计算
测量过程分为三步:
- 等待Trigger标志位置位(检测到上升沿)
- 读取CCR1(周期值)和CCR2(高电平时间)
- 计算周期和占空比
计算公式:
- 周期(ms) = CCR1 * (1/1MHz) * 1000
- 占空比(%) = (CCR2 / CCR1) * 100
实际代码中添加了100ms延时避免数据刷屏:
c复制float period = ccr1 * 1.0e-6f * 1.0e3f;
float duty = ((float)ccr2) / ccr1 * 100.0f;
5. 串口通信实现
5.1 USART1配置
采用115200波特率,8位数据位,无校验位,1位停止位的基础配置。注意GPIO模式必须设为AF_PP(复用推挽输出):
c复制GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
USART_InitStruct.USART_BaudRate = 115200;
USART_Init(USART1, &USART_InitStruct);
5.2 打印函数优化
使用自定义的My_USART_Printf函数输出浮点数,注意STM32标准库默认不支持浮点打印,需要:
- 在工程设置中勾选"Use float with printf"
- 或者使用sprintf先格式化到缓冲区
6. 常见问题与调试技巧
6.1 测量值异常排查
现象:测量得到的周期或占空比明显错误
可能原因:
- 定时器时钟配置错误 - 检查RCC配置和预分频值
- 引脚模式设置错误 - PWM输出必须AF_PP,输入捕获根据情况选择
- 从模式配置错误 - 确保触发源和从模式正确
调试技巧:先用示波器观察PA6输出的PWM波形,确认生成正确后再检查测量部分。
6.2 无输出信号排查
现象:PA6无PWM信号输出
检查步骤:
- 确认TIM_Cmd和TIM_CtrlPWMOutputs都已使能
- 检查GPIO时钟和定时器时钟是否开启
- 验证GPIO初始化代码,模式必须为AF_PP
- 检查MOE位是否置位(高级定时器特有)
6.3 数据跳变问题
现象:测量值在小范围内波动
解决方案:
- 增加输入捕获滤波器(TIM_ICFilter参数)
- 多次测量取平均值
- 检查电源稳定性,添加去耦电容
7. 进阶应用与扩展
7.1 高精度测量实现
要提高测量精度,可以:
- 使用更高主频(如STM32F4系列)
- 启用定时器的输入捕获预分频功能
- 采用DMA传输捕获值减少中断延迟
7.2 多通道测量
扩展方案:
- 配置多个输入捕获通道
- 使用定时器级联技术
- 通过中断或DMA处理多路信号
7.3 实际工程应用
该技术在以下场景有实用价值:
- 电机转速测量(通过编码器信号)
- 电源反馈环路监测
- 无线通信中的脉冲宽度解码
我在实际项目中发现,合理设置输入捕获滤波值(0x0F以内)能有效抑制毛刺干扰,但过大的滤波值会导致边沿检测延迟。通常建议从0x04开始尝试,根据实际信号质量调整。