TI C2000 DSP ePWM模块实战:从寄存器配置到电机驱动代码
1. 从寄存器手册到实战代码:ePWM模块配置的深度解析
如果你正在使用TI的C2000系列DSP,尤其是TMS320F2806x这类芯片做电机控制、数字电源或者任何需要精密PWM波形的应用,那么ePWM模块绝对是你绕不开的核心。官方技术手册(TRM)里那动辄几十页的寄存器描述,常常让人看得头大,感觉每个比特位都认识,但连起来就不知道如何下手了。我当年也是这么过来的,对着AQCTLA、DBCTL、TZSEL这些寄存器名字发懵。今天,我就结合自己十多年在电机驱动和电源项目上的踩坑经验,抛开那些晦涩的官方术语,用最直白的方式,带你把这些关键寄存器“盘”明白。我们的目标不是复读手册,而是让你看完就能写出稳健、高效的驱动代码,理解每一个配置项背后的“为什么”。
很多人觉得寄存器配置就是照着手册填值,但真正做过产品的人都知道,差之毫厘,谬以千里。一个死区时间算错,可能瞬间烧掉一套昂贵的IGBT模块;Trip-Zone配置不当,系统可能在故障时毫无反应,造成更大损失。ePWM的强大,正体现在它通过硬件寄存器实现的精细控制和快速保护,但这需要开发者真正理解其运作机制。接下来,我们就以动作限定器、死区、Trip-Zone和事件触发这几个最核心、也最容易出错的子模块为例,深入它们的寄存器世界。
2. 动作限定器(AQ):PWM波形生成的“雕刻刀”
动作限定器子模块是ePWM的灵魂,它决定了PWM输出波形具体长什么样。你可以把它想象成一位雕刻师,时间基计数器(TBCTR)的数值是他的刻刀轨迹,而AQCTLA和AQCTLB这两个寄存器,就是他手中的雕刻图样,规定了刻刀到达特定位置(比如零点、周期点、比较匹配点)时,要对输出引脚(EPWMxA和EPWMxB)进行何种“雕刻动作”——置高(Set)、拉低(Clear)还是翻转(Toggle)。
2.1 AQCTLA/AQCTLB寄存器:定义动作的“规则手册”
手册里把每个比特位都列出来了,但我们得抓住精髓。这两个寄存器结构完全对称,分别控制EPWMxA和EPWMxB。每个寄存器里都包含以下几组关键位域,它们都是在特定的计数器事件发生时触发:
- ZRO (Bits 1-0): 当计数器值等于0时采取的动作。
- PRD (Bits 3-2): 当计数器值等于周期值(TBPRD)时采取的动作。
- CAU/CAD (Bits 5-4 / Bits 7-6): 当计数器值等于比较寄存器A(CMPA)的值,且计数器正在递增(CAU)或递减(CAD)时采取的动作。
- CBU/CBD (Bits 9-8 / Bits 11-10): 当计数器值等于比较寄存器B(CMPB)的值,且计数器正在递增(CBU)或递减(CBD)时采取的动作。
每个位域的取值(00, 01, 10, 11)对应“无动作”、“拉低”、“置高”、“翻转”。这里有一个极其关键的细节,也是新手最容易忽略的:在递增-递减计数模式下,计数器等于0时,方向被定义为递增;计数器等于周期值时,方向被定义为递减。这个定义直接影响CAU/CAD、CBU/CBD的触发条件,在配置非对称PWM或中心对齐PWM时至关重要。
实操心得一:如何用AQ寄存器生成一对互补带死区的PWM?这是电机控制H桥驱动的标准需求。假设我们使用递增-递减模式,希望生成中心对齐的PWM,EPWMxA和EPWMxB互补。一个经典的配置思路如下:
- 配置TBCTR:工作在递增-递减模式(TBCTL[CTRMODE]=00)。
- 配置AQCTLA:
- ZRO = 01 (Clear): 计数器从0开始递增,此时将EPWMxA拉低。
- PRD = 10 (Set): 计数器到达周期值后转向递减,此时将EPWMxA置高。
- CAU = 01 (Clear): 计数器递增过程中,当值等于CMPA时,将EPWMxA拉低。这决定了PWM的下降沿。
- CAD = 10 (Set): 计数器递减过程中,当值等于CMPA时,将EPWMxA置高。这决定了PWM的上升沿。
- 配置AQCTLB:
- 通常将EPWMxB配置为与EPWMxA相反的逻辑。一种简单方法是利用“翻转”动作。
- ZRO = 10 (Set): 计数器为0时,EPWMxB置高(与EPWMxA的Clear相反)。
- PRD = 01 (Clear): 计数器为周期值时,EPWMxB拉低(与EPWMxA的Set相反)。
- CAU = 10 (Set): 计数器递增等于CMPA时,EPWMxB置高(在EPWMxA拉低的时刻,EPWMxB置高,形成互补)。
- CAD = 01 (Clear): 计数器递减等于CMPA时,EPWMxB拉低(在EPWMxA置高的时刻,EPWMxB拉低)。
通过这样配置,仅通过改变CMPA的值,就能同时、同步地控制EPWMxA和EPWMxB的占空比,并且两者是严格互补的。后续的死区模块会在这个基础上插入延迟,防止直通。
2.2 软件强制寄存器(AQSFRC/AQCSFRC):调试与控制的“紧急开关”
动作限定器通常是基于计数器事件自动运行的,但有时我们需要软件主动干预输出状态,这就是AQSFRC和AQCSFRC的用武之地。
AQSFRC (One-Time Software Force): 一次性软件强制。你可以通过设置
OTSFA/B位来触发一次强制事件,并通过ACTSFA/B位指定这次强制事件的动作(Clear/Set/Toggle)。这个位在写入后会自动清零,非常适合在调试中手动触发一个边沿变化,或者在某些特定控制序列中插入一个脉冲。注意:一次性强制事件的动作不受计数器方向(CNT_dir)限制,这是它与基于事件的AQ动作的一个重要区别。
AQCSFRC (Continuous Software Force): 连续软件强制。通过
CSFA/B位,你可以强制输出持续为高或低,完全覆盖由AQCTL和计数器事件产生的输出。这在故障安全处理或使能/禁用功率级时非常有用。它有两种模式:- 立即模式:在下一个TBCLK边沿立即生效。
- 影子模式:需要结合AQSFRC[RLDCSF]配置,在下次影子寄存器加载到活动寄存器时才生效。这保证了同步更新,避免在PWM周期中间产生毛刺。
实操心得二:何时使用软件强制?
- 系统初始化阶段:在PWM模块开始运行前,使用连续强制将输出置为已知的安全状态(比如全低),确保功率管不会误开通。
- 故障响应:当Trip-Zone等硬件保护触发后,除了硬件动作,软件也可以立刻通过连续强制将输出锁定在安全状态,形成双重保护。
- 调试与测试:用一次性强制来手动产生一个脉冲,可以非常方便地用示波器测量系统响应延迟,或者验证后续电路是否正常。
3. 死区生成器(DB):功率电路安全的“守护神”
死区时间是H桥或半桥电路中,为了防止上下管同时导通(直通)而设置的共同关闭时间。ePWM的死区生成器模块硬件实现此功能,精度高且不占用CPU资源。
3.1 DBCTL寄存器:死区工作模式的“总控台”
DBCTL寄存器控制了死区模块的三大核心:输入源选择、输出模式控制和极性控制。手册中的图3-29(死区模块框图)是理解这一切的关键,务必对照查看。
OUT_MODE (Bits 1-0): 输出模式控制。这是首先要配置的。
00:旁路模式。死区功能完全关闭,AQ的输出直接送到下一级。在不需要死区或者调试AQ输出时使用。01:仅启用下降沿延迟。EPWMxA直通,EPWMxB输出经过下降沿延迟的信号。10:仅启用上升沿延迟。EPWMxA输出经过上升沿延迟的信号,EPWMxB直通。11:完全启用。EPWMxA输出带上升沿延迟,EPWMxB输出带下降沿延迟。这是最常用的互补PWM带死区模式。
IN_MODE (Bits 5-4): 输入模式控制。决定延迟模块的输入信号来自哪里。
00:默认模式。EPWMxA In(来自AQ)同时作为上升沿和下降沿延迟的输入。这是最经典的配置,用一个AQ信号生成一对带死区的互补信号。01/10/11:这些模式允许你分别指定上升沿和下降沿延迟的输入源来自EPWMxA还是EPWMxB。这用于更复杂的场景,比如你需要基于两个独立的AQ信号来生成带死区的输出。
POLSEL (Bits 3-2): 极性选择。在信号送入PWM斩波器之前,可以选择是否反相。
00(AH): 都不反相。01(ALC): 反相EPWMxA。常用于驱动需要低电平有效的栅极驱动器。10(AHC): 反相EPWMxB。11(AL): 两者都反相。
实操心得三:死区配置的经典流程与计算假设我们要为上半桥(EPWMxA)和下半桥(EPWMxB)生成互补带死区的PWM,驱动电平为高有效。
- 确定需求:假设需要插入的死区时间为
T_dead = 500 ns,系统时钟TBCLK = 10 MHz (周期100 ns)。 - 计算延迟计数值:死区延迟计数器是10位的。
DBRED = DBFED = T_dead / TBCLK = 500ns / 100ns = 5。将十进制5写入DBRED和DBFED寄存器。 - 配置DBCTL:
OUT_MODE = 11:完全启用上升沿和下降沿延迟。IN_MODE = 00:使用EPWMxA In作为公共输入源(这是我们之前AQ模块生成的“原始”PWM信号)。POLSEL = 00:输出不反相(高有效)。
- 最终波形效果:对于EPWMxA(上半桥),其上升沿会比AQ输出的原始信号晚
5 * TBCLK;对于EPWMxB(下半桥),其下降沿会比AQ输出的原始互补信号晚5 * TBCLK。这样就确保了一个管子关闭后,另一个管子要等待500ns后才开启。
重要警告:
HALFCYCLE位(Bit 15)需要特别注意。当它为0时,死区计数器以TBCLK频率工作;为1时,以2倍TBCLK频率工作。这相当于将死区时间分辨率提高了一倍。但务必确保你的系统时钟配置能支持这个更高的频率,否则可能导致时序错误。在大部分应用中,保持为0(全周期时钟)即可。
4. Trip-Zone (TZ) 子模块:硬件级故障保护的“闪电响应”
在工业控制中,软件响应故障太慢。Trip-Zone模块提供了基于硬件引脚的快速保护,能在纳秒级内强制PWM输出进入安全状态(高、低或高阻态)。
4.1 TZSEL与TZCTL寄存器:故障源的“哨兵”与“处置官”
故障保护流程可以理解为:TZSEL寄存器决定“哪些情况算故障”(拉响警报),TZCTL寄存器决定“发生故障后怎么办”(执行应急预案)。
TZSEL (Trip-Zone Select): 用于使能具体的故障源。它分为两大类:
- One-Shot (OSHT): 一次性故障。一旦触发,除非软件手动清除(通过TZCLR),否则保护状态将一直保持。适用于过流、短路等严重故障。
- Cycle-By-Cycle (CBC): 逐周期故障。当故障条件在某个PWM周期内出现时,该周期内采取保护动作,一旦计数器回到0,保护条件自动复位。适用于需要每个周期都进行限流的场景。
- 源可以是外部引脚TZ1-TZ6,也可以是内部数字比较器事件(DCAEVT1/2, DCBEVT1/2)。例如,
TZSEL[CBC1] = 1就表示使能TZ1引脚作为逐周期故障源。
TZCTL (Trip-Zone Control): 定义当故障发生时,输出引脚EPWMxA和EPWMxB应采取什么动作。
00: 高阻态(High-Z)。这是最彻底的安全状态,直接断开驱动。常用于IGBT驱动,防止误触发。01: 强制为高。10: 强制为低。11: 无动作(忽略故障)。- 你可以为TZA、TZB以及四个数字比较事件(DCAEVT1/2, DCBEVT1/2)分别配置动作。例如,在电机驱动中,我们通常将TZCTL[TZA]和TZCTL[TZB]都配置为
10(强制为低),这样一旦故障触发,上下桥臂全部关闭,电机刹车。
4.2 TZFLG, TZCLR, TZFRC寄存器:状态、清除与强制
- TZFLG (Trip-Zone Flag): 状态标志寄存器。当故障事件发生时,对应的标志位(如CBC、OST)会被硬件置1。INT位尤其重要,它表示是否产生了Trip-Zone中断。即使故障条件已消失,这些标志位也会保持置1,直到被软件清除。
- TZCLR (Trip-Zone Clear): 清除寄存器。向对应的位写1,可以清除TZFLG中相应的标志位。例如,处理完一次OST故障后,需要向
TZCLR[OST]写1来清除OST标志,否则系统会认为故障依然存在。 - TZFRC (Trip-Zone Force): 软件强制寄存器。你可以通过软件写这个寄存器来模拟一个故障事件,强制置起对应的TZFLG标志位,并触发配置在TZCTL中的动作。这在系统自检、功能安全验证时非常有用。
实操心得四:构建一个稳健的故障处理流程
- 初始化配置:
// 使能TZ1引脚为逐周期故障源,TZ2为一次性故障源 EPwm1Regs.TZSEL.bit.CBC1 = 1; // TZ1 -> CBC EPwm1Regs.TZSEL.bit.OSHT2 = 1; // TZ2 -> OSHT // 配置故障动作:全部强制输出低电平 EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_LO; // 2 EPwm1Regs.TZCTL.bit.TZB = TZ_FORCE_LO; // 2 // 使能Trip-Zone中断(如果需要) EPwm1Regs.TZEINT.bit.OST = 1; // 使能一次性故障中断 - 中断服务程序(ISR)处理:
__interrupt void epwm1_tz_isr(void) { if (EPwm1Regs.TZFLG.bit.OST == 1) { // 1. 执行紧急处理:记录故障日志,关闭系统使能等 SystemErrorHandler(ERROR_OVER_CURRENT); // 2. 清除故障标志 EPwm1Regs.TZCLR.bit.OST = 1; // 3. 清除PIE中断标志位 PieCtrlRegs.PIEACK.all = PIEACK_GROUP2; } // 注意:CBC故障通常不需要中断,因为每个周期会自动恢复 } - 调试技巧:在系统启动时,可以尝试用
TZFRC寄存器强制一个故障,用示波器观察PWM输出是否按TZCTL的配置变为低电平,以此验证整个硬件保护通路是否工作正常。
5. 事件触发(ET)子模块:让ADC与PWM精准同步的“节拍器”
在电机控制FOC算法中,电流采样时刻必须与PWM波形中心点严格对齐,以获得准确的相电流。ePWM的事件触发子模块就是为此而生,它能基于时间基计数器的特定事件(如等于0、等于CMPA/B),产生精准的ADC启动转换(SOC)脉冲或CPU中断。
5.1 ETSEL与ETPS寄存器:选择事件与分频
ETSEL (Event-Trigger Selection): 选择触发事件源。
SOCASEL/SOCBSEL: 选择产生ADC SOCA/SOCB脉冲的事件。常见选择有:001: TBCTR = 0x0000010: TBCTR = TBPRD100: TBCTR = CMPA 且计数器递增 (CAU事件)101: TBCTR = CMPA 且计数器递减 (CAD事件)011: TBCTR = 0 或 TBPRD (在上下计数模式中,每个周期触发两次)
INTSEL: 选择产生ePWM中断的事件。源与SOC类似。SOCAEN/SOCBEN/INTEN: 使能位。必须置1,相应的脉冲或中断才会产生。
ETPS (Event-Trigger Prescale): 事件分频与计数器。
SOCAPRD/SOCBPRD/INTPRD:分频设置。决定在第几次选定事件发生时,才产生一个脉冲/中断。例如,SOCAPRD=01表示每1个事件产生一个脉冲;SOCAPRD=10表示每2个事件产生一个脉冲���即2分频)。SOCACNT/SOCBCNT/INTCNT:事件计数器。只读,显示当前已经发生了多少次选定事件。当计数值达到PRD设置的值时,产生脉冲/中断,同时计数器自动清零。
5.2 实现FOC电流采样的经典配置
在电机控制中,我们通常在PWM波形的“谷底”或“峰顶”(即计数器等于0或周期值)进行电流采样,以避开开关噪声。对于中心对齐PWM(上下计数),一个更优的方案是在计数器等于CMPA且计数器递减(CAD事件)时采样,此时PWM占空比稳定。
配置步骤:
- 配置PWM为上下计数模式,并设置好TBPRD和CMPA。
- 配置ETSEL:
EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO; // 例如,选择在计数器为0时触发SOCA EPwm1Regs.ETSEL.bit.SOCAEN = 1; // 使能SOCA - 配置ETPS:
EPwm1Regs.ETPS.bit.SOCAPRD = ET_1ST; // 每个事件都触发一次SOCA脉冲(不分频) - 连接ADC:在SysConfig或代码中,将ePWM1的SOCA信号连接到ADC的启动转换序列。
这样,每个PWM周期,当TBCTR回到0时,ePWM模块就会自动产生一个高脉冲(EPWMxSOCA),触发ADC启动一次转换。CPU完全不需要干预,实现了硬件级的精准同步。
实操心得五:中断与SOC的协同使用
- SOC用于ADC触发:实现高精度、确定性的模拟量采样。
- 中断用于软件任务:例如,配置在
TBCTR = TBPRD(周期点)产生中断,在这个中断服务程序中,可以安全地更新下一个PWM周期的CMPA/CMPB值(因为此时计数器正在递减,远离了比较点,更新影子寄存器不会引起毛刺)。这就是所谓的“影子寄存器加载点”策略。// 在周期点中断中更新占空比 __interrupt void epwm1_isr(void) { EPwm1Regs.CMPA.half.CMPA = new_duty_cycle; // 更新CMPA影子寄存器 EPwm1Regs.ETCLR.bit.INT = 1; // 清除中断标志 PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; }
6. 寄存器配置的常见陷阱与调试技巧
即使理解了原理,实际配置时依然会遇到各种问题。下面是一些我踩过的坑和总结的技巧。
6.1 时序与同步问题
- 影子寄存器 vs 活动寄存器:ePWM的很多关键寄存器(如CMPA, CMPB, TBPRD, AQCTL等)都有影子寄存器。你写入的是影子寄存器,硬件会在特定的“加载点”(如CTR=PRD, CTR=0)自动将其复制到活动寄存器生效。在错误的时刻更新活动寄存器会导致PWM波形出现毛刺或跳动。务必利用好加载点,在计数器为0或周期值时更新影子寄存器最安全。
- 时钟分频与死区精度:时间基时钟TBCLK来源于系统时钟SYSCLKOUT经过分频。死区时间、PWM频率的精度都依赖于TBCLK。计算周期和比较值时,要使用TBCLK的频率,而不是系统主频。
PWM_Period = (SYSCLKOUT / (TBCLK_div * PWM_Frequency)) - 1。
6.2 故障保护失效
- TZ引脚未正确配置:TZ1~TZ6是复用引脚,除了配置ePWM模块内的TZSEL,还必须通过GPIO多路复用器(GPIO MUX)将这些引脚配置为ePWM故障输入功能,并通常需要使能内部上拉。
- 标志位未及时清除:对于一次性故障(OST),触发后输出会锁定在安全状态。即使外部故障信号已消失,也必须软件清除
TZFLG[OST]标志(通过写TZCLR[OST]=1),PWM输出才能恢复正常。这是一个常见的“故障复位不了”的原因。 - 数字比较器(DC)事件未连接:如果你使用内部数字比较器事件(DCAEVT1等)作为Trip源,必须确保数字比较器子模块本身已正确配置并产生了相应的事件,否则TZ模块永远等不到这个故障信号。
6.3 调试手段与工具
- 寄存器查看:在CCS的Registers视图中,实时监控ePWM关键寄存器的值,特别是TBCTR、CMPA/CMPB、TZFLG、ETFLG等,这是最直接的调试方式。
- 输出强制:在系统初始化但未启动PWM时,使用AQCSFRC寄存器将输出强制为高或低,用万用表或示波器测量硬件引脚电平,可以快速验证引脚配置和驱动电路是否正常。
- 软件模拟故障:在调试阶段,使用
TZFRC寄存器手动触发故障,观察PWM输出是否按TZCTL的配置变化,以及中断是否产生,可以完整地测试整个保护链路。 - 示波器是关键:永远相信示波器。同时测量:
- ePWM输出引脚波形。
- 死区时间是否与计算值一致(测量互补通道上升沿/下降沿之间的间隔)。
- ADC SOC触发脉冲与PWM波形的相对位置。
- TZ故障输入引脚的电平与PWM输出的响应延迟(应在几十纳秒内)。
7. 从寄存器到代码:一个完整的电机驱动PWM初始化示例
理论说了这么多,最后给出一段基于TI的C2000 DriverLib库(或类似风格)的ePWM初始化代码片段,它整合了上述所有要点,用于生成一对中心对齐、带死区、带故障保护、并触发ADC采样的互补PWM。
void InitEPwm1(void) { // 1. 时基模块配置 EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // 上下计数模式 EPwm1Regs.TBPRD = SYSTEM_FREQ / (2 * PWM_FREQ) - 1; // 计算周期值 EPwm1Regs.TBPHS.half.TBPHS = 0; // 相位清零 EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // 禁止相位加载 EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1; // 设置TBCLK分频 // 2. 比较器模块配置 EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // CMPA使用影子模式 EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; // CMPB使用影子模式 EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // 在CTR=0时加载CMPA影子寄存器 EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // 在CTR=0时加载CMPB影子寄存器 EPwm1Regs.CMPA.half.CMPA = EPwm1Regs.TBPRD / 2; // 初始化占空比50% EPwm1Regs.CMPB = 0; // CMPB暂未使用 // 3. 动作限定器配置 (生成互补PWM) EPwm1Regs.AQCTLA.bit.ZRO = AQ_CLEAR; // CTR=0, EPWMxA拉低 EPwm1Regs.AQCTLA.bit.PRD = AQ_SET; // CTR=PRD, EPWMxA置高 EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // CTR=CMPA up, EPWMxA拉低 (下降沿) EPwm1Regs.AQCTLA.bit.CAD = AQ_SET; // CTR=CMPA down, EPWMxA置高 (上升沿) EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET; // CTR=0, EPWMxB置高 (互补) EPwm1Regs.AQCTLB.bit.PRD = AQ_CLEAR; // CTR=PRD, EPWMxB拉低 (互补) EPwm1Regs.AQCTLB.bit.CAU = AQ_SET; // CTR=CMPA up, EPWMxB置高 (互补) EPwm1Regs.AQCTLB.bit.CAD = AQ_CLEAR; // CTR=CMPA down, EPWMxB拉低 (互补) // 4. 死区生成器配置 EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // 完全使能死区 EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; // 高有效互补模式 EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL; // EPWMxA作为死区输入源 EPwm1Regs.DBRED = DEAD_TIME_COUNTS; // 上升沿延迟计数值 EPwm1Regs.DBFED = DEAD_TIME_COUNTS; // 下降沿延迟计数值 // 5. Trip-Zone故障保护配置 EPwm1Regs.TZSEL.bit.OSHT1 = 1; // 使能TZ1为一次性故障源 EPwm1Regs.TZSEL.bit.CBC2 = 1; // 使能TZ2为逐周期故障源 EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_LO; // 故障时,EPWMxA强制低 EPwm1Regs.TZCTL.bit.TZB = TZ_FORCE_LO; // 故障时,EPWMxB强制低 EPwm1Regs.TZEINT.bit.OST = 1; // 使能一次性故障中断 // 6. 事件触发配置 (用于ADC采样) EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO_PRD; // 在CTR=0或PRD时触发SOCA EPwm1Regs.ETSEL.bit.SOCAEN = 1; // 使能SOCA EPwm1Regs.ETPS.bit.SOCAPRD = ET_1ST; // 每个事件都触发 // 7. 初始输出状态安全设置 EPwm1Regs.AQCSFRC.bit.CSFA = AQCSF_FORCE_LO; // 软件强制输出A为低 EPwm1Regs.AQCSFRC.bit.CSFB = AQCSF_FORCE_LO; // 软件强制输出B为低 }这段代码是一个坚实的起点。在实际项目中,你需要根据具体的硬件连接(如TZ引脚分配、ADC采样需求)、控制算法(如是否使用CMPB)以及系统安全要求进行调整。记住,ePWM的配置是精细活,理解每个寄存器比特位的含义,结合示波器进行验证,是写出稳定可靠驱动代码的不二法门。