news 2026/4/19 0:45:42

STM32通用定时器TIM2~5实战:输入捕获测量PWM频率与占空比(附代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32通用定时器TIM2~5实战:输入捕获测量PWM频率与占空比(附代码)

STM32通用定时器TIM2~5实战:输入捕获测量PWM频率与占空比(附代码)

在嵌入式系统开发中,精确测量外部PWM信号的频率和占空比是常见需求。无论是电机控制、LED调光还是传感器信号处理,都需要对PWM参数进行准确捕获。STM32的通用定时器TIM2~TIM5提供了强大的输入捕获功能,配合PWM输入模式(PWM Input Mode),仅需少量代码即可实现高精度测量。

1. 硬件架构与测量原理

STM32的通用定时器TIM2~TIM5每个都包含4个独立的输入捕获通道,采用三级流水线架构实现信号处理:

  1. 信号调理层:包含可编程数字滤波器和边沿检测器
  2. 通道映射层:支持输入通道与捕获通道的灵活交叉配置
  3. 捕获逻辑层:具有自动重装载和主从触发控制

测量PWM参数时,关键要理解双沿捕获机制

  • 频率测量:需要捕获两个相同极性边沿(如连续上升沿)的时间间隔
  • 占空比测量:需要捕获相反极性边沿(如上升沿和后续下降沿)的时间间隔
// 典型PWM信号参数关系 周期T = 上升沿n到上升沿n+1的时间 占空比 = 高电平时间 / 周期T * 100%

定时器工作在72MHz时,理论最小可检测脉宽约13.89ns(1/72MHz),实际精度受滤波器配置影响。

2. PWM输入模式配置详解

PWM输入模式是STM32提供的高级测量功能,其核心在于单输入双捕获架构:

特性常规输入捕获模式PWM输入模式
所需通道数2个1个
测量方式软件协调硬件自动
触发逻辑独立配置主从联动
适用场景简单信号精确PWM

配置步骤可分为硬件层和软件层:

2.1 硬件电路设计要点

  1. 信号接入:PWM信号应接入TIMx_CH1或TIMx_CH2引脚
  2. 滤波电路:高频干扰环境下建议增加RC硬件滤波(如100Ω+100pF)
  3. 电平匹配:确保输入信号电压在GPIO容忍范围内

注意:TIM2的CH1/CH2对应PA0/PA1,TIM3对应PA6/PA7,不同型号引脚可能不同,需查阅具体芯片数据手册。

2.2 软件配置流程

  1. 时钟使能

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  2. GPIO初始化

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; // TIM3_CH1 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);
  3. 时基配置

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Period = 0xFFFF; TIM_TimeBaseStructure.TIM_Prescaler = 72-1; // 1MHz计数频率 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
  4. 输入捕获配置

    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 = 0x0; TIM_ICInit(TIM3, &TIM_ICInitStructure);

3. 双通道捕获实战代码

以下完整代码展示了如何利用TIM3测量PWM频率和占空比:

#include "stm32f10x.h" volatile uint32_t IC3ReadValue1 = 0, IC3ReadValue2 = 0; volatile uint32_t DutyCycle = 0, Frequency = 0; void TIM3_Config(void) { TIM_ICInitTypeDef TIM_ICInitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; /* 时钟使能 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* GPIO配置 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* 时基配置 */ TIM_TimeBaseStructure.TIM_Period = 0xFFFF; TIM_TimeBaseStructure.TIM_Prescaler = 72-1; // 1MHz TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); /* 输入捕获配置 - 通道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); /* PWM输入模式特定配置 */ TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable); /* 中断配置 */ NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2, ENABLE); TIM_Cmd(TIM3, ENABLE); } void TIM3_IRQHandler(void) { if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET) { IC3ReadValue1 = TIM_GetCapture1(TIM3); TIM_ClearITPendingBit(TIM3, TIM_IT_CC1); } if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET) { IC3ReadValue2 = TIM_GetCapture2(TIM3); DutyCycle = (IC3ReadValue2 * 100) / IC3ReadValue1; Frequency = 1000000 / IC3ReadValue1; // 单位Hz TIM_ClearITPendingBit(TIM3, TIM_IT_CC2); } } int main(void) { TIM3_Config(); while(1) { // 测量结果存储在全局变量中: // DutyCycle - 占空比(百分比) // Frequency - 频率(Hz) } }

4. 性能优化与误差处理

实际应用中需要考虑以下关键因素来提升测量精度:

4.1 数字滤波器配置

TIMx_CCMRx寄存器中的ICxF位控制滤波参数:

ICxF值采样频率采样次数适用场景
0000无滤波1清洁环境
0010fDTS/44轻度干扰
0101fDTS/168工业环境
1011fDTS/326强干扰
// 设置通道1滤波器为8次采样 TIM3->CCMR1 |= (0x05 << 4);

4.2 测量范围与精度平衡

通过调整预分频器实现不同量程:

预分频值计时频率最小分辨率最大周期
072MHz13.89ns0.9ms
711MHz1μs65.5ms
719100kHz10μs655ms

4.3 常见问题排查

  1. 无中断触发

    • 检查GPIO模式应为浮空输入或上拉输入
    • 验证TIMx_CCER寄存器CCxE位是否使能
    • 确认NVIC中断控制器配置正确
  2. 测量值不稳定

    • 增加数字滤波器设置
    • 检查电源稳定性
    • 缩短信号走线长度
  3. 占空比计算异常

    • 确保两个通道极性配置相反
    • 检查通道映射关系(直接/间接TI)
    • 验证主从模式是否使能

提示:使用示波器对比实际信号与测量结果,可以快速定位硬件或软件问题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/19 0:37:11

Python运算符的使用简单介绍

1、算术运算符Python 中常用运算符&#xff1a;运算符说明实例结果加22.4 1537.4-减4.56 - 0.564*乘5 * 315/除法&#xff08;和数学中的规则一样&#xff09;8 / 24//整除&#xff08;只保留商的整数部分&#xff09;7 // 23%取模&#xff0c;即返回除法的余数7 % 21**次方运…

作者头像 李华
网站建设 2026/4/19 0:31:50

高性能PCB文件解析与可视化引擎OpenBoardView架构深度解析

高性能PCB文件解析与可视化引擎OpenBoardView架构深度解析 【免费下载链接】OpenBoardView View .brd files 项目地址: https://gitcode.com/gh_mirrors/op/OpenBoardView 面对日益复杂的电路板设计与维修挑战&#xff0c;硬件工程师需要能够快速解析多种格式PCB文件并进…

作者头像 李华
网站建设 2026/4/19 0:31:33

【实战部署指南】DDRNet 从零到一:Cityscapes 数据集训练、测试与自定义数据迁移全流程解析

1. 环境准备与工程部署 第一次接触DDRNet时&#xff0c;我被它的实时语义分割能力惊艳到了。这个由哈尔滨工业大学团队提出的轻量级网络&#xff0c;在保持高精度的同时还能达到实时推理速度&#xff0c;特别适合需要快速响应的场景。不过在实际部署过程中&#xff0c;确实遇到…

作者头像 李华