PWM作为硬件中几乎不可或缺的存在,学会 PWM,等于打通了 STM32 的“定时器体系”。学一次,STM32 全系列(甚至 AVR、PIC、ESP32)都能通用。硬件只要一个 I/O 就能驱动功率模块,非常省成本。不会 PWM,几乎没法独立做电机控制、灯光调节、舵机、开关电源类项目。

1.PWM 的本质是什么(从电子角度说)

PWM(Pulse Width Modulation)——脉冲宽度调制

它并不是直接输出“某个电压值”,而是输出一个 固定周期、可变占空比 的方波。

当你用这个方波去驱动:

LED → 人眼视觉暂留会“平均”亮度。

电机 → 电机电感+惯性会把高频方波“平均”成类似直流的电压。

舵机 → 内部单片机通过高电平脉宽判断位置。

开关电源 → 控制 MOSFET 的导通时间来调节能量传输。

占空比定义

假设周期 = T, 高电平时间 = Th,
占空比 D = Th / T

0% → 恒低

100% → 恒高

50% → 高低时间相等

2.输出比较通道

1.最左边:比较与“输出模式控制器”

输入:

CNT > CCR1、CNT = CCR1 两个比较结果

ETR(外部触发脚)

TIM1_CCMR1 里的配置位:OC1M[2:0](选择 PWM1/2、切换、强制高/低等),OC1CE(OCref 清除使能)

做的事:
根据选定的 输出比较模式(OC1M)和比较结果,产生一个“理想参考波形” OC1REF。

PWM1:CNT < CCR1 → OC1REF=有效;否则无效

PWM2:相反

Toggle/强制高/低:按模式固定/翻转

若 OC1CE=1 且 ETR 上升沿到来 → 强制把 OC1REF 拉为无效(快速关断/保护用)

记忆:OC1REF 只是“内部参考信号”,还没考虑死区、极性、关闭时状态。

2中间:死区发生器(高级定时器专属)

输入: OC1REF
控制位: TIM1_BDTR.DTG[7:0](死区时间编码)

输出: 两路互补且带空窗的信号:

OC1_DT:给主输出(OC1)

OC1N_DT:给互补输出(OC1N)

它们之间永不同时为有效,并在换向时插入 死区时间,避免上下管直通。

F1 的 DTG 为 8 位分段编码(三段倍率),实际死区 = 编码值 × t_DTS(或乘 2/8/16 的倍率,具体按手册分段公式换算)。核心记住:数越大,死区越长。

3右侧两组多路选择器:运行/空闲/故障时的“强制电平”

你看到每路(OC1、OC1N)在进入极性反相器之前都有一个小 MUX,它的若干个输入是:

来自死区单元的 OC1_DT / OC1N_DT(“正常工作波形”)

常量 ‘0’ 或 ‘1’(“强制电平”)

它们在什么情况下选谁?
取决于高级定时器的 关断/空闲策略:

运行关断(OSSR):当通道被软件关断(CC1E/CC1NE=0)但定时器还在运行时,输出要进入哪个“安全电平”。

空闲关断(OSSI):当主输出被关闭(MOE=0,比如 Break 触发或还没使能)时,引脚保持哪个“空闲电平”。

OISx/OISxN(在 TIM1_CR2):定义“空闲电平”到底是 0 还是 1(注意是在极性反相之前的电平)。

一句话:MUX 负责在 正常波形 和 强制 0/1 之间选择,OSSR/OSSI/OISx 决定“关掉时该保持什么电平”。

4极性(反相器)

主通道用 TIM1_CCER.CC1P

互补通道用 TIM1_CCER.CC1NP

当这些位为 1 时,对应通道在 MUX 之后做一次逻辑反相。

注意:OISx 的 0/1 是在反相之前定义的,所以最终引脚电平 =(OISx 设定)→(再看 CC1P/CC1NP 是否反相)。

5最右:输出使能电路 & 全局门控

通道局部使能:TIM1_CCER.CC1E(主)、CC1NE(互补)

全局主输出使能(高级定时器特有):TIM1_BDTR.MOE 必须为 1,否则各通道即便 CCxE=1 也出不来波形

还会受 刹车/锁定(BDTR.BKE、LOCK)等保护逻辑控制

结合 OSSR/OSSI/OISx,在被禁止时输出保持“安全/空闲”电平

最终,经过这些门控后,才真正到达芯片引脚 OC1 与 OC1N。

把整条链路串一下(典型的 PWM1 互补输出场景)

比较:CNT 与 CCR1 比 → 输出模式控制器按 OC1M 生成 OC1REF

死区:OC1REF → 生成互补且不重叠的 OC1_DT / OC1N_DT(间隔 = DTG)

关断策略:

正常运行且 CC1E/CC1NE=1 且 MOE=1 → MUX 选 带死区的波形

若你清了 CC1E(通道禁用)且 OSSR=1 → MUX 选 强制 0/1(保持安全电平)

若发生 Break 或 MOE=0 且 OSSI=1 → MUX 选 空闲电平(由 OIS1/OIS1N 定义)

极性:按 CC1P/CC1NP 反相或不反相

输出门:再经过 CC1E/CC1NE 与 MOE 的最终门控 → 到 OC1/OC1N 引脚

各寄存器在这张图里各司其职(速查)

CCMR1:OC1M(决定 OC1REF 的生成方式),OC1CE(ETR 清除 OC1REF)

BDTR:DTG(死区)、MOE(主输出总开关)、OSSR/OSSI(运行/空闲的关断选择)

CR2:OIS1/OIS1N(空闲电平设定)

CCER:CC1E/CC1NE(局部开关)、CC1P/CC1NP(极性)

两个常见“为什么”

为什么有 OC1 和 OC1N 两路?
做半桥/全桥时分别去驱动上管与下管,需要互补且不重叠的门控信号,死区发生器确保不直通。

为什么关掉时还要管 0/1?
关断瞬间的引脚电平关系到功率管安全与外部电路的默认状态,OSSR/OSSI + OISx 就是为“安全、可预测”而设计的。

3.PWM 生成过程(边沿对齐模式)

假设:

PSC = 71(分频 72)

ARR = 99

CCR1 = 30

执行过程:

时钟源:
CK_TIMER = 72 MHz(假设来自 APB1 倍频)
CK_CNT = CK_TIMER / (PSC + 1) = 72 MHz / 72 = 1 MHz
→ CNT 每 1 μs 加 1。

计数周期:
CNT 从 0 → 99(ARR),共 100次计数 → 周期 = 100×1 μs = 1 ms → f = 100Hz。

比较过程:

CNT < CCR1(0–29) → 输出为高(PWM1 模式,极性高)。

CNT = 30时 → 比较事件触发,输出变低。

CNT 继续到 99 → 更新事件(CNT 归零),输出回到高。

形成波形:
周期 1 ms,高电平 500 μs → 占空比 = 30/ 100 = 30%。

模式比较

4.PWM基本结构

代码例子(呼吸灯)

//-----------------------------
// STM32 TIM2_CH1 PWM 输出示例(1kHz,0~100%呼吸)
// 对应结构图流程:PSC -> CNT/ARR -> CCR -> 输出模式控制器 -> 极性 -> 输出使能 -> GPIO
//-----------------------------#include "stm32f10x.h"void PWM_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_OCInitTypeDef TIM_OCInitStruct;// 1) 开启 GPIOA、AFIO、TIM2 时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   // GPIO 模块时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);    // 复用功能时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);    // TIM2 时钟// 2) 部分重映射 TIM2_CH1 到 PA15,并关闭 JTAG(保留 SWD)//    图中相当于把“输出使能电路”的信号线连到 PA15 引脚GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);  GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);// 3) 配置 PA15 为复用推挽输出,交给定时器驱动GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_15;GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;     // 复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// 4) 定时器内部时钟作为计数源TIM_InternalClockConfig(TIM2);// 5) 配置时基单元(PSC 和 ARR)—— 图中“计数器单元”TIM_TimeBaseInitStruct.TIM_ClockDivision   = TIM_CKD_DIV1;          // 滤波采样分频=1TIM_TimeBaseInitStruct.TIM_CounterMode     = TIM_CounterMode_Up;    // 向上计数模式TIM_TimeBaseInitStruct.TIM_Period          = 100 - 1;               // ARR=99,100个计数TIM_TimeBaseInitStruct.TIM_Prescaler       = 720 - 1;                // PSC=719,把72MHz分频到100kHz// PWM频率 = 100kHz / 100 = 1kHzTIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;                    // 重复计数器不用TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);// 6) 配置输出比较单元(CCR、模式、极性)—— 图中“输出模式控制器”TIM_OCStructInit(&TIM_OCInitStruct); TIM_OCInitStruct.TIM_OCMode      = TIM_OCMode_PWM1;         // PWM1模式:CNT<CCR为有效TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;  // 使能输出TIM_OCInitStruct.TIM_OCPolarity  = TIM_OCPolarity_High;     // 有效电平=高TIM_OCInitStruct.TIM_Pulse       = 0;                       // CCR1初值=0,占空比0%TIM_OC1Init(TIM2, &TIM_OCInitStruct);// 7) 开启 ARR 与 CCR1 预装载(影子寄存器)—— 避免更新毛刺TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);TIM_ARRPreloadConfig(TIM2, ENABLE);// 8) 启动定时器TIM_Cmd(TIM2, ENABLE);
}// 设置占空比(0~100)
void PWM_SetCompare1(uint16_t compare)
{TIM_SetCompare1(TIM2, compare); // 图中就是改变“红线阈值”
}int main(void)
{uint8_t i;PWM_Init();while(1){// 占空比 0% -> 100%for(i=0; i<=100; i++){PWM_SetCompare1(i); // 修改 CCR1Delay_ms(1);        // 延时 1ms}// 占空比 100% -> 0%for(i=0; i<=100; i++){PWM_SetCompare1(100 - i);Delay_ms(1);}}
}
结构图模块代码位置作用说明
PSC 预分频器(粉色块左下)TIM_Prescaler = 720 - 1;把 72 MHz 系统时钟分频到 100 kHz,减慢计数速度
CNT/ARR 计数器 + 自动重装器(粉色块中,锯齿波)TIM_Period = 100 - 1; + TIM_CounterMode = TIM_CounterMode_Up;CNT 从 0 数到 99 后自动回零形成锯齿波;计数模式为向上计数
CCR 捕获/比较器(绿色“CCR”块)TIM_Pulse = 0; + TIM_SetCompare1()设置红线阈值,当 CNT < CCR 输出高电平,当 CNT ≥ CCR 输出低电平,占空比由 CCR 决定
输出模式控制器(绿色框“CNT<CCR时REF有效”)TIM_OCMode = TIM_OCMode_PWM1;选择 PWM1 模式:CNT < CCR 时 REF = 有效电平
极性选择(绿色“极性选择”块)TIM_OCPolarity = TIM_OCPolarity_High;REF 有效电平为高电平
输出使能(极性选择后到 GPIO 前)TIM_OutputState = TIM_OutputState_Enable; + TIM_Cmd(TIM2, ENABLE);打开通道输出,启动定时器,让波形真正到达引脚
GPIO 复用输出(GPIO 块)GPIO_Mode_AF_PP; + GPIO_PinRemapConfig() + GPIO_Remap_SWJ_JTAGDisable;配置 PA15 为复用推挽输出,将 TIM2_CH1 信号映射到 PA15 并关闭 JTAG 占用

5.运用场景

应用场景PWM作用
LED调光通过占空比控制亮度,肉眼平滑过渡
直流电机调速占空比决定电机转速,反应快
舵机控制用 PWM 脉宽来表示角度(常见 1–2ms 脉宽)
开关电源控制 MOSFET 导通时间来稳定输出电压
音频信号生成PWM 高频调制后滤波得到模拟波形
加热器温控占空比决定加热功率
通信协议红外遥控等通过 PWM 编码数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/93426.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/93426.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/93426.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCompass傻瓜式入门教程

文章目录1 我也许不是傻瓜&#xff0c;却只想做个傻瓜2 环境要求3 安装3.1 下载源码3.2 创建虚拟环境3.3 安装4 下载数据5 查看支持的模型和数据集6 评测6.1 指定模型路径6.2 指定配置文件6.2.1 评测本地qwen2.5模型6.2.1.1 查看opencompass支持的qwen2.5模型6.2.1.2 创建配置文…

【软件测试】电商购物项目-各个测试点整理(三)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、优惠券的测试点…

流处理、实时分析与RAG驱动的Python ETL框架:构建智能数据管道(上)

> **2025年某电商大促,每秒20万订单涌入系统**——他们的风控团队仅用**47毫秒**就识别出欺诈交易。背后的秘密武器,正是融合流处理、实时分析与RAG的下一代Python ETL框架。 ### 一、范式革命:从批处理到AI增强的ETL 4.0 #### 1.1 数据处理演进史 ```mermaid graph LR …

开源 Arkts 鸿蒙应用 开发(十五)自定义绘图控件--仪表盘

文章的目的为了记录使用Arkts 进行Harmony app 开发学习的经历。本职为嵌入式软件开发&#xff0c;公司安排开发app&#xff0c;临时学习&#xff0c;完成app的开发。开发流程和要点有些记忆模糊&#xff0c;赶紧记录&#xff0c;防止忘记。 相关链接&#xff1a; 开源 Arkts …

​​​​​​​中国工业企业专利及引用被引用数据说明

1319 中国工业企业专利及引用被引用数据说明数据简介专利近年发文趋势及主题分布今天数据皮皮侠团队为大家分享一份2023年12月25日最新更新的中国工业企业专利及引用被引用数据&#xff0c;供大家研究使用。数据来源原始数据来源于国家统计局&#xff0c;由皮皮侠团队整理计算。…

MySQL知识点(上)

MySQL知识点 一&#xff1a;MySQL概述 MySQL是一款开源的数据库软件&#xff0c;是一种关系型数据库管理系统&#xff08;ROBMS&#xff09;&#xff0c;也叫做表数据库管理系统 如果需要快速安全地处理大量的数据&#xff0c;则必须使用数据库管理系统&#xff1b;任何基于数据…

shell脚本实现sha256sum校验并拷贝校验通过的文件

#!/bin/bash# 目标目录 TARGET_DIR"/appdata/jn1m/versions/old/bin"# 校验文件 CHECKSUM_FILE"checksum.txt"# 检查目标目录是否存在 if [ ! -d "$TARGET_DIR" ]; thenecho "错误&#xff1a;目标目录 $TARGET_DIR 不存在"exit 1 fi#…

中小型泵站物联网智能控制系统解决方案:构建无人值守的自动化泵站体系

一、系统核心架构与功能设计1.物联网感知层设备互联&#xff1a;网关对接压力传感器、超声波液位计、智能电表、振动传感器等&#xff0c;实时采集水泵运行状态&#xff08;流量、压力、温度、振动&#xff09;、液位、水质&#xff08;pH值、浊度&#xff09;、能耗等关键参数…

网络通信---Axios

1、什么是 Axios&#xff1f; Axios​ 是一个基于 ​Promise​ 的 ​HTTP 客户端&#xff0c;用于浏览器和 Node.js 环境&#xff0c;用来发送 ​HTTP 请求&#xff08;如 GET、POST、PUT、DELETE 等&#xff09;​。 它常用于&#xff1a; 向后台 API 发送请求获取数据提交表…

Ubuntu 软件源版本不匹配导致的依赖冲突问题及解决方法

在使用 Ubuntu 系统的过程中&#xff0c;软件包管理是日常操作的重要部分。但有时我们会遇到各种依赖冲突问题&#xff0c;其中软件源与系统版本不匹配是常见且棘手的一种。本文就来详细分享一次因软件源版本不匹配引发的依赖冲突问题&#xff0c;以及具体的解决思路和流程。一…

思考:高速场景的行星轮混动效率如何理解

行星轮混动 E-CVT&#xff08;电子无级变速器&#xff09;是一种专为混合动力汽车设计的动力分配系统&#xff0c;其核心原理是通过行星齿轮组和电机的协同工作&#xff0c;实现动力分流与无级变速。 一、核心结构与组成 E-CVT的核心部件包括 行星齿轮组 和 双电机&#xff08;…

跨域及解决方案

跨域&#xff08;Cross-Origin&#xff09;是指浏览器在执行 JavaScript 的时候&#xff0c;因为同源策略&#xff08;Same-Origin Policy&#xff09;的限制&#xff0c;阻止了一个网页去请求不同源&#xff08;域名、端口、协议有任意一个不同&#xff09;的资源。 1. 什么是…

PCA降维全解析:从原理到实战

一文读懂PCA降维&#xff1a;原理、实现与可视化全解析​本文6000字&#xff0c;涵盖PCA核心原理、数学推导、代码实战及高频面试题&#xff0c;建议收藏阅读​一、为什么需要降维&#xff1f;数据爆炸时代的生存法则当数据集的特征维度激增&#xff08;如基因数据、推荐系统用…

Kafka工作机制深度解析:Broker、Partition 与消费者组协作原理

&#x1f42f; Kafka工作机制深度解析&#xff1a;Broker、Partition 与消费者组协作原理 &#x1f3c1; 前言 Kafka 已成为互联网公司流式数据处理的事实标准&#xff0c;广泛应用于日志收集、实时计算、事件驱动架构等场景。 很多开发者会用 Kafka&#xff0c;但不了解它底…

深入解析live555:开源流媒体框架的技术原理与应用实践

引言&#xff1a;流媒体领域的"老兵"与技术基石 在实时音视频传输技术的发展历程中&#xff0c;live555作为一款诞生于1990年代末的开源项目&#xff0c;至今仍在流媒体服务器、嵌入式设备和安防监控等领域发挥着不可替代的作用。它由Live Networks公司开发并维护&a…

EN55014家用电器、电动工具和类似设备的电磁兼容

一、EN 55014标准定义与属性&#xff1f;EN 55014 是针对家用电器、电动工具及类似设备的电磁兼容&#xff08;EMC&#xff09;标准&#xff0c;主要规定了这类产品在电磁骚扰发射&#xff08;避免干扰其他设备&#xff09;和抗扰度&#xff08;抵抗其他设备干扰&#xff09;方…

python自学笔记9 Seaborn可视化

Seaborn&#xff1a;统计可视化利器 作为基于 Matplotlib 的高级绘图库&#xff0c;有一下功能&#xff1a;一元特征数据 直方图 import matplotlib.pyplot as plt import pandas as pd import seaborn as sns # import os # # 如果文件夹不存在&#xff0c;创建文件夹 # if…

kafka 消费者组的概念是什么?它是如何实现消息的点对点和发布/订阅模式?

Kafka 消费者组&#xff08;Consumer Group&#xff09;是 Kafka 架构中的核心概念&#xff0c;它是一组共同协作来消费一个或多个主题&#xff08;Topic&#xff09;数据的消费者应用的集合。 通过简单地为多个消费者实例配置相同的 group.id&#xff0c;它们就组成了一个消费…

C#文件复制异常深度剖析:解决“未能找到文件“之谜

一个看似简单的文件操作问题 在C#开发中&#xff0c;文件操作是基础中的基础&#xff0c;但有时最基础的File.Copy()方法也会抛出令人困惑的异常。最近我遇到了这样一个问题&#xff1a; File.Copy(sourceFile, targetFilePath);当targetFilePath设置为D:\25Q1\MR3.6.6.1_C1.2.…

OpenCV Python——图像查找(特征匹配 + 单应性矩阵)

1 图像查找&#xff08;单应性矩阵&#xff09;2 单应性矩阵 应用举例3 单应性矩阵 代码示例P87 111 图像查找&#xff08;单应性矩阵&#xff09; 特征匹配作为输入&#xff0c;获得单应性矩阵 点X在img1和img2中的成像分别为x,x 图中H即为单应性矩阵 2 单应性矩阵 应用…