STM32CubeMX + HAL 库:定时器输入捕获的应用,PWM波的占空比(频率/周期)测量
1. 概述
本实验旨在通过 STM32CubeMX 配置定时器输入捕获功能,并结合 HAL 库编程接口,实现对外部输入 PWM 信号的频率(或周期)和占空比 的精准测量。实验重点在于理解 STM32 定时器的输入捕获机制,以及掌握如何利用硬件定时器对脉冲信号的时间特性进行量化分析,从而实现信号周期与占空比的计算。
在实验过程中,使用 STM32 定时器的输入捕获通道 来检测 PWM 信号的上升沿与下降沿,通过捕获比较寄存器(CCR)的数值差计算高电平持续时间与整个周期时间。结合 HAL 库的中断回调机制,可实现实时数据采集与占空比计算。
本实验具有重要的工程应用意义。通过掌握定时器输入捕获测量 PWM 占空比与周期的技术,不仅能够实现对周期性信号的精确分析,还为多种嵌入式系统信号测量与控制任务提供了基础支撑。输入捕获机制本质上是一种时间精度极高的信号测量手段,可用于捕获任意脉冲信号的高、低电平持续时间,从而实现更复杂的功能扩展。
在实际工程中,该技术被广泛应用于以下场景:
红外线遥控信号解码:通过捕获脉冲间隔与宽度,识别不同编码格式,实现家电控制与信号识别。
超声波测距模块:利用输入捕获测量回波脉冲宽度,计算超声波传播时间,从而精确获得距离信息。
电容触摸按键:利用输入捕获测量电容触摸按键的充电时间,当手指接近感应电极时,等效电容增大,使得充电时间相应延长。通过对比当前测得的充电时间与基准充电时间,可准确判断按键是否被触摸,从而实现无机械结构的按键检测。
舵机与电机控制反馈:通过测量反馈 PWM 信号的占空比,获取角度或速度信息,实现闭环控制。
测速与计频应用:对转速传感器或方波信号进行捕获,计算转速、流量等物理量。
通信协议时序分析:例如对 One-Wire、DHT11/DHT22 温湿度传感器等脉宽编码信号进行解析。
通过本实验的学习与实践,学生不仅掌握了 STM32 输入捕获的配置与编程方法,更能体会该技术在信号测量、控制反馈、智能传感与系统通信等多个嵌入式领域中的重要价值。这为后续开展复杂信号处理、自动控制系统设计以及多传感器融合应用奠定了坚实的技术基础。
2. 测量原理
2.1 输入捕获的作用
输入捕获(Input Capture)是定时器的一项关键功能,用于精确测量输入信号的时间特征。
它可以在检测到输入通道上信号的上升沿或下降沿时,将当时定时器计数器(CNT)的数值“锁存”到捕获寄存器(CCR)中,从而记录事件发生的精确时间点。通过对两次捕获结果求差,即可得到脉冲信号的周期、频率或高电平持续时间。
2.2 周期与频率测量原理
当测量 PWM 信号的周期或频率时,只需捕获**连续的两个相同边沿(上升沿或下降沿)**的时间间隔。
该时间差反映了信号的一个完整周期,从而可计算出:
其中,T 为两次捕获间的时间差。
2.3 占空比测量原理
占空比定义为信号在一个周期内高电平持续时间与周期时间之比,只要测量出连续的一个上升沿和一个下降沿的时间间隔,然后除以周期即可。
当使用 定时器输入捕获(Input Capture) 测量占空比时,常用方法是捕获一个上升沿和随后的下降沿得到高电平时间 T1,并结合连续两个相同边沿(通常为连续两个上升沿)得到周期 T。
2.4 输入捕获内部过程
整个输入捕获过程可以分为以下几个阶段:
2.4.1 输入通道
外部信号首先通过定时器输入引脚(如 TIMx_CH1
)进入定时器模块,对应逻辑通道信号标记为 TI1。该信号是输入捕获的起点,决定了捕获信号的源头与物理通道。
2.4.2 滤波与边沿检测
TI1 信号首先经过数字滤波器(Input Filter),用于滤除短暂的毛刺或干扰脉冲,从而保证输入信号的稳定性和捕获结果的可靠性。
随后,信号进入边沿检测器(Edge Detector),根据配置可选择检测上升沿、下降沿或双边沿,用于产生标准化的捕获触发信号。
经边沿检测后,信号输出为 TI1FP1(即 Filtered Polarity 1 信号),作为后续模块的触发输入。
在多通道捕获应用中,可以通过内部信号选择器(Input Channel MUX),将同一外部输入信号(如 TI1)分别映射到不同的捕获通道(如 IC1 和 IC2)。这样,定时器的不同通道可分别配置为检测上升沿或下降沿,从而实现对同一输入信号的不同边沿事件进行独立捕获(例如测量 PWM 的高电平时间与周期)。
2.4.3 信号选择器(多路选择)
TI1FP1 信号经过**信号选择器(Multiplexer)**选择后,输出为 IC1(Input Capture 1)。
多路选择的目的,是在定时器的多个输入源之间选择捕获信号(例如可选择 TI1、TI2 或内部触发信号),从而提高通道复用灵活性。
2.4.4 预分频器(Prescaler)
捕获信号 IC1 进入输入捕获预分频器(ICPSC),可对输入事件进行分频处理。
若输入信号频率较高,可以设置每捕获 N 次有效边沿才触发一次捕获事件(N 可为 2、4、8),从而避免过多中断,提高系统性能。
2.4.5 捕获与寄存
分频后的信号(IC1PS)在检测到有效边沿后,会产生一次捕获事件(Capture Event)。
此时:
当前计数器值(CNT)会立即被“锁存”到对应的捕获寄存器(CCR1)中;
若启用了捕获中断,系统会同时触发 捕获中断(Capture Interrupt),用户可在中断回调函数中读取 CCR 值并计算信号特性。
在下一次捕获事件发生前,捕获寄存器的值保持不变,确保测量数据的稳定性。
2.5 测量方法
2.5.1 从模式测量(推荐)
从模式(Slave Mode) 本质上是让一个定时器的计数器 CNT 的行为受外部或内部事件控制,而不是自由运行。在自由模式下,定时器从 0 开始计数,到达 ARR 自动重载,完全由内部时钟驱动。在从模式下,计数器的启动、停止、清零或计数脉冲可以由外部输入信号或其他定时器的触发信号(Trigger Event)来控制。
SMS(二进制) | 十进制 | 模式名称(英文/中文) | 说明 / 典型用途 |
---|---|---|---|
000 | 0 | Disabled(关闭) | 从模式关闭,定时器自由运行 |
001 | 1 | Encoder Mode 1(编码器模式1) | 编码器接口(计数A/B) |
010 | 2 | Encoder Mode 2(编码器模式2) | 编码器接口 |
011 | 3 | Encoder Mode 3(编码器模式3) | 编码器接口(双向) |
100 | 4 | Reset Mode(复位模式) | 触发时复位 CNT;用于 PWM 周期对齐/占空比测量(推荐) |
101 | 5 | Gated Mode(门控模式) | 仅在触发有效时计数;用于脉冲宽度测量 |
110 | 6 | Trigger Mode(触发模式) | 触发事件用于启动/重启计数器;用于多定时器同步启动 |
111 | 7 | External Clock / ExtClock Mode(外部时钟/扩展) | 触发作为计数时钟(External Clock Mode 1 等) |
本文采用 从模式(Reset Mode),利用 PWM 信号的上升沿作为触发源,使定时器每个周期自动清零计数器(CNT)。同时,两个捕获比较寄存器(CCR)分别锁存上升沿和下降沿到来的 CNT 值,从而实现对 PWM 信号的 周期/频率测量 和 占空比计算。其测量步骤如下所示:
配置复位触发源
将定时器从模式(Slave Mode)设置为 复位模式(Reset Mode),并选择 TI1FP1(PWM 信号上升沿)作为触发源。每当 PWM 上升沿到来时,定时器的计数器(CNT)自动清零,为新的周期计数做好准备。启动计数与通道配置
CNT 计数器从零开始计数。定时器配置两个输入捕获通道:通道1(CH1):捕获上升沿,用于记录周期起点;
通道2(CH2):捕获下降沿,用于记录高电平结束时的计数值。
下降沿捕获
当 PWM 信号下降沿到来时,CH2 捕获事件触发,当前 CNT 值被锁存到 CCR2,该值即对应 PWM 的高电平持续时间 T1。上升沿捕获与计数器复位
当下一次上升沿到来时,CH1 捕获事件触发,当前 CNT 值被锁存到 CCR1,该值对应完整周期时间 T;同时复位触发生效,CNT 自动清零,为下一个周期计数做好准备。占空比计算
通过读取 CCR1 和 CCR2,按公式计算占空比
2.5.2 非从模式双通道测量
计数器自由运行
定时器计数器(CNT)保持自由计数状态,不使用从模式。PWM 信号通过输入捕获通道进入定时器。通道配置
配置两个输入捕获通道:通道1(CH1):捕获上升沿,用于记录周期计数值;
通道2(CH2):捕获下降沿,用于记录高电平结束时的计数值。
下降沿捕获
当 PWM 信号下降沿到来时,CH2 捕获事件触发,中断服务函数执行:读取当前 CNT 值,锁存到 CCR2,对应高电平时间 T1;
此时不手动清零CNT,保持连续计数,便于周期计算。
上升沿捕获与 CNT 清零
当下一次上升沿到来时,CH1 捕获事件触发,中断服务函数执行:读取当前 CNT 值,锁存到 CCR1,对应完整周期时间 T;
手动清零 CNT,为下一个周期计数做好准备。
占空比计算
通过读取 CCR1 和 CCR2,按公式计算占空比
2.5.3 非从模式单通道测量
计数器自由运行
定时器计数器(CNT)保持自由计数状态,不使用从模式。PWM 信号通过 CH1 输入捕获通道进入定时器。通道配置
配置 CH1 为输入捕获:初始捕获边沿为 上升沿,用于周期测量;
使能捕获比较中断(CC1IE = 1)。
上升沿捕获与计数器清零
当 PWM 信号上升沿到来时,中断服务函数执行:读取 CNT 值并保存为周期时间
T
;手动清零 CNT,保证从上升沿开始计数;
将捕获极性切换为 下降沿,等待高电平结束。
下降沿捕获
当 PWM 信号下降沿到来时,中断服务函数执行:读取 CNT 值并保存为高电平时间
T1
,因为 CNT 从上升沿清零开始计数,高电平时间直接等于当前 CNT 值;将捕获极性切换回 上升沿,准备下一周期测量。
周期测量与占空比计算
通过高电平时间和周期时间,按公式计算占空比
2.5.4 三种方法对比
对比项 | 从模式测量(主从通道) | 双通道测量(同时捕获) | 单通道非从模式测量 |
---|---|---|---|
测量原理 | 使用一个定时器的两个通道(如 CH1 主、CH2 从),通过从模式复位机制,在上升沿复位 CNT,硬件自动计算周期和占空比 | 使用两个输入通道(如 CH1 捕获上升沿、CH2 捕获下降沿),通过比较两次捕获值获得高电平时间和周期 | 使用一个通道(如 CH1)交替捕获上升沿和下降沿,在中断中切换极性并手动清零 CNT |
CNT 计数控制 | 上升沿触发自动清零(硬件复位),周期计数由硬件完成 | 每次捕获后在中断中手动清零 CNT | 每次捕获后在中断中手动清零 CNT |
触发与极性 | 硬件自动区分上升沿与下降沿 | 通道间独立配置极性(CH1 上升沿、CH2 下降沿) | 每次捕获中断后手动反转捕获极性 |
中断逻辑 | 简单,仅需读取 CCR1、CCR2 即可计算 | 中断中读取两个通道的捕获值,进行差值计算 | 逻辑较复杂,中断中既要清 CNT 又要切换极性 |
测量精度 | ★★★★★(硬件同步、自动清零、无中断延迟) | ★★★★☆(独立捕获,精度高但略受通道同步影响) | ★★★☆☆(中断延迟和清零时间造成误差) |
软件复杂度 | ★★☆☆☆(配置完成后硬件自动测量) | ★★★☆☆(需在代码中处理两通道同步) | ★★★★☆(中断逻辑繁琐,需切换极性和清零) |
CPU 占用率 | 低 | 中 | 高 |
资源占用 | 2 个通道(如 CH1 主、CH2 从) | 2 个通道(CH1、CH2) | 1 个通道 |
适用场景 | 高精度频率与占空比测量、实际工程中推荐方案 | 测量两个信号的相位差或延迟时间 | 单通道资源受限的低速 PWM 测量或教学对比实验 |
优点 | 精度高、全硬件自动完成、抗干扰能力强 | 精度高,可测量多个信号关系 | 通道占用少、结构简单 |
缺点 | 需配置主从关系、理解门槛较高 | 占用两个输入通道、同步性略低 | 精度受限、中断频繁、受 CPU 响应影响 |
3. STM32CubeMX 配置
利用通用定时器配置一个频率1KHz 占空比40%的PWM方波
注:硬件方面,一定要用杜邦线将PWM输出IO口和输入捕获输入IO口连接在一起。本文是PA1和PA6.
3.1 从模式测量配置
由于定时器的复位触发信号选择为 TI1FP1,该信号对应的输入通道为 CH1(TI1)。
因此,计数器的复位触发极性由通道 CH1 的输入捕获极性决定。在本实验中,CH1 通常配置为上升沿捕获,因此计数器为 上升沿复位。
3.2 非从模式双通道测量配置
与从模式不同,需配置中断,并在中断回调函数中清空计数器CNT
3.3 非从模式单通道测量配置
与从模式不同,需配置中断,并在中断回调函数中清空计数器CNT、反转捕获极性、记录中断高低电平CNT值
4. VSCode代码
4.1 从模式测量代码
由于计数器的复位(清零)、高电平和低电平时间的捕获,都是硬件在配置后自动完成的,因此配置中也无需进行中断开启,无需编写任何软件中断回调函数。
只需在主函数中初始化并启动两个输入捕获通道,然后直接读取这两个通道的 CCR寄存器值,即可计算信号的周期、频率和占空比。
uint32_t period, high; // pwm周期 pwm高电平
float duty, freq; // pwm占空比 pwm频率HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); // 启动PWM计数
HAL_TIM_IC_Start(&htim3, TIM_CHANNEL_1); // 启动上升沿捕获
HAL_TIM_IC_Start(&htim3, TIM_CHANNEL_2); // 启动下降沿捕获while(1){period = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_1); // 周期high = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_2); // 高电平宽�?if (period != 0){duty = (float)high / period * 100.0f;freq = 1000000.0f / period; // 计数频率=1MHzprintf("PWM: Period=%lu us, High=%lu us, Duty=%.2f %%, Freq=%.2f Hz\r\n",period, high, duty, freq);}HAL_Delay(2000); // 2秒延迟
}
4.2 非从模式双通道测量代码
与从模式相比,自由计数模式的主要区别在于:
需要分别开启 上升沿捕获中断 和 下降沿捕获中断;
在 上升沿捕获中断 中手动清零计数器(CNT),为下一个周期计数做好准备;
其他配置不变,仍然通过读取 CCR1 和 CCR2 分别获得周期时间和高电平时间,然后计算占空比和信号频率。
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {if(htim->Instance == TIM3){if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) // 上升沿{__HAL_TIM_SET_COUNTER(htim, 0); // 手动清零CNT}} }
uint32_t period, high; // pwm周期 pwm高电平 float duty, freq; // pwm占空比 pwm频率HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); // 启动tim2计数器 // 启动输入捕获中断 HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1); HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);while(1){period = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_1); // 周期high = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_2); // 高电平宽�?if (period != 0){duty = (float)high / period * 100.0f;freq = 1000000.0f / period; // 计数频率=1MHzprintf("PWM: Period=%lu us, High=%lu us, Duty=%.2f %%, Freq=%.2f Hz\r\n",period, high, duty, freq);}HAL_Delay(2000); // 2秒延迟 }
4.3 非从模式单通道测量代码
与双通道捕获法相比,单通道方法同样依赖中断回调函数。不同之处在于:
需要在 上升沿捕获中断中清零计数器(CNT),为下一周期计数做好准备;
还需 动态切换捕获极性,在上升沿和下降沿之间交替捕获;
通过记录 上升沿到下降沿的高电平时间 和 两次相邻上升沿之间的周期时间,再进行计算得到占空比和频率。
extern uint32_t period,high;
extern float duty, freq ;
extern uint8_t capture_flag;void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{static uint8_t edge = 0; // 0:上升沿, 1:下降沿uint32_t cnt;if(htim->Instance == TIM3 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1){cnt = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);if(edge == 0) // 上升沿:测周期{period = cnt;__HAL_TIM_SET_COUNTER(htim, 0); // 清零CNT// 切换为下降沿捕获__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);edge = 1;}else // 下降沿:测高电平{high = cnt; // CNT从上升沿清零开始计数,高电平时间直接等于CNT值// 切换回上升沿捕获__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);edge = 0;// 计算占空比和频率if(period != 0){duty = (float)high / period * 100.0f;freq = 1000000.0f / period; // 假设计数频率为1MHz}capture_flag = 1;}}
}
uint32_t period = 0, high = 0; // pwm周期, pwm高电平
float duty = 0, freq = 0; // pwm占空比 pwm频率
uint8_t capture_flag = 0; // 捕获标志位HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); // 启动tim2计数器
// 单通道
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);// 启动输入捕获中断while(1){if(capture_flag){capture_flag = 0;printf("PWM: Period=%lu us, High=%lu us, Duty=%.2f %%, Freq=%.2f Hz\r\n",period, high, duty, freq);}HAL_Delay(2000); // 2秒延迟
}
5 结论
TIM2输出 PWM: Period=10000us, High=4000us, Duty=40 %, Freq=100 Hz
通过三种方法对其进行测量,最后得到的结果如图所示:
1. 从模式 PWM: Period=9999 us, High=3999 us, Duty=39.99 %, Freq=100.01 Hz
2. 双通道 PWM: Period=9998 us, High=3998 us, Duty=39.99 %, Freq=100.02 Hz
3. 单通道 PWM: Period=9997 us, High=3997 us, Duty=39.98 %, Freq=100.03 Hz
实验同时演示了 从模式、双通道 和 单通道 三种方法测量 PWM 的周期、频率和占空比,并对比了它们在测量精度和实时性方面的差异。实验结果显示:
从模式(Reset Mode):通过硬件自动清零计数器 CNT,测量精度最高;
双通道方法:通过中断清零 CNT ,精度次之;
单通道方法:通过中断清零 CNT 、动态切换捕获极性并分别记录上升沿和下降沿CNT,精度最低。
原因在于:中断占用 CPU 处理时间,中断回调函数执行的指令越多,占用 CPU 越久,从而导致测量精度下降。