news 2026/9/4 22:06:50

STM32 14 PWM1测频率占空比(测周法)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32 14 PWM1测频率占空比(测周法)

一、学习背景和目标

1.1 学习背景

在嵌入式系统开发中,测量外部信号的频率和占空比是一项非常常见的需求。无论是电机转速检测、遥控器信号解码,还是传感器数据采集,都离不开对脉冲信号的精确测量。传统的测量方法往往需要额外的硬件计数器或复杂的逻辑分析仪,不仅成本高,而且使用不便。

STM32 系列单片机内置了功能强大的定时器(Timer)模块,配合输入捕获(Input Capture)功能,可以轻松实现对 PWM 信号频率和占空比的精确测量。本实验基于 STM32F103 微控制器,利用 TIM2 产生 PWM 信号,再通过 TIM3 的输入捕获功能对信号进行测量,最终在 OLED 屏幕上实时显示测量结果。

1.2 学习目标

通过本实验,你将掌握以下核心知识与技能:

  • 理解 PWM 信号的基本原理:掌握频率、占空比的概念及其计算方法。
  • 掌握 STM32 定时器的基本配置:学会使用标准外设库配置定时器的时基单元。
  • 掌握 PWM 输出模式:学会使用 TIM2 的 PWM 模式生成可调频率、可调占空比的方波信号。
  • 掌握输入捕获功能:学会使用 TIM3 的输入捕获模式测量外部信号的频率和占空比。
  • 掌握 OLED 显示技术:学会在 OLED 屏幕上实时显示测量数据。
  • 培养系统调试能力:通过实际测量验证理论计算,提升嵌入式开发的综合实践能力。

二、接线图

三、代码块
main.h

#include"stm32f10x.h"// Device header#include"delay.h"#include"OLED.h"#include"pwm.h"#include"IC.h"intmain(){OLED_Init();pwm_init();IC_init();pwm_setpsc(7200-1);//ƵÂÊ=72M/(PSC+1)(ARR+1)pwm_setcompare(70);OLED_ShowString(1,1,"Freq:");OLED_ShowString(1,12," HZ");OLED_ShowString(2,1,"Duty:");OLED_ShowString(2,12," %");while(1){OLED_ShowNum(1,6,get_fre(),6);//×îµÍ´ó¸ÅÊÇ15,×î´ó1000000;OLED_ShowNum(2,6,get_duty(),6);}}

pwm.c

#include"stm32f10x.h"// Device headervoidpwm_init(void){RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period=100-1;//ARRTIM_TimeBaseInitStructure.TIM_Prescaler=720-1;//PSCTIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);TIM_OCInitTypeDef TIM_OCInitStructure;TIM_OCStructInit(&TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;TIM_OCInitStructure.TIM_Pulse=50;//CCRTIM_OC1Init(TIM2,&TIM_OCInitStructure);TIM_Cmd(TIM2,ENABLE);}voidpwm_setcompare(uint16_tnum){TIM_SetCompare1(TIM2,num);}voidpwm_setpsc(uint16_tpsc){TIM_PrescalerConfig(TIM2,psc,TIM_PSCReloadMode_Immediate);}

IC.c
#include “stm32f10x.h” // Device header

void IC_init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); TIM_InternalClockConfig(TIM3); TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //ARR TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure); TIM_ICInitTypeDef TIM_struct; TIM_struct.TIM_Channel=TIM_Channel_1; TIM_struct.TIM_ICFilter=0xF; TIM_struct.TIM_ICPolarity=TIM_ICPolarity_Rising; TIM_struct.TIM_ICPrescaler=TIM_ICPSC_DIV1; TIM_struct.TIM_ICSelection=TIM_ICSelection_DirectTI; TIM_PWMIConfig(TIM3,&TIM_struct); //µÈЧÓÚ£ºTIM_struct.TIM_Channel=TIM_Channel_2; //TIM_struct.TIM_ICFilter=0xF; //TIM_struct.TIM_ICPolarity=TIM_ICPolarity_Falling; //TIM_struct.TIM_ICPrescaler=TIM_ICPSC_DIV1; //TIM_struct.TIM_ICSelection=TIM_ICSelection_IndirectTI; //TIM_ICInit(TIM3,&TIM_struct); TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1); TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset); TIM_Cmd(TIM3,ENABLE);

}

uint32_t get_fre(void)
{
return 1000000/(TIM_GetCapture1(TIM3)+1);
}

uint32_t get_duty(void)
{
return (TIM_GetCapture2(TIM3)+1)*100/(TIM_GetCapture1(TIM3)+1);
}

四、知识点详解

4.1 PWM 信号产生原理

本实验使用 TIM2 的 PWM 输出模式产生被测信号。PWM 波形的核心参数有两个:

  • 频率(Frequency):由定时器的时钟源、预分频器(PSC)和自动重装载值(ARR)共同决定,计算公式为频率 = 72MHz / ((PSC+1) × (ARR+1))
  • 占空比(Duty Cycle):由比较寄存器(CCR)与自动重装载值(ARR)的比值决定,计算公式为占空比 = CCR / (ARR+1) × 100%

pwm_init()中,TIM_Period = 100 - 1设置 ARR 为 99,TIM_Prescaler = 720 - 1设置 PSC 为 719,因此默认输出频率为72MHz / (720 × 100) = 1000Hz,默认占空比为50 / 100 = 50%pwm_setpsc()pwm_setcompare()分别用于动态调整频率和占空比。

4.2 输入捕获测量原理

本实验使用 TIM3 的输入捕获功能测量外部信号的频率和占空比,核心思路如下:

  • 频率测量:利用定时器的从模式复位功能,在每次捕获到上升沿时,计数器自动清零并重新计数。因此,TIM_GetCapture1(TIM3)返回的即为一个完整周期的计数值,频率计算公式为频率 = 72MHz / (PSC+1) / (捕获值+1)。本实验中 PSC 设置为 71,故get_fre()返回1000000 / (捕获值+1)
  • 占空比测量:通过TIM_PWMIConfig()配置 PWM 输入模式,通道 1 捕获上升沿(记录周期),通道 2 自动捕获下降沿(记录高电平时间)。占空比计算公式为占空比 = 高电平时间 / 周期 × 100%,即get_duty()中的(TIM_GetCapture2(TIM3)+1) × 100 / (TIM_GetCapture1(TIM3)+1)

4.3 定时器从模式复位

TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1)将 TI1 的上升沿作为触发源,TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset)使计数器在触发时自动复位。这一机制保证了每次捕获到的计数值都对应一个完整的信号周期,无需软件干预即可连续测量。

4.4 OLED 显示

OLED 屏幕通过OLED_ShowString()OLED_ShowNum()实时刷新频率与占空比数据。主循环中不断调用get_fre()get_duty()获取最新测量值并显示,实现动态监测。

五、实验不足与改进方向

5.1 测量精度受限

  • 低频测量误差大:当被测信号频率较低时,计数器可能溢出(ARR 最大为 65535),导致测量结果不准确。当前代码未处理计数器溢出情况。
  • 高频测量分辨率不足:PSC 固定为 71,当频率较高时,一个周期内的计数值较小,量化误差相对增大。

5.2 功能单一

  • 仅支持单通道测量,无法同时测量多路信号。
  • 未实现超量程提示,当信号超出可测范围时,OLED 显示结果可能失真。

5.3 缺少校准与滤波

  • 未对输入信号进行软件滤波,易受噪声干扰,导致测量值抖动。
  • 未提供校准功能,测量结果可能存在系统偏差。

5.4 改进方向

  • 增加计数器溢出处理,扩展低频测量范围。
  • 根据信号频率动态切换预分频系数,提高测量分辨率。
  • 加入软件滤波算法(如多次采样取平均),提升测量稳定性。
  • 扩展多通道测量,支持同时监测多路 PWM 信号。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/4 22:06:50

MiniMax H3本地部署实测:ComfyUI中AI视频生成安装与使用

MiniMax H3 本地部署实测:AI 视频生成模型在 ComfyUI 中的安装与使用 AI 视频生成这两年最大的变化,是模型从“只能生成几秒动态图”逐步走向“能控制镜头、角色和参考图”。MiniMax H3 是这条路径上一个值得实测的对象。它的定位是文本生成视频模型&am…

作者头像 李华
网站建设 2026/9/4 22:05:18

依赖收集的内存账:一张响应式依赖图怎么长大

依赖收集的内存账:一张响应式依赖图怎么长大 在 Vue3 项目的日常开发中,响应式(Reactivity)几乎是“呼吸般自然”的基础能力。声明一个 ref 或 reactive,在模板中一写,数据一变视图就自动刷新。 但是&…

作者头像 李华
网站建设 2026/9/4 22:01:07

YOLOv8人流量检测实战:从算法选型到边缘部署全链路解析

简介:本资源是一套基于YOLOv8算法实现的人流量智能检测完整工程源码,面向具备Python与计算机视觉基础的开发者、智能监控系统集成工程师及高校相关专业学生,解决公共场所、交通枢纽、商业场所等场景下实时人流量统计与行为分析的实际需求。压…

作者头像 李华
网站建设 2026/9/4 21:55:14

无畏契约手游对枪总是输?预瞄、急停与陀螺仪校准全解析

无畏契约手游最近的热度不用多说。很多玩家在排位里会有一种很熟悉的感觉:明明自己反应不慢,提前枪也敢打,可一进入中距离对枪,就是拼不过对面。更让人沮丧的是,失败的原因看起来毫无规律——有时是因为子弹全飘了&…

作者头像 李华