1 PWM 简介
PWM 是 Pulse Width Modulation 的缩写,中文意思就是脉冲宽度调制,简称脉宽调制。
PWM 是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM 信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断 (OFF)的重复脉冲序列被加到模拟负载上去的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。只要带宽足够,任何模拟值都可以使用 PWM 进行编码。

从图中可以看到,上图 a 是一个正弦波即模拟信号,b 是一个数字脉冲波形即数字信号。我们知道在计算机系统中只能识别是 1 和 0,对于 F28335 芯片,要么输出高电平(3.3V),要么输出低电平(0),假如要输出 1.5V 的电压,那么就必须通过相应的处理,比如本章所要讲解的 PWM 输出,其实从上图也可以看到,只要保证数字信号脉宽足够就可以使用 PWM 进行编码,从而输出 1.5V的电压。
PWM 波形可分为等幅 PWM 波和不等幅 PWM 波两种,微控制器输出的电平一般都是确定的,所以一般调整微控制器输出矩形脉冲的占空比,就可以输出等幅不等宽的 PWM 波,微控制器输出的 PWM 波功率有限,主要用来驱动功率开关管。通过对功率开关器件的开关控制,可以输出更大功率、更多形状的 PWM 波形,将功率开关器件的开关拓扑逻辑组合变化,就可以输出不等幅即多电平的大功率 PWM波形。PWM 就像大功率 DA 转换器一样,将数字信号转换为模拟信号,只是 PWM是用调制脉宽的方法将数字信号等效替代模拟信号。也可以认为 PWM 电路就是一类特殊的 D/A 电路。
PWM 控制一般包括两部分电路,一部分是功率开关管组成的功率电路,另一部分是由微控制器组成的驱动开关管的驱动电路。微控制器产生的单周期 PWM驱动信号本身很简单,主要包括 4 个要素,周期、脉宽、脉冲相位、脉冲个数,但是每个周期的脉冲波形的宽度会变化,有时对脉冲的具体相位也有要求,脉冲宽度如何具体调制,这就要根据具体的控制场合以及功率电路进行算法研究,详情可参考 PWM 控制相关技术,我们主要介绍 F28335 如何产生最初的这个脉冲波形,并且每个周期的脉冲波形宽度以及具体相位都是可以配置和调制的。
目前 PWM 控制技术应用已极为广泛,在电机拖动、电机控制、整流、逆变、有源电力滤波(APF)、静止无功发生器(SVG)、统一潮流控制器(UPFC)、超导储能(SMES)、LED 调光、开关电源灯众多领域都有很重要应用。
2 F28335 的 ePWM 介绍
F28335 的ePWM 模块是个加强模块,与F2812 的PWM 模块有较大不同,在F2812中,PWM 模块采用事件管理器控制,与 eCAP 和 eQEP 共享定时器信号,而 F28335中每个 ePWM 模块都是一个独立的小模块,这样的体系结构更方便我们使用与理解。每个 ePWM 模块由两路 ePWM 输出组成,分别为 ePWMxA 和 ePWMxB,这一对 PWM输出,可以配置成两路独立的单边沿 PWM 输出,或者两路独立的但互相相对称的双边沿 PWM 输出,或者一对双边沿非对称的 PWM 输出,共有 6 对这样的 ePWM 模块,因为每对 PWM 模块中的两个 PWM 输出均可以单独使用,所以也可以认为有 12 路单路 ePWM,除此之外还有 6 个 APWM,这 6 个 APWM 通过== CAP 模块==扩展配置,可以独立使用,所以 F28335 最多可以有 18 路 PWM 输出。每一组 ePWM 模块都包含以下 7 个模块:时基模块 TB、计数比较模块 CC、动作模块 AQ、死区产生模块 DB、PWM 斩波模块 PC、错误联防模块 TZ、时间触发模块 ET,如下所示:
2.1 ePWM模块的基本结构
"每个ePWM模块由两路ePWM输出组成,分别为ePWMxA和ePWMxB"
┌─────────────────────────────────────┐
│ ePWM1 模块 │
│ ┌─────────┐ ┌─────────┐ │
│ │ ePWM1A │ │ ePWM1B │ │
│ │ 输出 │ │ 输出 │ │
│ └─────────┘ └─────────┘ │
│ ↑ ↑ │
│ 可以独立配置,也可以配对使用 │
└─────────────────────────────────────┘
关键:每个ePWM模块有两路输出(A和B),它们共享同一个时基(计数器),但可以灵活配置。
2.2 两路PWM输出的配置方式(重点)
原文描述了三种配置模式:
模式1:两路独立的单边沿PWM
ePWM1A: ┌─────┐ ┌─────┐
│ │ │ │
─────┘ └──────┘ └─────
ePWM1B: ┌─────┐ ┌─────┐
│ │ │ │
─────────┘ └──────┘ └─
- 两路PWM 频率可以不同
- 每路独立控制自己的占空比
- 适合控制两个独立的设备(如两个LED、两个风扇)
- 每个通道只在计数器归零时更新
- 应用场景:两个独立的负载控制,不需要互补关系。
模式2:两路对称的双边沿PWM(互补带死区)
- A和B波形完全互补(一个高另一个低)
- 中间插入死区时间(同时为低,防止直通)
- 这是电机控制最常用的模式用于驱动IGBT的上下桥臂
上下桥臂是什么?
在变频器驱动电机时,用到的是一种叫H桥 或三相逆变桥的电路。以其中一相(比如U相)为例:
┌─────────┐
│ +VBUS │ (直流母线正极,比如+540V)
│ │
│ ┌┴┐
│ │ │ ← 上桥臂功率管(Q1)
│ └┬┘
│ │
│ ┼────→ 接电机U相绕组
│ │
│ ┌┴┐
│ │ │ ← 下桥臂功率管(Q2)
│ └┬┘
│ │
└────── ──┼──→ GND (直流母线负极)
|
- 上桥臂:连接直流母线正极(高压)的功率管。它导通时,电机绕组被接到正高压。
- 下桥臂:连接直流母线负极(地)的功率管。它导通时,电机绕组被接到地(0V)。
为什么叫桥臂? 因为整个结构像一个桥,两个功率管像桥的两个支柱,电机绕组接在中间。一相需要两个功率管,三相就需要6个功率管。
功率管是什么?
常见的功率管有:
- MOSFET(低压、高频)
- IGBT(高压、大电流,变频器中最常用)
可以把它们想象成电子开关:
- 给控制极(栅极)加高电压 → 开关导通(像开关闭合)
- 给控制极加0V → 开关关断(像开关断开)
关键特性:导通时电阻极小(几毫欧到几十毫欧),相当于一根导线。
为什么上下两个功率管不能同时导通?
正常工作时的情况:
- 上管导通(Q1 ON)、下管关断(Q2 OFF)→ 电机绕组接正高压,电流从正极流向电机
- 上管关断(Q1 OFF)、下管导通(Q2 ON)→ 电机绕组接地,电流从电机流向地
同时导通时(直通/ Shoot-Through):
+540V ──┬── Q1导通 ──┐
│ │
│ 电机绕组
│ │
│ Q2导通
GND ──┴────────────┘
相当于用一根极低电阻的导线把+540V和GND直接短路!会产生:
- 巨大的电流(上千安培),远超功率管承受能力
- 瞬间高温(功率管在几微秒内烧毁、炸裂)
- 可能引发火灾或损坏整个驱动电路
死区时间是什么?
既然上下管不能同时导通,那问题来了:切换时如果上管先关、下管再开,中间是不是有一段两个管都关断的时间?
是的!这个时间就叫死区时间(Dead Time)。
上桥臂驱动 ──┐ ┌──────
│ │
└─────┘ ← 高电平=导通
下桥臂驱动: ┌─────┐
─────┘ └──────
↑死区↑
(两个管都关断)
死区时间的必要性:
功率管不是瞬间开关的:
- 从收到关断信号到真正关断 → 需要关断延迟(几百纳秒)
- 从收到导通信号到真正导通 → 需要开通延迟(几百纳秒)
如果没有死区时间:
- 上管收到关断指令,但还没完全关断
- 下管立即收到开通指令,已经开始导通
- 短暂但危险的重叠导通 → 上下管同时导通 → 短路炸机!
设置死区时间后:
- 上管关断后,等待足够长时间(比如2微秒),确保已完全关断
- 再让下管导通
死区时间在代码中
之前看到的代码:
c
gDeadBand.DeadBand = gDeadBandTable[12]; // 初始化死区时间为4.8us
这行代码就是设置死区时间为4.8微秒 。这4.8us内,上下桥臂同时关闭,确保不会发生短路。
c
CalDeadBandComp(); // 计算死区补偿大小
死区时间虽然能防止短路,但也会带来波形畸变 (输出电压变低、谐波变大)。CalDeadBandComp()就是用来软件补偿这个畸变的,这是高端变频器才有的功能。
死区时间过长过短的问题
- 过短:可能不能完全覆盖功率管的开关延迟,仍有直通风险
- 过长:输出电压降低、波形畸变更严重、电机效率下降
典型值:几百纳秒到几微秒,取决于功率管的型号。IGBT通常需要2-5微秒,超快MOSFET可能只需要200纳秒。
模式3:两路双边沿非对称PWM
- 两路有相位差
- 用于特定的功率变换拓扑(如移相全桥)
独立单边沿模式和双边沿不对称模式的区别
区别在于信号是"单边沿控制"还是"双边沿控制",以及它们与计数器的关系。
核心区别总结
- 独立单边沿模式 :两路信号完全独立。每路信号只由单个比较事件 决定其其中一边沿(通常是周期开始后多久变低),另一个边沿是固定的。
- 双边沿不对称模式 :两路信号也完全独立。但每路信号的上升沿和下降沿都由独立的比较事件决定,因此可以产生更复杂、中心可变的波形。它们彼此独立,但各自又是"双边沿"的。
核心区别:单边沿 vs 双边沿
这是根本的区别,决定了波形的形态和精度。
1. 单边沿 PWM(如独立单边沿模式)
- 工作原理 :波形的一个边沿(比如上升沿)是固定的,通常与周期的开始(计数器=0)对齐。另一个边沿(下降沿)则由比较寄存器(CMPA/B)的值来控制,可以在0到周期之间移动。
- 波形特点 :所有脉冲的上升沿或下降沿是对齐的。通常用于控制直流电机或简单调光。
- 固定上升沿模式:
ON时间可变,但脉冲总是从周期起点开始。 - 固定下降沿模式:
OFF时间可变,脉冲总是在周期结束前结束。
- 固定上升沿模式:
2. 双边沿 PWM(如互补对称和非对称模式)
- 工作原理 :波形的上升沿和下降沿都是可控的 。这意味着你可以独立控制脉冲的开启相位 和关闭相位。
- 波形特点:脉冲可以在周期中的任意位置开始和结束,不是必须对齐周期起点或终点。这需要至少两个比较事件来决定这两个边沿。
通过波形图看区别
假设我们有一个周期为 100 的计数器,想要产生一个占空比为 40%(即高电平长度为 40)的 PWM 波。
| 特征 | 独立单边沿 (固定上升沿) | 双边沿非对称 (中心或移相) |
|---|---|---|
| 波形图 | ON---OFF---ON---OFF ▲ ▲ ▲ 固定对齐 |
-----ON---OFF---ON ▲ ▲ ▲ 位置可变 |
| 开启相位 | 固定,始终在周期起点(或中点) | 可调,可以在周期中任意位置开始 |
| 关闭相位 | 可调 ,在 CMPA 处关闭 |
可调 ,在 CMPB 处关闭 |
| 所需比较器 | 1个 (CMPA) | 2个 (CMPA, CMPB) |
| 产生的波形 | 脉冲的左(或右)边缘对齐 | 脉冲可以"悬浮"在周期中间 |
具体波形示例(周期 = 100,高电平时间 = 40):
-
单边沿(固定上升沿):从 0 到 40 是高电平(共 40),从 40 到 100 是低电平。
-
双边沿(非对称):从 0 到 30 是低电平,从 30 到 70 是高电平(共 40),从 70 到 100 是低电平。
什么时候需要"双边沿非对称"?
既然单边沿可以实现占空比控制,为什么还需要更复杂的双边沿?主要原因有:
- 控制精度与谐波:在电机控制或数字电源中,双边沿PWM(特别是中心对齐模式)产生的波形对称性更好,谐波含量更低,对电机和滤波器更友好。
- 实现移相控制:很多高效电源拓扑(如移相全桥)需要两路波形完全相同,但相位可移。这必须通过双边沿控制来实现:A路的下降沿和B路的上升沿需要精确配合。
- 实现复杂调制:如空间矢量PWM(SVPWM),需要产生非对称的PWM波形来合成旋转磁场,这必须用到ePWM模块的双边沿控制能力。
2.3 APWM(辅助PWM)
"除此之外还有6个APWM,这6个APWM通过CAP模块扩展配置,可以独立使用,所以F28335最多可以有18路PWM输出"
- APWM = 通过捕获模块(eCAP)配置成的PWM输出模式
- 当eCAP模块不用于捕获时,可以当作一个简单的PWM发生器
- F28335有6个eCAP模块,所以可扩展出6路APWM
总数 :12路ePWM + 6路APWM = 最多18路PWM输出
7个子模块的作用(与变频器的关系)
| 模块 | 缩写 | 作用 | 变频器中用来 |
|---|---|---|---|
| 时基模块 | TB | 设置PWM周期、计数模式 | 决定载波频率(如8kHz) |
| 计数比较模块 | CC | 设置比较值,确定占空比 | 控制电机电压大小 |
| 动作模块 | AQ | 决定何时输出高/低 | 生成基本的PWM波形 |
| 死区模块 | DB | 插入死区时间 | 防止IGBT上下桥臂直通 |
| PWM斩波模块 | PC | 高频载波调制(较少用) | 特殊应用 |
| 错误联防模块 | TZ | 故障时强制PWM输出安全状态 | 过流时立即封锁输出 |
| 事件触发模块 | ET | 触发ADC或产生中断 | 触发ADC采样、产生PWM中断 |
2.4 代码中的对应关系
代码中的PWM中断:
c
interrupt void EPWM1_zero_isr(void) // ePWM1的下溢中断
这里的"下溢中断"就是**ET(事件触发模块)**配置的------当计数器归零时触发中断。
c
EPwm1Regs.TZCLR.bit.OST = 1; // 清除TZ故障标志
这里的TZ就是错误联防模块,当过流发生时,硬件自动封锁PWM输出,代码中清除标志恢复输出。
2.5 小结
| 问题 | 答案 |
|---|---|
| 一个ePWM模块有几路输出? | 2路(A和B) |
| 电机控制常用哪种模式? | 互补带死区模式(防止IGBT直通) |
| F28335最多多少路PWM? | 18路(12路ePWM + 6路APWM) |
| ePWM有哪7个模块? | TB、CC、AQ、DB、PC、TZ、ET |
| 哪个模块负责故障保护? | TZ(错误联防) |
| 哪个模块负责触发中断? | ET(事件触发) |
| 哪个模块防止上下桥短路? | DB(死区模块) |
3 时基模块 TB
3.1 时基模块的功能
用户通过对时基模块的设定和配置可实现以下功能:
①确定 ePWM 时基模块的频率或者周期,进一步确定了事件发生的频率。主要是通过配置 PWM 时基计数器(TBCTR)来标定与系统时钟(SYSCLKOUT)有关的时基时钟的频率或周期。
②管理 ePWM 模块之间的同步性。
③维护 ePWM 与其他 ePWM 模块间的相位关系。
④设置时基计数器的计数模块。可以工作在向上计数(递增计数)、向下计数(递减计数)、向上-向下计数模式(先递增后递减计数)。
⑤产生下列事件:
--CTR=PRD:时基计数器的值与周期寄存器的值相同(TBCTR=TBPRD)。
--CTR=ZERO:时基计数器的值为 0(TBCTR=0x0000)。
时基计数器按照指定模式进行计数,递增时会达到与周期寄存器的值一致,递减时则会减到最小值 0。
⑥配置时基模块的时钟基准,对系统时钟 SYSCLKOUT 进行分频可以得到时基时钟,通过合理分频系统时钟,计数的时候可以工作在相对较低的频率。
3.2 时基模块的关键信号和寄存器
下面我们从时基模块内部结构图来了解里面的关键信号,时基模块内部结构图如下所示:
①ePWMxSYNCI:时基同步信号输入。输入脉冲用于时基计数器与之前的 ePWM模块同步,每个 ePWM 模块可以通过软件配置为使用或者忽略此信号。对于第一个ePWM 模块,这个信号从外部引脚或得。随后的模块的同步信号可以由其他 ePWM模块传递过来。例如第 2 个模块的同步信号可以从第 1 个模块的同步信号输出或
得,第 3 个模块由第 2 个模块产生,以此类推。
②ePWMxSYNCO:时基同步信号输出。输出脉冲用于随后的 ePWM 的时基计数器同步。ePWM 模块产生该信号来源于下列 3 个事件源中的一件。
--ePWMxSYNCI(同步输入脉冲)。
--CTR=ZERO,时基计数器等于 0(TBCTR=0X0000)。
--CTR=CMPB,时基计数器等于比较寄存器。
③CTR=PRD,时基计数器等于指定周期值。无论什么时候当时基计数器的值与激活的周期寄存器(相对于影子寄存器而言)的值相等的时候,就会产生此信号。
④CTR=ZERO,时基计数器等于 0。无论什么时候当时基计数器的值为 0 的时候,会产生此信号。
⑤CTR=CMPB,时基计数器等于比较寄存器。时基计数器的值等于激活的比较寄存器 B 的时候,会产生此信号。该信号由比较计数器模块产生,用于同步输出逻辑。
⑥CTR_dir:时基计数器方向。表明时基计数器的计数方向,当高电平时,计数器向上计数,低电平时则向下计数。
⑦CTR_max:时基计数器的值为最大值。当时基计数器到最大值时会产生此信号。该信号用作状态指示。
⑧TBCLK:时基时钟信号。这个信号来源于预分频的系统时钟信号,用于所有的 ePWM 模块。该信号确定了时基计数器增减的速率。
3.3 ePWM 周期和频率的计算
ePWM 的频率是由时基周期寄存器值(TBPRD)和时基计数器的计数模式(TBCTRL)共同决定的。时基计数器的计数模式有向上计数(递增)模式、向下计数(递减)模式、向上-向下计数(先递增后递减)模式。下边就以周期寄存器设置为 4(TBPRD=4)举例说明。
①向上-向下计数模式(先递增后递减)
在此模式下,时基计数器先从 0 开始向上计数(递增)直到递增到周期寄存器的值 4,然后再由 4 向下计数(递减)直到减到 0,再重复以上动作,如下图所示:

在此模式下,随着同步信号的到来,时基模块的输出波形有两种情形,需要通过设置相位方向 TBCTL[PHSDIR]来确定。如果 ==TBCTL[PHSDIR]=0 ==时,那么当同步信号到来时,对应的输出波形如下图所示:

如果 TBCTL[PHSDIR]=1 时,那么当同步信号到来时,对应的输出波形如下图

TBPRD:时基周期寄存器值
TBPHS:相位寄存器
ePWMxSYNCI:同步信号脉冲
CTR_dir:时基计数器方向。表明时基计数器的计数方向,当高电平时,计数器向上计数,低电平时则向下计数。
CTR=ZERO,时基计数器等于 0。
CTR=PRD,时基计数器等于指定周期值。
CTR_max:时基计数器的值为最大值。当时基计数器到最大值时会产生此信号。该信号用作状态指示。
同步信号来临时,不管目前时基计数器已经到了什么值,都将置位为相位寄存器的值,这个作用可以协调各路 ePWM 模块间的固定相位差,对于先递增后递减模式,同一相位寄存器的值,同时对应着两个段,例如相位值 3,既出现在递增的过程中,又出现在递减的过程中,通过 TBCTL 寄存器的 PHSDIR 位的设置,就可以确定究竟是递增过程还是递减过程中的 3。TBCTL[PHSDIR]=1 表示为相位寄存器的值是递增过程中的值,TBCTL[PHSDIR]=0 时表示为相位寄存器的值是递减过程中的值。当时基计数器的值变化到特定值的时候,特定事件就会产生,特定信号就会发出。
①ePWMxSYNCI:同步信号脉冲:当同步信号输入脉冲到来的时候,时基计数器就会在时基模块时钟 TBCLK 的下一个边沿自动加载TBPHS 的值。
②软件强制同步信号脉冲:向 TBCTL 的 SWFYNC 位写入 1 后,时基计数器也会在时基模块时钟 TBCLK 的下一个边沿自动加载 TBPHS 的值。
这个特点可以使其中一个 PWM 的时基与其他的 PWM 模块的时基同步,清除 TBCTL[PHSEN]位,可以配置 PWM 忽略同步输入信号。但是同步信号仍然可以通过第一个 PWM 产生,经过 ePWMxSYNCO 传递给下面的 PWM 模块(ePWM2~ePWMx)。
TBCLKSYNC 位可以被用来同步在一个设备上所有使能的 PWM 模块。该位是系统时钟使能寄存器的一部分。当 TBCLKSYNC=0 时,ePWM 模块时基时钟停止(默认情况),TBCLKSYNC=1 时,所有的 ePWM 模块在 TBCLK 的时钟上升沿到来时同时被启动,为了更好的同步各 ePWM 模块的 TBCLK,每个 ePWM 模块的预分频系统时钟的时基时钟 TBCTL 的寄存器都要设置为相同的值。设置 ePWM 时钟的操作步骤如下:
①使能各 ePWM 模块的时钟。
②设置 TBCLKSYNC=0,停止所有已使能的 ePWM 模块的时基时钟。
③配置预分频值与 ePWM 工作模式。
④设置 TBCLKSYNC=1,启动时基时钟。
②向上计数模式(递增)
在此模式下,时基计数器从 0 开始向上计数,直到递增到周期寄存器的值后,时基计数器会自动复位到 0,重复以上动作,如下图所示:

在此模式下,随着同步信号的到来,时基模块的输出波形如下所示:

③向下计数模式(递减)
在此模式下,时基计数器首先加载周期寄存器的值,然后开始递减,直到减到 0 时,自动在加载周期寄存器的值,重复以上动作,如下图所示:

在此模式下,随着同步信号的到来,时基模块的输出波形如下所示:

3.4 影子寄存器
在时基模块中有个周期影子寄存器。影子寄存器允许寄存器可以随硬件进行同步更新。在 ePWM 模块中多处出现了影子寄存器,其意义都差不多。影子寄存器是相对于活动寄存器而言的。Active Register(活动寄存器)也就是被激活的寄存器,在工作的寄存器,控制着硬件,可以响应由硬件引起的相关事件。 Shadow Register(影子寄存器)影子寄存器缓存器相当于为活动寄存器提供了一个暂时的存放地址,不能直接影响硬件的控制,当系统运行到一定的时候,影子寄存器的值会传递给活动寄存器,这样可以防止由于软件配置寄存器与硬件不同步时而出现的系统崩溃或一些奇怪的故障。
影子寄存器与活动寄存器的内存地址映射值是一致的,写或者读哪一个寄存器,主要取决于 TBCTL[PRDLD]位。该位可以对 TBPRD 的影子寄存器进行使能或者禁止。
①时基周期影子寄存器模式
当== TBCTL[PRDLD]=0== 时,TBPRD 的影子寄存器是使能的,读写 TBPRD 的映射地址的内容时,会读写影子寄存器。时基模块计数器值为 0 时(TBCTR=0x0000),影子寄存器的值传递给活动寄存器。默认情况下,影子寄存器都是有效的。
②时基周期立即加载模式
当== TBCTL[PRDLD]=1 时,为立即加载模式,读写时基周期寄存器对应的地址时,都是直接到活动寄存器==。

4 计数比较模块 CC
计数器比较模块是以时基计数器的值作为输入,与比较寄存器 CMPA 和比较寄存器 CMPB 不断进行比较,当时基计数器的值等于其中之一时,就会产生相应的事件。
①产生比较事件具体取决于编程时是采用寄存器还是寄存器 B:
--CTR=CMPA:时基计数器的值与比较寄存器 A 的值相等。
--CTR=CMPB:时基计数器的值与比较寄存器 B 的值相等。
②动作模块 AC 恰当配置后可以控制 PWM 的占空比。
③采用影子寄存器来更新比较值可以有效防止在PWM 周期内出现故障以及毛刺。
(1) 计数器比较模块 CC 的功能
计数器比较模块可以产生两个独立的比较事件,对于向上(递增)或者向下
(递减)计数模式来说,在一个 PWM 周期内,比较事件只发生一次。而对于向上向下(先递增后递减)计数器模式来说,如果比较寄存器的值在 0-TBPRD 之间,在一个 PWM 周期内,比较事件就会发生两次。这些事件都会直接影响动作模块。
(2) 计数器比较模块 CC 的关键信号与寄存器
①CTR=CMPA:时基计数器的值与 CMPA 的值相同时,PWM 可以根据 AQ 动作。
②CTR=CMPB:时基计数器的值与 CMPB 的值相同时,PWM 可以根据 AQ 动作。
③CTR=PRD:时基计数器的值与周期寄存器的值相同,PWM 可以根据 AQ 动作。 CMPA 与 CMPB 可以根据相关影子寄存器的值进行更新。
④CTR=ZERO:时基计数器的值递减到 0 时,PWM 可以根据 AQ 动作。CMPA 与 CMPB 可以根据相关影子寄存器的值进行更新。

5 动作限定模块 AQ
(1) 动作限定模块功能
①动作模块根据下列事件产生动作(置高、拉低、翻转)。
--CTR=PRD:时基模块来的信号,时基计数器的值等于周期寄存器的值。
--CTR=ZERO:时基模块来的信号,时基计数器的值等于 0。
--CTR=CMPA:计数比较模块来的信号,时基计数器的值等于比较寄存器 A 的值。
--CTR=CMPB:计数比较模块来的信号,时基计数器的值等于比较寄存器 B 值。
②管理以上事件发生后 PWM 的输出极性。
③针对时基计数器递增或者递减时提供独立的动作控制。
(2) 动作限定模块关键信号与寄存器
动作限定模块是基于事件驱动的,下图展示了动作限定模块的输入逻辑和输出动作。



ePWMA 和 ePWMB 输出的几种操作方式如下:
①置高(SET HIGH):使 ePWMA 和 ePWMB 输出高电平。
②置低(CLEAR LOW):使 ePWMA 和 ePWMB 输出低电平。
③取反(TOOGLE):当 ePWMA 或者 ePWMB 当前状态是低电平时,那么下一时刻就是高电平;当 ePWMA 或者 ePWMB 当前状态是高电平时,那么下一时刻就是低电平。
④不动作(DO NOTHING):不对 ePWM 输出做任何改变。但是还是可以产生相应的事件触发信号以及相关中断。
(3) 动作限定模块事件优先级
在同一时刻,动作模块可能会收到两个及两个以上的事件时,动作模块如何执行呢?在这种情况下,就需要硬件提供事件优先级。优先级 1 最高,优先级 7最低。根据不同的计数模式,优先级定义不同。向上向下(先增后减)计数模式的优先级定义如下:

软件强制优先级最高,最低是计数器在增的时候,与比较寄存器 A 匹配事件。向上计数(递增)模式的优先级如下,此时的计数方向始终是递增的,所以不使用递减事件。

最高同样是软件强制,最低是计数器等于 0 事件。
向下计数(递减)模式的优先级如下,此时的计数方向始终是递减的,所以不使用递增事件。

最高同样是软件强制,最低是计数器等于周期寄存器的值匹配事件。
(4) 动作限定模块一般配置条件下的输出波形
PWM 波形在通过 AQ 模块后是什么样的呢?需要根据时基计数器的工作模式来分别讨论。上下计数模式(先增后减)的波形图如下所示:

在这个模式下占空比可以从 0-100%变化。当计数器递增到 CMPA 的值时,PWM输出电平经 AQ 模块被置高,同样,当计数器递减到 CMPA 时,PWM 输出电平被置低。若 CMPA=0 时,则 PWM 信号一直输出低电平,占空比为 0%。当 CMPA=TBPRD时,PWM 信号输出高电平,占空比为 100%。
实际使用中,如果装载 CMPA 或者 CMPB 为 0 时,那么设置 CMPA 或者 CMPB 的值要大于或等于 1,如果装载 CMPA 或 CMPB 为周期寄存器的值时,那么设置 CMPA或 CMPB 的值要小于或等于 TBPRD-1,这就意味着每个 PWM 周期至少有一个时基时钟周期的脉冲,在系统角度来看,这个周期很短,所以可以忽略。
具体波形的调整与配置程序如下:
【例①】单边非对称波形(ePWMxA 和 ePWMxB 独立调制,高电平有效)
如下所示:

注意:
①PWM 周期=(TBPRD+1)*T(TBCLK)
②CMPA 决定 ePWMxA 的占空比,CMPB 决定 ePWMxB 占空比。下面是该输出波形相关配置代码:
c
EPwm6Regs.TBPRD = tbprd;//设定 PWM 周期为 tbprd+1 个 TBCLK 时钟周期 EPwm6Regs.CMPA.half.CMPA = 350;//比较器 A 的值为 350 EPwm6Regs.CMPB = 200;//比较器 B 的值为 200 EPwm6Regs.TBPHS.half.TBPHS = 0;//相位寄存器清零
EPwm6Regs.TBCTR = 0x0000;//时基计数器清零 EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;//设定为增计数模式 EPwm6Regs.TBCTL.bit.PHSEN = TB_DISABLE;//禁止相位控制 EPwm6Regs.TBCTL.bit.PRDLD = TB_SHADOW;//TBPRD 寄存器采用影子寄存器
模式
EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;//禁止同步信号 EPwm6Regs.TBCTL.bit.HSPCLKDIV=TB_DIV1;//设定TBCLK=SYSCLK 时基时钟=
系统时钟
EPwm6Regs.TBCTL.bit.CLKDIV=TB_DIV1;
EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;//设定 CMPA 为影子寄存器模式
EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;//在 CTR=Zero 时装载 EPwm6Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
EPwm6Regs.AQCTLA.bit.ZRO = AQ_SET;//CTR=ZERO 时,将 ePWM6A 置高 EPwm6Regs.AQCTLA.bit.CAU = AQ_CLEAR;//CTR=CAU 时,将 ePWM6A 置低 EPwm6Regs.AQCTLB.bit.ZRO = AQ_SET;//CTR=ZERO 时,将 ePWM6B 置高 EPwm6Regs.AQCTLB.bit.CBU = AQ_CLEAR;//CTR=CAU 时,将 ePWM6B 置低
EPwm6Regs.CMPA.half.CMPA = Duty1A;//调整 ePWM6A 的占空比 EPwm6Regs.CMPB = Duty1B;//调整 ePWM6B 的占空比
这段代码完整配置了ePWM6模块,使其输出两路独立的单边沿PWM波形 (高电平有效)。这是ePWM配置的完整示例,包含了时基、比较、动作等多个模块的配置。
代码分段解释
第1部分:时基模块配置(决定周期和频率)
c
EPwm6Regs.TBPRD = tbprd; // 周期值
EPwm6Regs.TBPHS.half.TBPHS = 0; // 相位值=0
EPwm6Regs.TBCTR = 0x0000; // 计数器清零
EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // 向上计数模式
EPwm6Regs.TBCTL.bit.PHSEN = TB_DISABLE; // 禁止相位加载
EPwm6Regs.TBCTL.bit.PRDLD = TB_SHADOW; // 周期寄存器用阴影模式
EPwm6Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; // 禁止同步输出
EPwm6Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // 不分频
EPwm6Regs.TBCTL.bit.CLKDIV = TB_DIV1; // 不分频
| 配置 | 含义 |
|---|---|
| 向上计数 | 从0增加到TBPRD,然后回0 |
| 周期寄存器阴影模式 | TBPRD在周期开始时更新(平滑调频) |
| 不分频 | TBCLK = 系统时钟(最高精度) |
周期公式 :PWM周期 = (TBPRD + 1) / TBCLK频率
第2部分:比较模块配置(决定占空比更新方式)
c
EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // CMPA阴影模式
EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; // CMPB阴影模式
EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // 计数器=0时加载新CMPA
EPwm6Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // 计数器=0时加载新CMPB
| 配置 | 含义 |
|---|---|
| 阴影模式 | 写入的CMP值不立即生效,等到加载时刻才生效 |
| 加载时刻=CTR_ZERO | 每个周期开始时加载新的比较值 |
效果 :占空比逐周期平滑变化,不会在周期中间突变。
第3部分:动作模块配置(核心!决定波形形状)
c
// ePWM6A 的动作配置
EPwm6Regs.AQCTLA.bit.ZRO = AQ_SET; // 计数器=0时:输出高电平
EPwm6Regs.AQCTLA.bit.CAU = AQ_CLEAR; // 计数器=向上比较A时:输出低电平
// ePWM6B 的动作配置
EPwm6Regs.AQCTLB.bit.ZRO = AQ_SET; // 计数器=0时:输出高电平
EPwm6Regs.AQCTLB.bit.CBU = AQ_CLEAR; // 计数器=向上比较B时:输出低电平
这就是"单边沿"的由来:
计数器: 0 ───────────────────────────→ tbprd
│
动作A: 置高 ──────────────────────→ 清低
│ ↑
│ 在CMPA处变低
│
动作B: 置高 ───────────→ 清低
↑
在CMPB处变低
关键 :只有下降沿(清低)是可调的,上升沿(置高)固定在0点 → 所以叫单边沿PWM。
第4部分:初始比较值设置
c
EPwm6Regs.CMPA.half.CMPA = 350; // 初始占空比(A通道)
EPwm6Regs.CMPB = 200; // 初始占空比(B通道)
这两个值决定了初始的占空比:
- A通道高电平时间 = 350个TBCLK周期
- B通道高电平时间 = 200个TBCLK周期
第5部分:运行时动态调整占空比
c
EPwm6Regs.CMPA.half.CMPA = Duty1A; // 运行时更新A占空比
EPwm6Regs.CMPB = Duty1B; // 运行时更新B占空比
关键 :由于前面配置了阴影模式和周期加载,这里写入的新值不会立即生效,而是在下一个周期开始时才生效,保证波形平滑。
【例②】向上计数(递增)单边不对称脉冲波形(ePWMA、ePWMB 独立调制)
如下图所示:

与例①程序不一样的地方只在初始化最后部分,如下:
c
EPwm6Regs.AQCTLA.bit.PRD = AQ_CLEAR;//CTR=PRD 时,将 ePWM6A 置低
EPwm6Regs.AQCTLA.bit.CAU = AQ_SET;//CTR=CAU 时,将 ePWM6A 置高
EPwm6Regs.AQCTLB.bit.PRD = AQ_CLEAR;//CTR=PRD 时,将 ePWM6B 置低
EPwm6Regs.AQCTLB.bit.CBU = AQ_SET;//CTR=CAU 时,将 ePWM6B 置高
【例③】向上计数(递增)ePWMA 独立调制,不对称脉冲波形,如下图所示:

c
EPwm6Regs.TBPRD=tbprd;//设定PWM周期为tbprd+1个TBCLK时钟周期
EPwm6Regs.CMPA.half.CMPA=200;//比较器A的值为200
EPwm6Regs.CMPB=400;//比较器B的值为400
EPwm6Regs.TBPHS.half.TBPHS=0;//相位寄存器清零
EPwm6Regs.TBCTR=0x0000;//时基计数器清零
EPwm6Regs.TBCTL.bit.CTRMODE=TB_COUNT_UP;//设定为增计数模式
EPwm6Regs.TBCTL.bit.PHSEN=TB_DISABLE;//禁止相位控制
EPwm6Regs.TBCTL.bit.PRDLD = TB_SHADOW;//TBPRD寄存器采用影子寄存器模式
EPwm1Regs.TBCTL.bit.SYNCOSEL=TB_SYNC_DISABLE;//禁止同步信号
EPwm6Regs.TBCTL.bit.HSPCLKDIV=TB_DIV1;//设定TBCLK=SYSCLK时基时钟=系统时钟
EPwm6Regs.TBCTL.bit.CLKDIV=TB_DIV1;
EPwm6Regs.CMPCTL.bit.SHDWAMODE=CC_SHADOW;//设定CMPA为影子寄存器模式
EPwm6Regs.CMPCTL.bit.SHDWBMODE=CC_SHADOW;
EPwm6Regs.CMPCTL.bit.LOADAMODE=CC_CTR_ZERO;//在CTR=Zero时装载
EPwm6Regs.CMPCTL.bit.LOADBMODE=CC_CTR_ZERO;
EPwm6Regs.AQCTLA.bit.CAU=AQ_SET;//CTR=CAU时,将ePWM6A置高
EPwm6Regs.AQCTLA.bit.CBU=AQ_CLEAR;//CTR=CBU时,将ePWM6A置低
EPwm6Regs.AQCTLB.bit.ZRO=AQ_TOGGLE;//CTR=ZERO时,将ePWM6B翻转
EPwm6Regs.CMPA.half.CMPA=Duty1A;//调整ePWM6A的占空比
EPwm6Regs.CMPB=Duty1B;//调整ePWM6B的占空比
【例④】上下(先增后减)计数,双边对称波形,ePWMxA 和 ePWMxB 独立调制,低电平有效,如下图所示:

其配置代码如下:
c
EPwm6Regs.TBPRD= tbprd;//设定PWM周期为2*(tbprd)个TBCLK时钟周期
EPwm6Regs.CMPA.half.CMPA=400;//比较器A的值为400
EPwm6Regs.CMPB=500;//比较器B的值为500
EPwm6Regs.TBPHS.half.TBPHS=0;//相位寄存器清零
EPwm6Regs.TBCTR = 0x0000;//时基计数器清零
EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;//设定为上下计数模式
EPwm6Regs.TBCTL.bit.PHSEN = TB_DISABLE;//禁止相位控制
EPwm6Regs.TBCTL.bit.PRDLD = TB_SHADOW;//TBPRD 寄存器采用影子寄存器模式
EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;//禁止同步信号
EPwm6Regs.TBCTL.bit.HSPCLKDIV=TB_DIV1;//设定TBCLK=SYSCLK时基时钟=系统时钟
EPwm6Regs.TBCTL.bit.CLKDIV=TB_DIV1;
EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;//设定 CMPA 为影子寄存器模式
EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;//在 CTR=Zero 时装载
EPwm6Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
EPwm6Regs.AQCTLA.bit.CAU = AQ_SET;//CTR=CAU 时,将 ePWM6A 置高
EPwm6Regs.AQCTLA.bit.CAD = AQ_CLEAR;//CTR=CAD 时,将 ePWM6A 置低
EPwm6Regs.AQCTLB.bit.CBU = AQ_SET;//CTR=CBU 时,将 ePWM6B 置高
EPwm6Regs.AQCTLB.bit.CBD = AQ_CLEAR;//CTR=CBD 时,将 ePWM6B 置低
EPwm6Regs.CMPA.half.CMPA = Duty1A;//调整 ePWM6A 的占空比
EPwm6Regs.CMPB = Duty1B;//调整 ePWM6B 的占空比
【例⑤】上下(先增后减)计数,双边对称波形,ePWMxA和ePWMxB独立调制,互补型,如下图所示:

c
EPwm6Regs.CMPA.half.CMPA = 350;//比较器 A 的值为 350
EPwm6Regs.CMPB = 400;//比较器 B 的值为 400
EPwm6Regs.AQCTLB.bit.CBU = AQ_CLEAR;//CTR=ZERO 时,将 ePWM6B 置低
EPwm6Regs.AQCTLB.bit.CBD = AQ_SET;//CTR=CBD 时,将 ePWM6B 置高
【例⑥】上下(先增后减)计数,ePWMxA 独立独立输出双边沿不对称波形,如下图所示:

其相关配置代码如下
c
EPwm6Regs.TBPRD=tbprd;//设定PWM周期为tbprd+1个TBCLK时钟周期
EPwm6Regs.CMPA.half.CMPA=250;//比较器A的值为250
EPwm6Regs.CMPB=450;//比较器B的值为450
EPwm6Regs.TBPHS.half.TBPHS=0;//相位寄存器清零
EPwm6Regs.TBCTR=0x0000;//时基计数器清零
EPwm6Regs.TBCTL.bit.CTRMODE=TB_COUNT_UPDOWN;//设定为上下计数模式
EPwm6Regs.TBCTL.bit.PHSEN=TB_DISABLE;//禁止相位控制
EPwm6Regs.TBCTL.bit.PRDLD = TB_SHADOW;//TBPRD寄存器采用影子寄存器模式
EPwm1Regs.TBCTL.bit.SYNCOSEL=TB_SYNC_DISABLE;//禁止同步信号
EPwm6Regs.TBCTL.bit.HSPCLKDIV=TB_DIV1;//设定TBCLK=SYSCLK时基时钟=系统时钟
EPwm6Regs.TBCTL.bit.CLKDIV=TB_DIV1;
EPwm6Regs.CMPCTL.bit.SHDWAMODE=CC_SHADOW;//设定CMPA为影子寄存器模式
EPwm6Regs.CMPCTL.bit.SHDWBMODE=CC_SHADOW;
EPwm6Regs.CMPCTL.bit.LOADAMODE=CC_CTR_ZERO;//在CTR=Zero时装载
EPwm6Regs.CMPCTL.bit.LOADBMODE=CC_CTR_ZERO;
EPwm6Regs.AQCTLA.bit.CAU=AQ_SET;//CTR=CAU时,将ePWM6A置高
EPwm6Regs.AQCTLA.bit.CBD=AQ_CLEAR;//CTR=CBD时,将ePWM6A置低
EPwm6Regs.AQCTLB.bit.ZRO=AQ_CLEAR;//CTR=ZERO时,将ePWM6B置低
EPwm6Regs.AQCTLB.bit.PRD=AQ_SET;//CTR=PRD时,将ePWM1B置高
EPwm6Regs.CMPA.half.CMPA=Duty1A;//通过设置Duty1A的值调整ePWM6A的上升沿发生的时刻
EPwm6Regs.CMPB=Duty1B;//通过设置Duty1B的值调整ePWM6A的下降沿发生的时刻

