C2000 eHRPWM寄存器配置实战:从时基到死区,驱动电机与电源

C2000 eHRPWM寄存器配置实战:从时基到死区,驱动电机与电源

1. 从寄存器手册到实战代码:eHRPWM编程的核心思路

如果你正在用TI的C2000系列MCU做电机控制、数字电源或者任何需要精密PWM的活儿,那你肯定绕不开eHRPWM这个模块。手册上那几十页的寄存器描述,密密麻麻的位字段,第一次看确实让人头大。我当年也是这么过来的,对着SPRUH91D这份技术参考手册,一行行啃寄存器定义,从时基到死区,从动作限定到高分辨率扩展,感觉每个字都认识,但连起来就不知道该怎么下手写代码。

其实,eHRPWM的寄存器配置,核心逻辑就一条:用一个时基计数器作为“心跳”,通过比较器在特定的“心跳数”上触发动作,再经过死区等模块的修饰,最终输出你想要的PWM波形。听起来简单,但魔鬼全在细节里。比如,为什么要有影子寄存器?动作限定器里CAU和CAD有什么区别?死区控制的IN_MODE和POLSEL组合起来到底会产生什么效果?这些问题手册不会直接告诉你答案,它只告诉你每个位是干什么的,而把寄存器“串起来”形成工作流,才是我们工程师真正要做的。

这篇文章,我就结合自己这些年调试变频器、伺服驱动和LLC电源的经验,把eHRPWM那几个关键子模块的寄存器掰开揉碎了讲。我不会照着手册再给你念一遍每个位的定义——那个你随时可以查。我会重点讲清楚:当你需要输出一个带死区的互补PWM去驱动半桥时,你应该按什么顺序、配置哪些寄存器、每个配置背后的物理意义是什么,以及我踩过的那些坑。我们的目标不是读懂手册,而是把手册变成你手上一行行能跑起来、并且稳定可靠的代码。

2. 时基模块:PWM的“心脏”与“节拍器”

时基模块是整个eHRPWM的节奏之源。你可以把它想象成一个音乐节拍器,它决定了PWM波的“速度”(频率)和“起始拍子”(相位)。这个模块的寄存器不多,但每一个都至关重要,配置错了,后面的比较、动作全是白搭。

2.1 核心寄存器拆解与配置逻辑

时基模块主要有五个寄存器:控制寄存器TBCTL、状态寄存器TBSTS、相位寄存器TBPHS、计数器TBCNT和周期寄存器TBPRD。我们一个一个来看。

TBCTL (Time-Base Control Register): 全局指挥中心这是最重要的寄存器,它设定了PWM运行的“基本法”。配置它,你需要想清楚下面几件事:

  1. 计数模式 (CTRMODE, Bits 1-0):这是第一个要决定的。0是向上计数,1是向下计数,2是向上-向下计数。电机控制和电源里最常用的是向上-向下计数模式。为什么?因为这种模式生成的PWM波是关于周期中心对称的,能有效降低谐波,对于需要对称波形的应用(如SPWM、SVPWM)是刚需。而简单的LED调光,用向上计数就够了。
  2. 时钟预分频 (CLKDIV & HSPCLKDIV, Bits 12:10 & 9:7):这两个位共同决定了时基时钟TBCLK的频率。公式是TBCLK = SYSCLKOUT / (HSPCLKDIV × CLKDIV)。这里有个坑:HSPCLKDIV的复位默认值是/2,而CLKDIV是/1。如果你直接用默认值,而SYSCLKOUT是150MHz,那么TBCLK就是75MHz。如果你的PWM周期寄存器TBPRD设置得很小,计数器会跑得飞快,可能导致你设定的占空比分辨率极低。我的经验是,先根据你想要的PWM频率和计数器精度(比如希望TBPRD在1000左右),反推出合适的TBCLK,再配置这两个分频器。
  3. 相位加载使能 (PHSEN, Bit 2):这是实现多个PWM模块同步(Sync)的关键。当你把它设为1,并且有一个同步信号(来自外部EPWMxSYNCI或软件强制SWFSYNC)到来时,计数器TBCNT会立刻被加载为TBPHS寄存器里的值。这相当于给了这个PWM模块一个“延迟启动”或者“对齐启动”的能力。在多相交错并联电源中,就是用这个功能让各个桥臂的PWM波彼此错开一定相位,均流效果才好。
  4. 周期装载模式 (PRDLD, Bit 3):这个位决定了你写TBPRD寄存器时,是直接生效(立即模式),还是等到计数器归零再生效(影子模式)。99%的情况下,你应该使用影子模式(PRDLD=0)。想象一下,你正在运行一个电机,突然在线修改了PWM频率(即TBPRD值)。如果使用立即模式,计数器可能正数到一半,周期突然改变,会导致当前周期波形畸形,可能立即导致桥臂直通炸管。影子模式保证了只在计数器安全点(零点)更新周期,波形切换是平滑的。

TBPRD (Time-Base Period Register) & TBCNT (Time-Base Counter Register): 周期与心跳

  • TBPRD:这个值直接决定了PWM的周期。在向上-向下计数模式下,PWM频率Fpwm = TBCLK / (2 * TBPRD)。例如,TBCLK=75MHz,想要20kHz的PWM频率,则TBPRD = 75MHz / (2 * 20kHz) = 1875
  • TBCNT:这是实时变化的计数器值,你可以读取它来了解当前PWM周期走到了哪一步。注意:直接写TBCNT会立即生效,这通常只在调试或强制同步时使用,正常运行时不要动它。

TBPHS (Time-Base Phase Register): 相位偏移量这个寄存器定义了同步事件发生时,TBCNT被装载的值。它用于设置从PWM模块之间的相位差。假设主模块TBPRD=1000,从模块TBPRD也是1000。如果将从模块的TBPHS设为250,并使能PHSEN,那么当主模块发出同步信号时,从模块的计数器会从250开始计数,它的所有波形事件都会比主模块延迟1/4个周期。

TBSTS (Time-Base Status Register): 运行状态监视器这个寄存器主要用于诊断。CTRMAX位告诉你计数器是否曾溢出(达到0xFFFF),SYNCI位记录是否有外部同步事件发生,CTRDIR则实时显示计数器当前是向上还是向下计数。在调试复杂同步逻辑时,这些状态位非常有用。

2.2 时基模块初始化代码示例与避坑指南

理论说完了,来看一段典型的时基初始化代码(以C语言为例,假设使用TI的DriverLib库或类似寄存器操作):

void InitEPwm1TimeBase(void) { // 1. 首先,停止计数器,确保在安全状态下配置 EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_FREEZE; // 停止计数 // 2. 配置时钟预分频。假设SYSCLKOUT=150MHz,目标TBCLK=75MHz // HSPCLKDIV默认是/2, CLKDIV默认是/1, 正好是75MHz,所以这里可以不用改。 // EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_HSPCLKDIV_2; // EPwm1Regs.TBCTL.bit.CLRDIV = TB_CLKDIV_1; // 3. 设置PWM频率为20kHz (TBCLK=75MHz, 采用Up-Down计数) EPwm1Regs.TBPRD = 1875; // 周期值 = TBCLK / (2 * Fpwm) = 75e6 / (2*20000) // 4. 设置计数模式为向上-向下计数 EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // 5. 配置相位相关(假设此模块作为从模块,需要与EPwm2同步) EPwm1Regs.TBPHS.half.TBPHS = 0; // 相位偏移设为0,即同步后立即从0开始计数 EPwm1Regs.TBCTL.bit.PHSEN = TB_ENABLE; // 使能同步时加载相位 EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // 同步输出选择为输入同步,即透传 // 6. 配置周期寄存器为影子模式(安全!) EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW; // 7. 配置仿真行为:自由运行,这样在代码调试暂停时,PWM输出不会停止。 // 这对于驱动电机或电源至关重要,避免调试停顿时导致失控。 EPwm1Regs.TBCTL.bit.FREE_SOFT = FREE_SOFT_FREE; }

避坑要点:

  • 顺序很重要:一定要先停止计数器(CTRMODE=冻结),再配置其他参数,尤其是TBPRD。否则在计数器运行时更改周期,可能导致不可预测的波形。
  • 影子寄存器是朋友:对于TBPRD以及后面会讲��的CMPA/CMPB,务必使用影子模式。这是保证PWM波形稳定、无毛刺切换的基石。
  • 同步信号理解SYNCOSEL选择同步信号的来源。TB_SYNC_IN表示使用外部输入同步信号。如果你需要构建一个同步链(如EPwm1同步EPwm2,EPwm2再同步EPwm3),就需要正确设置每个模块的SYNCOSEL
  • 仿真模式设置FREE_SOFT位决定了你在CCS中设置断点调试时,PWM的行为。对于真实的功率硬件,务必设置为FREE_RUN(自由运行),否则一旦CPU暂停,PWM输出停止,电机可能失速,电源可能过压。

3. 计数器比较模块:PWM的“雕刻刀”

时基模块产生了均匀的“心跳”,而计数器比较模块,就是在这心跳线上刻下标记,告诉系统:“当心跳数数到这里时,该干点啥了”。这个“啥”,就是改变PWM输出引脚的电平。这是决定PWM占空比的核心。

3.1 比较寄存器与影子缓冲机制

比较模块的核心是两个比较寄存器:CMPA和CMPB。它们的作用非常简单:硬件会实时将TBCNT的值与CMPA/CMPB的值进行比较,相等时,就产生一个事件(CTR=CMPA或CTR=CMPB事件)。这个事件会被送到下一个模块——动作限定器去执行具体操作。

为什么需要CMPA和CMPB两个?这提供了极大的灵活性。例如,在向上-向下计数模式下:

  • 你可以设置CMPA在计数器上升阶段触发一个动作(比如置高),在下降阶段再触发另一个动作(比如拉低),从而生成一个中央对称的PWM波。
  • CMPB则可以用来生成另一个不同占空比的PWM波(在EPWMxB输出),或者用于更复杂的波形生成,比如在特定时刻插入一个触发事件用于ADC采样。

影子寄存器机制详解这是eHRPWM的一个关键特性。以CMPA为例,它实际上有两套寄存器:影子寄存器(Shadow Register)活动寄存器(Active Register)。我们软件读写的是影子寄存器。而硬件真正用来和TBCNT做比较的,是活动寄存器。

那么,影子寄存器里的值什么时候“搬”到活动寄存器呢?这就是由CMPCTL寄存器中的LOADAMODELOADBMODE位控制的。常见的模式有:

  • LOAD_ON_CNTR_ZERO:在TBCNT等于0时加载。
  • LOAD_ON_CNTR_PRD:在TBCNT等于TBPRD时加载。
  • LOAD_ON_CNTR_ZERO_OR_PRD:在TBCNT等于0或TBPRD时加载(在Up-Down模式下,一个周期有两次加载机会)。

这种机制的巨大优势在于“双缓冲”。你可以在任何时候(比如中断服务程序里)安全地更新影子寄存器CMPA的值,但这个新值不会立即生效,不会打断当前正在输出的PWM周期。它会等到下一个指定的加载点(如计数器归零)才生效,从而实现了PWM占空比的无毛刺、平滑切换。在电机控制中,这用于实现电流环的平滑调节;在数字电源中,这用于实现输出电压的平滑调整。

3.2 比较控制寄存器CMPCTL的实战配置

CMPCTL寄存器控制着CMPA和CMPB的加载行为。

void InitEPwm1Compare(void) { // 1. 配置CMPA和CMPB为影子模式(强烈推荐) EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; // 2. 配置影子寄存器的加载时机 // 对于Up-Down模式,通常选择在CTR=PRD时加载,这样新的比较值在下个周期开始时生效。 // 也可以选择CTR=ZERO,效果类似。但避免使用CTR=ZERO_OR_PRD,除非你有特殊需求, // 因为它可能导致一个周期内比较值变化两次,产生不对称波形。 EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_PRD; // CMPA在计数器达到周期值时加载 EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_PRD; // CMPB在计数器达到周期值时加载 // 3. 初始化比较值(占空比) // 假设我们要在EPWM1A上产生一个50%占空比的PWM(Up-Down模式) // 占空比 = CMPA / TBPRD EPwm1Regs.CMPA.half.CMPA = 937; // 50% of 1875 = 937.5,取整937 // 假设我们暂时不用CMPB EPwm1Regs.CMPB = 0; // 4. (可选)检查影子寄存器状态位 // 在频繁更新CMPA/CMPB的中断里,可以先检查SHDWAFULL/SHDWBFULL位, // 如果为1,说明上一次写入的值还未被加载,此时再写入会覆盖掉未加载的值。 // 通常简单的做法是直接写,硬件FIFO只有一级,但软件设计上应注意更新速率不要超过PWM频率。 }

关键点解析:

  • SHDWAFULL标志位:这是一个非常重要的状态位。当你向CMPA影子寄存器写入一个新值时,该位被置1。只有当指定的加载事件(如CTR=PRD)发生后,硬件将影子寄存器的值载入活动寄存器,这个标志位才会自动清零。在高速实时控制中,如果你在中断中更新CMPA,最好先检查这个位。如果它为1,意味着你上次设定的值还没生效,此时再写入新值会覆盖掉旧的、未生效的值,可能导致控制紊乱。一个稳健的策略是:如果SHDWAFULL=1,则跳过本次写入,或者记录一个“更新请求”,等待下一周期再处理。
  • 立即模式(Immediate Mode):将SHDWAMODE设为1就是立即模式。此时,你对CMPA的写入会直接作用到活动寄存器,立即影响当前PWM周期。除非你在做非常特殊的调试或需要极快响应(且能承担波形畸变风险)的场景,否则不要使用立即模式。在电机和电源控制中,这几乎是禁忌。

4. 动作限定模块:事件的“翻译官”与“执行者”

比较模块只负责发出“时间到了”的事件(CTR=CMPA, CTR=CMPB, CTR=PRD, CTR=ZRO)。至于这个事件具体要做什么——是把输出引脚拉高、拉低,还是翻转——则由动作限定(Action-Qualifier)模块来决定。它是连接“时间事件”和“物理输出”的桥梁。

4.1 动作控制寄存器AQCTLA/AQCTLB:定义波形蓝图

这是整个eHRPWM配置中最具技巧性,也最能体现其强大功能的部分。AQCTLA控制EPWMxA输出引脚的动作,AQCTLB控制EPWMxB输出引脚的动作。每个寄存器控制着在6个特定事件发生时,输出引脚应该做什么。

这6个事件是:

  • ZRO:计数器等于0。
  • PRD:计数器等于周期值TBPRD。
  • CAU:计数器等于CMPA,且计数器正在向上计数。
  • CAD:计数器等于CMPA,且计数器正在向下计数。
  • CBU:计数器等于CMPB,且计数器正在向上计数。
  • CBD:计数器等于CMPB,且计数器正在向下计数。

对于每个事件,你可以定义4种动作:

  • 00:不采取任何行动(忽略该事件)。
  • 01:强制输出低电平(Clear)。
  • 10:强制输出高电平(Set)。
  • 11:翻转输出电平(Toggle)。

如何用这些事件“拼”出PWM波形?我们以最常用的向上-向下计数、非对称PWM生成为例,目标是让EPWMxA输出一个中央对称的PWM波。

  1. 在计数器从0开始向上计数时,我们希望输出为低电平。
  2. 当计数器向上数到CMPA的值时(CAU事件),我们希望输出翻转为高电平。
  3. 当计数器达到峰值TBPRD后开始向下计数,数到CMPA的值时(CAD事件),我们希望输出再翻转为低电平。
  4. 计数器回到0,开始下一个周期。

对应的AQCTLA配置就是:

  • ZRO: 无动作 (00) 或 设为低 (01)。设为低电平可以确保周��开始时状态明确。
  • PRD: 无动作 (00)。
  • CAU: 设为高 (10)。注意:这里不能用Toggle。因为如果ZRO时已经是低,CAU时Toggle会变成高,看似正确。但如果系统启动时状态不确定,Toggle可能导致错误。所以用Set/Clear更可靠。
  • CAD: 设为低 (01)。

那么,AQCTLA= (CAD=01, CAU=10, PRD=00, ZRO=01)。用代码表示:

void InitEPwm1ActionQualifier(void) { // 配置EPWM1A输出 (AQCTLA) // 在Up-Down模式下,生成一个中央对称的PWM波 EPwm1Regs.AQCTLA.bit.ZRO = AQ_CLEAR; // CTR=0时,输出低 (确保起始状态) EPwm1Regs.AQCTLA.bit.PRD = AQ_NO_ACTION; // CTR=TBPRD时,不动作 EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; // CTR=CMPA且向上计数时,输出高 EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR; // CTR=CMPA且向下计数时,输出低 // 如果我们想用CMPB在EPWM1B上生成另一个PWM,配置AQCTLB // EPwm1Regs.AQCTLB.bit.CBU = AQ_SET; // EPwm1Regs.AQCTLB.bit.CBD = AQ_CLEAR; // 注意:也需要配置CMPB的值,并可能配置ZRO/PRD事件 }

为什么不用Toggle?Toggle看似简洁,但在复杂的启动、关断、故障处理序列中,输出状态可能变得不可预测。而使用明确的Set和Clear,你可以精确控制每个边沿,逻辑更清晰,抗干扰能力更强。在工业产品中,可靠性优先,我强烈推荐使用Set/Clear组合。

4.2 软件强制与连续强制寄存器

动作限定模块还提供了AQSFRC(软件强制)和AQCSFRC(连续软件强制)寄存器,允许软件直接干预输出状态,而不依赖于计数器事件。

  • AQSFRC(One-Time Force):用于产生一次性的强制动作。比如,你想在某个特定时刻(非计数器比较点)立即将输出拉高或拉低。写OTSFA位可以触发一次对EPWMxA的强制,ACTSFA定义强制动作(Set/Clear/Toggle)。这个位是自清除的,写1触发后硬件会自动清零。这在注入特定测试脉冲时很有用。
  • AQCSFRC(Continuous Force):用于持续强制输出为高、低或禁用强制。CSFACSFB位可以分别将EPWMxA和EPWMxB输出锁定在高或低电平,覆盖所有由动作限定器产生的事件。这是一个非常强大的功能,常用于:
    1. 安全关断:在检测到故障时,立即将CSFACSFB设为强制低,关闭所有PWM输出,保护功率器件。
    2. 调试模式:强制输出高或低,方便测量电路或驱动静态工作点。
    3. 互补输出对中的独立控制:在死区模块之前,你可以强制其中一个输出为固定电平,而另一个仍由PWM控制。
// 示例:在故障处理中断中,强制关闭PWM输出 void Fault_ISR(void) { // 连续强制EPWM1A和EPWM1B输出为低电平 EPwm1Regs.AQCSFRC.bit.CSFA = AQCSF_FORCE_LO; EPwm1Regs.AQCSFRC.bit.CSFB = AQCSF_FORCE_LO; // ... 其他故障处理逻辑 } // 示例:清除强制,恢复正常PWM操作 void ClearFault(void) { EPwm1Regs.AQCSFRC.bit.CSFA = AQCSF_DISABLE; EPwm1Regs.AQCSFRC.bit.CSFB = AQCSF_DISABLE; }

重要提示:连续强制模式的优先级高于动作限定器。一旦使能,动作限定器的事件将被忽略,直到你禁用强制。这为安全处理提供了最高优先级的硬件通路。

5. 死区生成模块:功率驱动的“安全卫士”

在驱动H桥、半桥等桥式电路时,上下两个开关管(通常是MOSFET或IGBT)绝对不能同时导通,否则会造成电源直通短路,瞬间烧毁器件。死区(Dead-Time)就是在控制上下管导通的PWM信号中,插入一个两者都为关断状态的小时间间隔,确保一个管子完全关断后,另一个管子才开启。

5.1 死区控制寄存器DBCTL:模式与极性配置

死区模块的配置集中在DBCTL寄存器,理解它的三个控制字段是关键。

1. OUT_MODE (Bits 1-0): 输出模式控制这是死区功能的开关。

  • 00:完全旁路。EPWMxA和EPWMxB信号直接来自动作限定器,不经过死区模块。这是默认值,也是调试初期验证基本PWM波形时应使用的模式。
  • 01:禁用上升沿延迟。EPWMxA直通,EPWMxB信号接受下降沿延迟。这是最常用的“高有效互补”模式,EPWMxA作为原信号,EPWMxB是其互补信号并加入了死区。
  • 10:禁用下降沿延迟。EPWMxB直通,EPWMxA信号接受上升沿延迟。
  • 11:完全使能。EPWMxA接受上升沿延迟,EPWMxB接受下降沿延迟。这种模式用于需要双边独立延迟的特殊场景,较少使用。

2. IN_MODE (Bits 5-4): 输入源选择它决定死区延迟模块的输入信号来自哪里。

  • 00 (默认):EPWMxA In作为上升沿和下降沿延迟的输入源。这是经典配置,用于从EPWMxA生成带死区的互补对(EPWMxA_OUT, EPWMxB_OUT)。
  • 01:EPWMxB In作为上升沿延迟输入,EPWMxA In作为下降沿延迟输入。这可以实现信号交叉输入,用于更复杂的逻辑。
  • 10:EPWMxA In作为上升沿延迟输入,EPWMxB In作为下降沿延迟输入。
  • 11:EPWMxB In作为上升沿和下降沿延迟的输入源。

对于典型的半桥驱动,我们使用OUT_MODE=01 (EPWMxB加死区),IN_MODE=00 (输入源为EPWMxA)。这样,动作限定器产生的原始PWM波形在EPWMxA上,而其互补的、加入了死区的波形在EPWMxB上。

3. POLSEL (Bits 3-2): 极性选择在信号经过延迟后,输出前可以选择是否反相。这对于驱动不同配置的栅极驱动器非常重要。

  • 00 (Active High, AH):都不反相。延迟后的EPWMxA_OUT高电平有效,延迟后的EPWMxB_OUT高电平有效。这意味着输出高电平时开关管导通。
  • 01 (Active Low Complementary, ALC):EPWMxA_OUT反相。EPWMxA_OUT低有效,EPWMxB_OUT高有效。常用于上管使用P型器件或需要低电平开启的驱动器。
  • 10 (Active High Complementary, AHC):EPWMxB_OUT反相。EPWMxA_OUT高有效,EPWMxB_OUT低有效。这是最最常见的模式,用于驱动标准的半桥,其中上管和下管都是N型MOSFET,且栅极驱动器是高电平导通。此时,EPWMxA_OUT直接驱动下管,EPWMxB_OUT反相后驱动上管(通常还需经过电平移位)。
  • 11 (Active Low, AL):两者都反相。两个输出都是低有效。

配置示例:驱动一个典型的N-MOSFET半桥

  • 目标:EPWM1A输出高电平有效信号驱动下管,EPWM1B输出低电平有效信号驱动上管,并插入死区。
  • 动作限定器配置:AQCTLA生成一个高有效的PWM波(如前述CAU=SET, CAD=CLEAR)。
  • 死区配置:
    • OUT_MODE = 0x1(01b): 仅对EPWMxB启用下降沿延迟。
    • IN_MODE = 0x0(00b): 输入源为EPWMxA。
    • POLSEL = 0x2(10b): AHC模式,EPWMxB输出反相。
void InitEPwm1DeadBand(void) { // 配置死区参数 EPwm1Regs.DBRED = 75; // 上升沿延迟值,单位是TBCLK周期。假设TBCLK=75MHz,则延迟1us。 EPwm1Regs.DBFED = 75; // 下降沿延迟值,设为相同,产生对称死区。 // 配置死区控制寄存器 // 使用模式:EPWMxA直通(高有效),EPWMxB为互补信号并加入下降沿延迟,且EPWMxB反相(低有效) EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // 实际上,对于典型半桥,我们只需要EPWMxB加死区。 // 更精确的配置是: EPwm1Regs.DBCTL.bit.OUT_MODE = DB_DISABLE_RED; // 01b: 禁用上升沿延迟,使能下降沿延迟给EPWMxB EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; // 10b: AHC模式,EPWMxB反相 EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL; // 00b: 输入源为EPWMxA for both }

5.2 死区时间计算与寄存器设置

死区时间由DBRED(上升沿延迟)和DBFED(下降沿延迟)两个10位寄存器控制。延迟时间 = 寄存器值 ×TBCLK周期。

例如,TBCLK = 75MHz,周期为13.33ns。要插入1us的死区时间:寄存器值 = 死区时间 / TBCLK周期 = 1us / 13.33ns ≈ 75

重要注意事项

  • 死区时间并非越长越好。太长的死区会降低最大占空比,增加波形失真,降低效率。需要根据功率器件的开关特性(特别是关断���间)来设定,通常留出2-3倍的余量。例如,MOSFET关断时间约50ns,那么死区可设为150ns。
  • DBREDDBFED是独立的。在不对称开关器件或特殊驱动逻辑中,可能需要设置不同的上升沿和下降沿延迟。
  • 死区插入的位置:以OUT_MODE=01(EPWMxB加死区)和POLSEL=10(AHC)为例。假设原始EPWMxA是一个高电平脉冲。死区模块会:
    1. EPWMxA_OUT = 原始EPWMxA(高有效)。
    2. 生成EPWMxB的互补信号(此时已是低有效),然后在这个互补信号的下降沿(对应原信号的上升沿)和上升沿(对应原信号的下降沿)各插入一段延迟(由DBFED控制),确保在状态切换时,EPWMxA_OUT和EPWMxB_OUT同时为低(即两个管子都关断)的时间至少为设定的死区时间。

6. 高级主题与实战避坑指南

掌握了以上四个核心子模块,你已经可以应对大多数eHRPWM应用了。但在实际复杂系统中,还有一些高级特性和常见的“坑”需要注意。

6.1 高分辨率PWM扩展

eHRPWM中的“HR”代表高分辨率。标准PWM的占空比分辨率受限于TBCLK频率和TBPRD值。例如,TBCLK=75MHz,PWM频率=20kHz,则一个计数周期对应的时间是1/(75MHz) ≈ 13.33ns,而PWM周期是50us,理论分辨率是13.33ns / 50us ≈ 0.0267%。但对于某些需要极高精度调制的应用(如高性能数字电源的电压纹波控制),这可能还不够。

高分辨率PWM扩展通过微调比较匹配点的位置,可以将边沿定位的精度提高到皮秒级。它主要涉及CMPAHRTBPHSHR这两个寄存器。CMPAHR是CMPA的扩展,提供了额外的8位小数部分。启用HRPWM后,实际的比较值 =CMPA + (CMPAHR/256)。这需要配合特定的MEP(Micro-Edge Positioner)逻辑和时钟校准。启用HRPWM相对复杂,需要配置HRCNFG等寄存器,并且对系统时钟质量要求很高。在一般电机控制中,标准分辨率已足够,但在通信电源、高性能D类音频功放中,HRPWM能显著提升性能。

6.2 同步与相位控制实战

多模块同步是eHRPWM的强项。假设我们有三个PWM模块驱动一个三相逆变器。

  1. 主模块设置:将EPwm1设为同步源。EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO。这样,当EPwm1的计数器归零时,它会产生一个EPWMSYNCO输出信号。
  2. 从模块设置:将EPwm2和EPwm3的EPWMSYNCI输入连接到EPwm1的EPWMSYNCO输出(这通常在芯片内部通过寄存器EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN来配置,表示接受外部同步输入)。同时,使能它们的相位加载PHSEN=1,并设置不同的TBPHS值(如0, 1200, 2400,假设TBPRD=3600,则相位差120度)。
  3. 软件强制同步:在系统初始化所有PWM模块后,可以通过写主模块的TBCTL.bit.SWFSYNC = 1来产生一个软件同步脉冲,让所有从模块的计数器同时从各自的相位值开始计数,实现严格的相位对齐。

避坑点:同步信号是边沿触发的。确保在主模块的计数器运行稳定后再触发同步。通常的初始化顺序是:配置所有模块参数 -> 启动主模块计数器 -> 延迟一小段时间 -> 软件强制同步。

6.3 常见问题排查实录

  1. 没有PWM输出?

    • 检查时钟:首先确认系统时钟SYSCLKOUT和eHRPWM外设时钟是否使能。检查TBCTL中的CLKDIVHSPCLKDIV,确保TBCLK不为零。
    • 检查计数器:确认TBCTL.CTRMODE不是停止模式(11b)。读取TBCNT寄存器,看它是否在循环计数。
    • 检查输出引脚:确认GPIO复用功能已正确配置为PWM输出模式,而不是普通的I/O。
    • 检查动作限定器:确认AQCTLA/B已为相应的事件(如CAU, CAD)配置了Set/Clear动作,而不是全部为“无动作”。
    • 检查强制输出:确认AQCSFRC没有将输出强制为高或低。
  2. PWM频率不对?

    • 公式核对:牢记公式。向上计数模式:Fpwm = TBCLK / (TBPRD + 1)。向上-向下计数模式:Fpwm = TBCLK / (2 * TBPRD)。仔细计算TBCLK
    • 影子寄存器:确认你修改的是影子寄存器值,并且它是否已加载?检查TBCTL.PRDLD模式,并在修改TBPRD后等待一个完整的PWM周期再测量。
  3. 死区不生效或效果不对?

    • OUT_MODE配置:最常见错误是OUT_MODE设成了00(旁路模式)。确保它被设置为01或10或11以启用死区。
    • 极性看反:用示波器同时测量EPWMxA和EPWMxB。根据POLSEL的设置,理解哪个应该是高有效,哪个应该是低有效,是否与你的栅极驱动器需求匹配。
    • 延迟值太小DBRED/DBFED的值可能设得太小,小于器件的关断时间,死区效果不明显。也可能设得太大,用示波器测量两个信号之间的间隔确认。
  4. 占空比修改后波形出现毛刺或跳动?

    • 影子寄存器未使用:你是否在直接写活动寄存器(CMPCTL.SHDWAMODE=1)?或者在错误的时间点写入了影子寄存器?确保在影子模式下,并在稳定的时刻(如CTR=0的中断里)更新CMPA/CMPB。
    • SHDWAFULL问题:在高速更新时,你是否在SHDWAFULL=1时覆盖了影子寄存器?需要在写入前检查该位,或确保更新频率不超过PWM频率。
  5. 多个PWM模块不同步?

    • 同步源:检查每个模块的SYNCOSEL设置,确认同步链正确。
    • 相位加载使能:确认从模块的PHSEN位已使能。
    • 软件同步时机:软件同步SWFSYNC应在所有模块初始化完成、主模块开始运行后执行一次。

调试eHRPWM,示波器是你的最佳伙伴。同时捕获EPWMxA和EPWMxB,观察计数器事件(ZRO, PRD, CAU, CAD)与输出边沿的关系,结合寄存器配置,可以快速定位问题所在。理解每个寄存器位对应的硬件行为,而不是死记配置值,才能让你在遇到任何异常波形时都能游刃有余。