Home
avatar

Tolshao

SVPWM怎么落到PWM定时器?(下篇)开关序列、过调制与完整实现

封面:SVPWM怎么落到PWM定时器?(下篇)开关序列、过调制与完整实现

你好,我是老列 👋

在SVPWM凭啥能把直流母线多榨15%?(上篇)六支箭、八种状态与六个扇区里,我们认清了八种开关状态和六个扇区;在SVPWM的作用时间怎么算(中篇)调制边界、伏秒平衡与作用时间里,我们又算出了两支相邻有效矢量各自该站多久。

现在只剩最后一公里: 把这些时间排成不会乱跳的开关序列,再翻译成 PWM 定时器能够识别的 CMP 比较值 。

🧭系列导航 | SVPWM凭啥能把直流母线多榨15%?(上篇)六支箭、八种状态与六个扇区 | SVPWM的作用时间怎么算(中篇)调制边界、伏秒平衡与作用时间 | 本篇:排顺序、算 CMP | SVPWM如何兼顾损耗与寿命?(番外篇)钳位策略、零矢量与IGBT热平衡

本文概览:从连续开关序列到三相 PWM 比较寄存器


01|为什么作用时间算对了,还要讲究开关顺序?

TgT_g、 ThT_h、 TZT_Z只回答“每支矢量一共作用多久”。只要三者总时间不变,一个 PWM 周期内的平均电压就相同;但真实逆变器还必须在这些开关状态之间逐个走过去。

走法不同,会直接改变:

  • 一次有几个桥臂同时换向;
  • 电压矢量跳变有多大;
  • 电流纹波的峰值和频谱;
  • 死区误差、窄脉冲与共模电压;
  • EMI、轴承电流与器件开关损耗;
  • ADC 能否落在稳定、可观测的采样窗口内。

01.1|第一条原则:相邻状态只允许 A、B、C 中的一相换向

把三相上管状态写成二进制 SASBSCS_AS_BS_C。两状态之间若只有一位不同,就称为 Gray 邻接。例如:

000→100→110→111000\rightarrow100\rightarrow110\rightarrow111

每一步分别只改变 A、B、C 中的一相。反过来,若直接从 000000跳到 110110,A、B 两个桥臂同时换向;若从 000000跳到 111111,三个桥臂同时换向。

一次只动一个桥臂的好处是:

  1. 避免多个桥臂的开关沿在同一时刻叠加;
  2. 减小空间电压矢量的单次跳跃;
  3. 降低共模电压尖峰、寄生电容电流和 EMI;
  4. 让死区、最小脉宽和故障互锁更容易管理;
  5. 给电流采样留下更可预测的稳定区间。

这里说的“一相换向”,是指三相状态字一次只改变一位;同一桥臂的上下管仍由硬件互补、死区和互锁保证,绝不能同时导通。

01.2|第二条原则:跨扇区时,矢量和比较值都要连续

第Ⅰ扇区使用 V4V_4、 V6V_6,第Ⅱ扇区使用 V6V_6、 V2V_2。参考矢量越过 60∘60^\circ边界时:

  • T4T_4应连续减小到 0;
  • T2T_2应从 0 连续增加;
  • 两区共享的 T6T_6保持连续;
  • 三相 CMP 不应因为扇区编号变化而突然跳变。

因此,扇区切换不是把两张表硬切,而是让“退出矢量”消失、“进入矢量”出现,并把公共矢量保留下来。边界处若两个比较事件重合,应删除零宽度片段或按固定优先级合并,不能让量化误差制造一个极窄脉冲。

🔄顺序设计的两条底线 :扇区内部按 Gray 邻接逐相换向;扇区之间让作用时间、序列端点和三相 CMP 连续衔接。

下图把两条原则放在一起:左侧对比 Gray 邻接与多桥臂同时换向,右侧展示参考矢量跨越第Ⅰ、Ⅱ扇区边界时,退出矢量、公共矢量和进入矢量的作用时间如何连续交接。

SVPWM 开关顺序的两条原则:单相换向与跨扇区连续

02|五段式:满足对称与逐相换向的最少段数

02.1|为什么最少需要五段?

一个扇区至少要出现三种状态:一个零矢量 Z=V0(V7)Z=V_0(V_7)和两支相邻有效矢量 Vg′V_{g'}Vh′V_{h'}。若还要求:

  • 前后关于周期中心镜像;
  • 周期结束回到起始零矢量;
  • 相邻状态只改变一个桥臂;

那么最短的回文路径只能是:

Z→Vg′→Vh′→Vg′→ZZ\rightarrow V_{g'}\rightarrow V_{h'}\rightarrow V_{g'}\rightarrow Z

这正好是五段。少于五段,无法满足01章的2个原则。

五段式每周期只有 4 次状态跳变;七段式则有 6 次。理想计数下,五段式少掉了一个桥臂的一次通断。

02.2|为什么并非每个扇区都是“零矢量→Vg′V_{g'}→Vh′V_{h'}”?

局部坐标中的 Vg′V_{g'}、 Vh′V_{h'}只说明哪两支矢量参与合成,并不规定谁先出现。真正决定顺序的是二进制状态的邻接关系:

  • V0=000V_0=000只能与2相下桥臂导通矢量相邻,如V4=100V_4=100、 V2=010V_2=010、 V1=001V_1=001;
  • V7=111V_7=111只能与2相上桥臂导通矢量相邻,如V6=110V_6=110、 V3=011V_3=011、 V5=101V_5=101。

所以第Ⅱ扇区的相邻有效矢量虽然常按 V6V_6、 V2V_2书写,下钳位时却必须从 V0V_0先走到 V2V_2,再走到 V6V_6:

V0→V2→V6→V2→V0V_0\rightarrow V_2\rightarrow V_6\rightarrow V_2\rightarrow V_0

02.3|六个扇区的五段式序列表

扇区下钳位:只用 V0V_0钳位相上钳位:只用 V7V_7钳位相
ⅠV0→V4→V6→V4→V0V_0\to V_4\to V_6\to V_4\to V_0C=0V7→V6→V4→V6→V7V_7\to V_6\to V_4\to V_6\to V_7A=1
ⅡV0→V2→V6→V2→V0V_0\to V_2\to V_6\to V_2\to V_0C=0V7→V6→V2→V6→V7V_7\to V_6\to V_2\to V_6\to V_7B=1
ⅢV0→V2→V3→V2→V0V_0\to V_2\to V_3\to V_2\to V_0A=0V7→V3→V2→V3→V7V_7\to V_3\to V_2\to V_3\to V_7B=1
ⅣV0→V1→V3→V1→V0V_0\to V_1\to V_3\to V_1\to V_0A=0V7→V3→V1→V3→V7V_7\to V_3\to V_1\to V_3\to V_7C=1
ⅤV0→V1→V5→V1→V0V_0\to V_1\to V_5\to V_1\to V_0B=0V7→V5→V1→V5→V7V_7\to V_5\to V_1\to V_5\to V_7C=1
ⅥV0→V4→V5→V4→V0V_0\to V_4\to V_5\to V_4\to V_0B=0V7→V5→V4→V5→V7V_7\to V_5\to V_4\to V_5\to V_7A=1

五段式下钳位、上钳位的六扇区矢量顺序与逐相换向路径

图中箭头画的是前半周期,后半周期沿原路径镜像返回。它直观说明: 先保证相邻状态只差一位,再决定局部两支矢量谁先谁后 。

02.4|钳位相怎样跨扇区轮换?

若始终采用下钳位:

  • 第Ⅰ、Ⅱ扇区钳位 C 相;
  • 第Ⅲ、Ⅳ扇区钳位 A 相;
  • 第Ⅴ、Ⅵ扇区钳位 B 相。

若始终采用上钳位:

  • 第Ⅵ、Ⅰ扇区钳位 A 相;
  • 第Ⅱ、Ⅲ扇区钳位 B 相;
  • 第Ⅳ、Ⅴ扇区钳位 C 相。

每相连续钳位约 120∘120^\circ电角度,三相在完整电周期内能够轮换;但上、下器件的损耗、共模电压与 ADC 采样窗口仍会随钳位策略改变。

五段式真正麻烦的地方就在这里:跨扇区时不仅要换有效矢量,还要管理钳位相;若运行中再切换上、下钳位,还要管理 V0V_0、 V7V_7的交接。直接从 000000跳到 111111会让三个桥臂同时翻转,必须用状态机、过渡序列或短暂的七段式周期衔接。

03|为什么还要引入七段式?

五段式已经能正确合成平均电压,也可以做成时间轴上的镜像序列。它所谓的“不对称”,主要是:

  • 每周期只使用 V0V_0、 V7V_7中的一个;
  • 三相中有一个桥臂完全不切换,另外两个承担全部换向;
  • 钳位相在扇区边界轮换;
  • 差模脉冲、共模电压和采样窗口更依赖所选钳位策略。

这能降低开关损耗,却会让三相桥臂的活动分布和扇区衔接变得更复杂。在相同 PWM 频率下,常规五段式的部分工况还可能出现更大的峰值电流纹波或载波边带。

03.1|标准七段式:把另一种零矢量放回周期中心

以 V0V_0首尾闭合的第Ⅰ扇区为例:

V0→V4→V6→V7→V6→V4→V0V_0\rightarrow V_4\rightarrow V_6\rightarrow V_7 \rightarrow V_6\rightarrow V_4\rightarrow V_0

为避免跨扇区后继续使用 T4T_4、 T6T_6这类物理矢量下标,先按开关状态中上桥臂置 1 的数量定义两类有效矢量时间:

  • T1T_1:当前扇区中,只有 1 相上桥臂状态为 1 的有效矢量总作用时间;
  • T2T_2:当前扇区中,有 2 相上桥臂状态为 1 的有效矢量总作用时间。

这里的下标 1、2 表示“有几相上桥臂置 1”, 不是物理矢量 V1V_1、 V2V_2的编号。第Ⅰ扇区中, V4=100V_4=100对应 T1T_1, V6=110V_6=110对应 T2T_2,所以总零矢量时间为:

TZ=Ts−T1(V4)−T2(V6)T_Z=T_s-T_1(V_4)-T_2(V_6)

标准对称分配为:

TV0=TV7=TZ2T_{V0}=T_{V7}=\frac{T_Z}{2}

因为 V0V_0在首尾各出现一次, V7V_7在中心出现一次,各段时间为:

TZ4,T12,T22,TZ2,T22,T12,TZ4\frac{T_Z}{4},\quad \frac{T_1}{2},\quad \frac{T_2}{2},\quad \frac{T_Z}{2},\quad \frac{T_2}{2},\quad \frac{T_1}{2},\quad \frac{T_Z}{4}

03.2|六个扇区的七段式序列

扇区V0V_0首尾的七段式序列
ⅠV0→V4→V6→V7→V6→V4→V0V_0\to V_4\to V_6\to V_7\to V_6\to V_4\to V_0
ⅡV0→V2→V6→V7→V6→V2→V0V_0\to V_2\to V_6\to V_7\to V_6\to V_2\to V_0
ⅢV0→V2→V3→V7→V3→V2→V0V_0\to V_2\to V_3\to V_7\to V_3\to V_2\to V_0
ⅣV0→V1→V3→V7→V3→V1→V0V_0\to V_1\to V_3\to V_7\to V_3\to V_1\to V_0
ⅤV0→V1→V5→V7→V5→V1→V0V_0\to V_1\to V_5\to V_7\to V_5\to V_1\to V_0
ⅥV0→V4→V5→V7→V5→V4→V0V_0\to V_4\to V_5\to V_7\to V_5\to V_4\to V_0

下面仍以第Ⅰ扇区为例,把下钳位五段式和标准七段式的 A、B、C 三相开关状态画在同一时间轴上。五段式中 C 相全周期钳位为 0;七段式则让三相都参与切换,并由中央的 V7V_7脉冲补回另一半零矢量时间。

第Ⅰ扇区五段式与七段式的 A、B、C 三相时序对比

03.3|七段式通常怎样改善电流纹波和谐波?

电流纹波来自瞬时输出矢量与参考平均矢量之间的误差:

Δi≈1L∫(Vk−Uref)dt\Delta\boldsymbol i \approx \frac{1}{L} \int \left(\boldsymbol V_k-\boldsymbol U_{ref}\right)dt

七段式并没有改变一周期的伏秒总量,而是改变误差电压在周期内走过的路径:

  1. 三个桥臂都在每个周期内参与规则换向,等效换向分布更均匀;
  2. 两支有效矢量被平分到周期前后,电压误差通常形成更小、更规则的闭合轨迹;
  3. 序列结构在六个扇区中统一,不需要每周期额外决定钳位相;
  4. 差模谐波更多集中在载波及其边带,电机电感更容易衰减。

但“七段式一定更好”也不严谨:它增加了开关次数,并且 V0↔V7V_0\leftrightarrow V_7的使用会改变共模电压。若五段式省下的损耗允许提高 PWM 频率,最终电流纹波也可能追平甚至反超。两者的损耗与寿命取舍,放在番外篇单独展开:SVPWM如何兼顾损耗与寿命?(番外篇)钳位策略、零矢量与IGBT热平衡。

03.4|五段式与七段式放在一起看

比较项五段式七段式
每周期状态段57
状态跳变4 次6 次
零矢量只用 V0V_0或 V7V_7同时使用 V0V_0、 V7V_7
桥臂活动一相钳位,另两相切换三相均参与切换
同频率差模纹波部分工况较大通常更低、更均匀
开关损耗通常较低通常较高
扇区切换还要管理钳位相与零矢量规则统一,较容易连续
推荐起点热设计或效率受限后再引入通用高性能控制默认方案

04|从七段式序列到 PWM 定时器 CMP

概念讲到这里,读者最容易卡住的是:序列表里的 V0V_0、 V4V_4、 V6V_6、 V7V_7,到底怎样变成 MCU 的三个比较寄存器?

这里继续沿用SVPWM的作用时间怎么算(中篇)调制边界、伏秒平衡与作用时间的输出:先得到当前扇区局部两支矢量的作用时间 Tg′T_{g'}、 Th′T_{h'},再根据开关状态中上桥臂置 1 的数量,把它们映射为 T1T_1、 T2T_2。完成这一步后,CMP 计算统一只使用 TZT_Z、 T1T_1、 T2T_2。

04.1|为什么中心对齐三角载波天然适配?

常见 PWM 计数方式有三种:

  • 向上计数 :计数器从 0 增加到 ARR 后复位,生成边沿对齐 PWM;
  • 向下计数 :从 ARR 减小到 0,是向上计数的镜像;
  • 中心对齐 :计数器按 0→ARR→00\to ARR\to0往返,形成三角载波。

向上计数、向下计数和中心对齐三角载波的比较事件与矢量路径

中心对齐的关键优势是: 同一组 CMP 在上数阶段生成正向序列,在下数阶段自动按相反顺序返回 。因此,一个比较寄存器既给出上升沿,也给出镜像下降沿,天然适合五段式和七段式的回文结构。

04.2|先规定定时器输出逻辑

设定时器计数:

CNT:0→N→0,N=ARRCNT:0\rightarrow N\rightarrow0,\qquad N=ARR

一个完整 PWM 周期为 TsT_s。这里约定三相上管状态满足:

Sx={1,CNT>CMPx0,CNT≤CMPxS_x= \begin{cases} 1,&CNT>CMP_x\\ 0,&CNT\le CMP_x \end{cases}

这样在计数器谷值附近三相都是 0,对应 V0V_0;接近峰值时三相都是 1,对应 V7V_7。若具体 MCU 使用“CNT<CMPCNT < CMP时输出高电平”,只需反转输出极性或把比较值映射为 N−CMPxN - CMP_x。

沿用中篇的局部时间定义:

  • Vg′V_{g'}:当前扇区局部 g′ 轴对应的有效矢量,作用时间为 Tg′T_{g'};
  • Vh′V_{h'}:当前扇区局部 h′ 轴对应的有效矢量,作用时间为 Th′T_{h'}。

进入开关序列生成后,再按状态字的汉明重量统一定义:

  • T1T_1:状态字中只有 1 个“1”的有效矢量时间,即 V4=100V_4=100、 V2=010V_2=010、 V1=001V_1=001三者之一;
  • T2T_2:状态字中有 2 个“1”的有效矢量时间,即 V6=110V_6=110、 V3=011V_3=011、 V5=101V_5=101三者之一;
  • TZ=Ts−T1−T2T_Z=T_s-T_1-T_2:两个零矢量合计的作用时间。

🔢其中 T1T_1、 T2T_2不是 V1V_1、 V2V_2的作用时间 。下标只表示当前有效矢量的三位状态字中有 1 个还是 2 个“1”。

六个扇区中, T1T_1、 T2T_2与中篇 Tg′T_{g'}、 Th′T_{h'}的关系如下:

扇区Vg′V_{g'},作用 Tg′T_{g'}Vh′V_{h'},作用 Th′T_{h'}T1T_1对应T2T_2对应时间关系
ⅠV4=100V_4=100V6=110V_6=110V4V_4V6V_6T1=Tg′, T2=Th′T_1=T_{g'},\ T_2=T_{h'}
ⅡV6=110V_6=110V2=010V_2=010V2V_2V6V_6T1=Th′, T2=Tg′T_1=T_{h'},\ T_2=T_{g'}
ⅢV2=010V_2=010V3=011V_3=011V2V_2V3V_3T1=Tg′, T2=Th′T_1=T_{g'},\ T_2=T_{h'}
ⅣV3=011V_3=011V1=001V_1=001V1V_1V3V_3T1=Th′, T2=Tg′T_1=T_{h'},\ T_2=T_{g'}
ⅤV1=001V_1=001V5=101V_5=101V1V_1V5V_5T1=Tg′, T2=Th′T_1=T_{g'},\ T_2=T_{h'}
ⅥV5=101V_5=101V4=100V_4=100V4V_4V5V_5T1=Th′, T2=Tg′T_1=T_{h'},\ T_2=T_{g'}

因此,奇数扇区有 T1=Tg′T_1=T_{g'}、 T2=Th′T_2=T_{h'};偶数扇区有 T1=Th′T_1=T_{h'}、 T2=Tg′T_2=T_{g'}。无论在哪个扇区, V0V_0首尾七段式都先经过“1 相上桥臂置 1”的有效矢量,再经过“2 相上桥臂置 1”的有效矢量,完整时间序列统一为:

TZ4,T12,T22,TZ2,T22,T12,TZ4\frac{T_Z}{4},\quad \frac{T_1}{2},\quad \frac{T_2}{2},\quad \frac{T_Z}{2},\quad \frac{T_2}{2},\quad \frac{T_1}{2},\quad \frac{T_Z}{4}

定义从作用时间到计数增量的统一换算:

KZ=NTZ2TsK_Z=\frac{N T_Z}{2T_s}K1=NT1Ts,K2=NT2TsK_1=\frac{N T_1}{T_s},\qquad K_2=\frac{N T_2}{T_s}

为什么 KZK_Z带 1/21/2?因为首端的 V0V_0只占 TZ/4T_Z/4,而计数器上数半周期只有 Ts/2T_s/2:

KZ=NTZ/4Ts/2=NTZ2TsK_Z=N\frac{T_Z/4}{T_s/2}=\frac{NT_Z}{2T_s}

两支有效矢量在上数阶段分别作用 T1/2T_1/2、 T2/2T_2/2,对应计数增量为:

NT1/2Ts/2=NT1Ts=K1N\frac{T_1/2}{T_s/2}=\frac{NT_1}{T_s}=K_1NT2/2Ts/2=NT2Ts=K2N\frac{T_2/2}{T_s/2}=\frac{NT_2}{T_s}=K_2

为了避免在六扇区 CMP 表中反复书写累加式,再定义三个按时间先后排列的比较阈值:

C0=KZC_0=K_ZC1=C0+K1=KZ+K1C_1=C_0+K_1=K_Z+K_1C2=C1+K2=KZ+K1+K2C_2=C_1+K_2=K_Z+K_1+K_2

其中 C0≤C1≤C2C_0\le C_1\le C_2。它们分别表示上数阶段的第一次、第二次和第三次桥臂翻转时刻, 并不固定属于 A、B、C 中的某一相 ;具体分配由扇区决定。

04.3|第Ⅰ扇区:三个比较值如何出现?

第Ⅰ扇区中:

Vg′=V4=100,Vh′=V6=110V_{g'}=V_4=100,\qquad V_{h'}=V_6=110

因此:

T1=Tg′  (V4),T2=Th′  (V6)T_1=T_{g'}\;(V_4),\qquad T_2=T_{h'}\;(V_6)

完整七段式及其时间序列分别为:

V0→V4→V6→V7→V6→V4→V0V_0\rightarrow V_4\rightarrow V_6\rightarrow V_7 \rightarrow V_6\rightarrow V_4\rightarrow V_0TZ4,T12,T22,TZ2,T22,T12,TZ4\frac{T_Z}{4},\quad \frac{T_1}{2},\quad \frac{T_2}{2},\quad \frac{T_Z}{2},\quad \frac{T_2}{2},\quad \frac{T_1}{2},\quad \frac{T_Z}{4}

上数阶段对应:

000→100→110→111000\rightarrow100\rightarrow110\rightarrow111

于是:

  • 计数到 C0=KZC_0=K_Z, V0V_0的首段结束,A 相翻为 1;
  • 计数到 C1=C0+K1C_1=C_0+K_1, V4V_4的 T1/2T_1/2结束,B 相翻为 1;
  • 计数到 C2=C1+K2C_2=C_1+K_2, V6V_6的 T2/2T_2/2结束,C 相翻为 1;
  • 到达峰值前后连续保持 V7V_7,两侧合计形成中央的 TZ/2T_Z/2。

因此第Ⅰ扇区只需把三个有序阈值依次分配给 A、B、C:

CMPA=C0CMP_A=C_0CMPB=C1CMP_B=C_1CMPC=C2CMP_C=C_2

计数器越过峰值后自动按 111→110→100→000111\to110\to100\to000返回,完整七段式无需软件逐段切换 GPIO。换到其它扇区后, C0C_0、 C1C_1、 C2C_2的数值定义保持不变,只改变它们与 A、B、C 三相的对应关系。

04.4|六个扇区只需排列 C0C_0、 C1C_1、 C2C_2

扇区上数阶段CMPACMP_ACMPBCMP_BCMPCCMP_C
ⅠV0→V4(T1)⋅⋅⋅V6(T2)→V7V_0\to V_4(T_1)\cdot\cdot\cdot V_6(T_2)\to V_7C0C_0C1C_1C2C_2
ⅡV0→V2(T1)⋅⋅⋅V6(T2)→V7V_0\to V_2(T_1)\cdot\cdot\cdot V_6(T_2)\to V_7C1C_1C0C_0C2C_2
ⅢV0→V2(T1)⋅⋅⋅V3(T2)→V7V_0\to V_2(T_1)\cdot\cdot\cdot V_3(T_2)\to V_7C2C_2C0C_0C1C_1
ⅣV0→V1(T1)⋅⋅⋅V3(T2)→V7V_0\to V_1(T_1)\cdot\cdot\cdot V_3(T_2)\to V_7C2C_2C1C_1C0C_0
ⅤV0→V1(T1)⋅⋅⋅V5(T2)→V7V_0\to V_1(T_1)\cdot\cdot\cdot V_5(T_2)\to V_7C1C_1C2C_2C0C_0
ⅥV0→V4(T1)⋅⋅⋅V5(T2)→V7V_0\to V_4(T_1)\cdot\cdot\cdot V_5(T_2)\to V_7C0C_0C2C_2C1C_1

对应上管占空比为:

dx=1−CMPxNd_x=1-\frac{CMP_x}{N}

例如第Ⅰ扇区若:

Ts=100 μs,T1=30 μs,T2=50 μs,TZ=20 μsT_s=100\,\mu s,\quad T_1=30\,\mu s,\quad T_2=50\,\mu s,\quad T_Z=20\,\mu s

且 N=5000N=5000,则:

KZ=500,K1=1500,K2=2500K_Z=500,\qquad K_1=1500,\qquad K_2=2500

先计算三个有序阈值:

C0=500,C1=2000,C2=4500C_0=500,\qquad C_1=2000,\qquad C_2=4500

第Ⅰ扇区映射为:

CMPA=C0=500,CMPB=C1=2000,CMPC=C2=4500CMP_A=C_0=500,\qquad CMP_B=C_1=2000,\qquad CMP_C=C_2=4500

因此:

dA=0.9,dB=0.6,dC=0.1d_A=0.9,\qquad d_B=0.6,\qquad d_C=0.1

六个扇区都复用同一组 C0C_0、 C1C_1、 C2C_2:最先置 1 的桥臂取 C0C_0,第二个置 1 的桥臂取 C1C_1,最后置 1 的桥臂取 C2C_2。

🧮统一接口 :中篇输出扇区号、 Tg′T_{g'}、 Th′T_{h'}→ 映射为 T1T_1、 T2T_2→ 计算 KZK_Z、 K1K_1、 K2K_2→ 累加得到 C0C_0、 C1C_1、 C2C_2→ 按扇区排列为 CMPACMP_A、 CMPBCMP_B、 CMPCCMP_C。

04.5|硬件更新与采样的三个落点

  1. 中断触发 :固定在计数器谷值、峰值或指定更新事件,给扇区判断与 CMP 计算留下确定预算;
  2. 影子寄存器 :A、B、C 三相先写 shadow,再在同一更新事件中同步装载,不能分批生效;
  3. ADC 同步 :采样点放在远离开关沿和死区的稳定片段中。若从七段式切到五段式,稳定窗口也会移动,ADC 触发时刻必须同步重算。

更深入的钳位切换、温度平衡与 ADC 窗口变化见番外篇:SVPWM如何兼顾损耗与寿命?(番外篇)钳位策略、零矢量与IGBT热平衡。

05|写 CMP 前还要过最后一道关: TZT_Z不能为负

只要:

TZ=Ts−T1−T2≥0T_Z=T_s-T_1-T_2\ge0

参考矢量就在当前线性调制范围内。若 T1+T2>TsT_1+T_2>T_s,现实中不存在负的零矢量时间,此时不能把负数直接换算成 CMP。

最简单的边界限幅是按比例压缩两支有效矢量:

k=TsT1+T2k=\frac{T_s}{T_1+T_2}T1←kT1,T2←kT2,TZ←0T_1\leftarrow kT_1,\qquad T_2\leftarrow kT_2,\qquad T_Z\leftarrow0

这会把参考矢量压回六边形边界。若要继续提高基波电压,则进入过调制:参考轨迹逐渐从圆变成六边形,最终走向六步方波;可用电压继续增加,但低次谐波、转矩纹波和控制非线性也随之增加。

高速弱磁区尤其要同时处理:

  • 实时母线电压 UdcU_{dc};
  • 参考电压矢量限幅;
  • 电流 PI 抗积分饱和;
  • 最小脉宽与死区;
  • TZ=0T_Z=0时的 ADC 采样窗口。

06|C 语言完整实现

下面将前面的 60° 坐标变换、扇区判断、过调制限幅、 C0/C1/C2C_0/C_1/C_2计算和三相 CMP 映射合并为一个 C 函数。输入数组依次为 Va 、 Vb 、 Vc 、 Ts 、 PRD ;输出参数可直接用于三相 PWM 比较寄存器。

代码中的 T0T_0、 T1T_1、 T2T_2均为相对于 TsT_s的标幺时间,因此计算 CMP 时 TsT_s可以约去。 PRD 表示中心对齐计数器的峰值。

06.1|伪代码流程

flowchart TD
    A(["输入 Va、Vb、Vc、Ts、PRD"]) --> B["60° 斜坐标变换<br/>计算 Vg、Vh"]
    B --> C["按 2Vdc/3 标幺化<br/>计算 Vr = Vg + Vh"]
    C --> D{"根据 Vg、Vh、Vr<br/>判断六个扇区"}
    D --> E["将局部作用时间<br/>映射为 T1、T2"]
    E --> F["计算 T0 = 1 - T1 - T2"]
    F --> G{"T0 是否小于 0?"}
    G -- "是" --> H["按 T1 + T2 等比例限幅<br/>并令 T0 = 0"]
    G -- "否" --> I["保留 T0、T1、T2"]
    H --> J["计算 TL、TM、TH"]
    I --> J
    J --> K["换算 C0、C1、C2"]
    K --> L{"按扇区排列<br/>C0、C1、C2"}
    L --> M(["输出 CMPA、CMPB、CMPC"])
    M --> N(["同步写入三相影子寄存器"])

    classDef io fill:#EAF2FB,stroke:#2878B5,color:#17324D,stroke-width:1.5px;
    classDef process fill:#F4F7FA,stroke:#6B7785,color:#17324D,stroke-width:1px;
    classDef decision fill:#FFF3DF,stroke:#E38B29,color:#17324D,stroke-width:1.5px;
    class A,M,N io;
    class B,C,E,F,H,I,J,K process;
    class D,G,L decision;

06.2|C 语言函数

#include <stdint.h>

void SVPWM(const float u[5],
           uint32_t *CMPA,
           uint32_t *CMPB,
           uint32_t *CMPC)
{
    const float Va  = u[0];
    const float Vb  = u[1];
    const float Vc  = u[2];
    const float Ts  = u[3];
    const float PRD = u[4];

    /* 示例直流母线电压;工程中应替换为实时采样值或函数参数。 */
    const float Vdc = 700.0f;

    float Vg;
    float Vh;
    float Vr;
    float T0;
    float T1;
    float T2;
    float Tsum;
    float TL;
    float TM;
    float TH;
    float C0;
    float C1;
    float C2;
    float cmpA;
    float cmpB;
    float cmpC;
    uint8_t sec;

    if ((Ts <= 0.0f) || (PRD <= 0.0f)) {
        *CMPA = 0U;
        *CMPB = 0U;
        *CMPC = 0U;
        return;
    }

    /* 60°斜坐标变换。 */
    Vg = (2.0f / 3.0f) * (Va - Vb);
    Vh = (2.0f / 3.0f) * (Vb - Vc);

    /* 按有效矢量幅值 2Vdc/3 进行标幺化。 */
    Vg /= (2.0f * Vdc / 3.0f);
    Vh /= (2.0f * Vdc / 3.0f);
    Vr = Vg + Vh;

    /*
     * 判断扇区,并把局部两矢量时间统一映射为:
     * T1:状态字中只有 1 个“1”的有效矢量时间;
     * T2:状态字中有 2 个“1”的有效矢量时间。
     */
    if ((Vh >= 0.0f) && (Vg >= 0.0f)) {
        sec = 1U;
        T1 = Vg;
        T2 = Vh;
    } else if ((Vh >= 0.0f) && (Vr >= 0.0f)) {
        sec = 2U;
        T1 = -Vg;
        T2 = Vr;
    } else if ((Vh >= 0.0f) && (Vr <= 0.0f)) {
        sec = 3U;
        T1 = Vh;
        T2 = -Vr;
    } else if ((Vg <= 0.0f) && (Vh <= 0.0f)) {
        sec = 4U;
        T1 = -Vh;
        T2 = -Vg;
    } else if ((Vg >= 0.0f) && (Vr <= 0.0f)) {
        sec = 5U;
        T1 = -Vr;
        T2 = Vg;
    } else {
        sec = 6U;
        T1 = Vr;
        T2 = -Vh;
    }

    /* 计算标幺化的零矢量时间。 */
    T0 = 1.0f - T1 - T2;

    /* 超出线性调制区时,将 T1、T2 等比例压回六边形边界。 */
    if (T0 < 0.0f) {
        Tsum = T1 + T2;
        T1 /= Tsum;
        T2 /= Tsum;
        T0 = 0.0f;
    }

    /* 七段式上数阶段的三个累计时刻。 */
    TL = 0.25f * T0;
    TM = TL + 0.5f * T1;
    TH = TM + 0.5f * T2;

    /* 中心对齐计数:完整周期对应 2 × PRD。 */
    C0 = TL * PRD * 2.0f;
    C1 = TM * PRD * 2.0f;
    C2 = TH * PRD * 2.0f;

    /* 根据扇区排列 C0、C1、C2,得到三相 CMP。 */
    switch (sec) {
    case 1U:
        cmpA = C0;
        cmpB = C1;
        cmpC = C2;
        break;

    case 2U:
        cmpA = C1;
        cmpB = C0;
        cmpC = C2;
        break;

    case 3U:
        cmpA = C2;
        cmpB = C0;
        cmpC = C1;
        break;

    case 4U:
        cmpA = C2;
        cmpB = C1;
        cmpC = C0;
        break;

    case 5U:
        cmpA = C1;
        cmpB = C2;
        cmpC = C0;
        break;

    case 6U:
    default:
        cmpA = C0;
        cmpB = C2;
        cmpC = C1;
        break;
    }

    /* 四舍五入为定时器寄存器计数值。 */
    *CMPA = (uint32_t)(cmpA + 0.5f);
    *CMPB = (uint32_t)(cmpB + 0.5f);
    *CMPC = (uint32_t)(cmpC + 0.5f);
}

⚙️落到真实 MCU 时还要处理三点 :把固定的 Vdc = 700 V 改成实时母线电压;按定时器位宽选择 uint16_t 或 uint32_t ;在同一个更新事件中把三个结果同步写入影子寄存器。

07|本篇小结:从两支箭到三个比较寄存器

  1. 作用时间决定平均值,状态顺序决定瞬态品质 ;
  2. 五段式是“零矢量—两支有效矢量—镜像返回”的最短对称路径 ;
  3. 六扇区的先后顺序由二进制 Gray 邻接决定,不由 Vg′V_{g'}、 Vh′V_{h'}的命名决定 ;
  4. 七段式把另一零矢量放回周期中心,用更多换向换取更均匀的差模脉冲和更统一的扇区逻辑 ;
  5. 中心对齐三角载波在上数、下数过程中天然生成正向与镜像序列 ;
  6. 六扇区 CMP 表,就是把矢量停留时间累加成三个比较阈值 ;
  7. 在 CMP 写入前必须处理过调制、最小脉宽、shadow 锁存和 ADC 同步 。

至此,SVPWM 的完整链条终于闭合:

判断扇区 → 计算作用时间 → 选择连续序列 → 换算 CMP → 同步更新 PWM → 在安全窗口采样电流 。

至于“五段式上下钳位怎么选”“七段式 V0V_0、 V7V_7怎么分”“如何根据 IGBT 手册、扭矩和转速降低损耗并延长寿命”,继续看:SVPWM如何兼顾损耗与寿命?(番外篇)钳位策略、零矢量与IGBT热平衡。

💬 老列碎碎念

这一篇最容易让人卡住的地方,不是五段式、七段式的箭头怎么画,而是“作用时间已经算出来了,为什么还不能直接写进 PWM 定时器”。换个视角就顺了: T1T_1、 T2T_2、 TZT_Z是每种状态在一个周期里的总预算,开关序列负责安排它们按什么顺序出场,而 CMP 则是把这份时间表翻译成计数器上的三个事件位置。三者说的是同一件事,却处在不同层级。

中心对齐计数器也没有真的替软件逐段切换七次。控制器只需算好 C0C_0、 C1C_1、 C2C_2,再按扇区分配给 A、B、C 三相;计数器上数时把序列正着走一遍,下数时自然镜像返回。真正需要工程师盯紧的,是扇区边界、最小脉宽、影子寄存器和 ADC 采样窗口——这些地方一旦处理不好,纸面上完全正确的伏秒平衡也可能在硬件上变成窄脉冲、错采样甚至桥臂误动作。

你把 SVPWM 落到 MCU 时,最容易卡在五段式和七段式的顺序,还是 CMP 极性、中心对齐模式和同步更新这些定时器细节?评论区聊聊。觉得这套“从箭头到寄存器”的链条终于接上了,老规矩, 点赞、在看、转发三连伺候,老列给你比个心。

如果觉得这篇文章对你有帮助,
别忘了点赞、在看、分享三连哦!

👇👇👇


推荐关注公众号「探物及理」,探万物之然,及万理之源。

SVPWM 空间矢量 五段式 七段式 PWM定时器