3. PWM基础与定时器:ePWM模块原理

伺服驱动里最核心的底层技术,就是PWM生成。你想想看,电机转得快慢、力矩大小,最终都靠PWM波去控制功率管开关。C2000的ePWM模块,我用了快十年,真心觉得它设计得巧妙。

这一章咱们就把ePWM的底裤扒干净。从时基计数器开始,到比较器、动作限定、死区插入,最后算算分辨率和频率。嗯,都是干货。

本章核心脉络:时基周期 → 计数器模式 → 比较匹配 → 动作限定 → 死区插入 → 互补PWM输出

ePWM模块内部数据流 时基模块 TBCTR / TBPRD 比较器 CMPA/CMPB 动作限定 AQ 死区插入 DB ePWMxA/B 说明: 时基模块驱动计数器递增/递减,计数器值与比较器CMPA/CMPB匹配时触发动作。 动作限定模块决定输出电平变化,死区模块插入延时后生成互补PWM对。

3.1 时基周期与计数器

ePWM的核心是一个时基计数器TBCTR。它有三种模式:递增、递减、递增递减。我个人最常用递增递减模式,也就是中心对齐PWM。为什么?因为谐波小,电流纹波也小。

时基周期寄存器TBPRD决定了计数器的最大值。举个例子:

// 假设系统时钟 SYSCLKOUT = 100 MHz
// 想要 PWM 频率 = 20 kHz
// 递增递减模式:TBPRD = SYSCLKOUT / (2 * PWM频率)
// TBPRD = 100,000,000 / (2 * 20,000) = 2500

EPwm1Regs.TBPRD = 2500;          // 时基周期
EPwm1Regs.TBCTL.bit.CTRMODE = 2; // 递增递减模式
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0; // 高速时钟不分频
EPwm1Regs.TBCTL.bit.CLKDIV = 0;    // 时基时钟不分频

我的习惯:初始化时先把TBCTR清零,避免上电瞬间出现不确定的PWM状态。曾经有个项目没做这步,电机上电时抖了一下,吓我一跳。

3.2 比较器与动作限定

比较器CMPA和CMPB,就是用来设定占空比的。当TBCTR的值等于CMPA或CMPB时,ePWM内部会产生一个比较事件。动作限定模块AQ根据这个事件,决定输出是高电平还是低电平。

动作限定的配置很灵活。你可以设置:

  • CAU:递增时CMPA匹配
  • CAD:递减时CMPA匹配
  • CBU:递增时CMPB匹配
  • CBD:递减时CMPB匹配

每个事件都可以独立设置动作:置高、置低、翻转、不变。我一般这样配:

// 递增递减模式,中心对齐
// 递增时匹配CMPA → 输出置低
// 递减时匹配CMPA → 输出置高
// 这样占空比 = (TBPRD - CMPA) / TBPRD

EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;  // 递增匹配 → 低电平
EPwm1Regs.AQCTLA.bit.CAD = AQ_SET;    // 递减匹配 → 高电平

注意:动作限定的配置顺序会影响输出波形。我曾经在调试时把CAU和CAD写反了,结果PWM波形完全反相,电机直接反转。排查了半天才发现是这里的问题。

3.3 死区插入与互补PWM生成

伺服驱动里,同一桥臂的上下两个功率管绝对不能同时导通。否则就是短路,炸管子。死区插入就是为了解决这个问题。

C2000的死区模块DB,可以独立控制上升沿延时和下降沿延时。我通常这样配:

// 死区配置:上升沿延时 100 ns,下降沿延时 100 ns
// 系统时钟 100 MHz,一个时钟周期 = 10 ns
// 所以延时计数 = 100 ns / 10 ns = 10

EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // 使能上升和下降沿延时
EPwm1Regs.DBRED = 10;  // 上升沿延时计数
EPwm1Regs.DBFED = 10;  // 下降沿延时计数
EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HI; // 输出极性:高有效

互补PWM生成很简单。ePWM模块会自动从ePWMxA和ePWMxB输出互补波形。你只需要把死区模块的输出模式配好就行。

死区模式 ePWMxA输出 ePWMxB输出 典型应用
DB_FULL_ENABLE 带延时的原始信号 带延时的互补信号 全桥驱动
DB_RED_ENABLE 带延时的原始信号 原始信号 仅需上升沿延时
DB_FED_ENABLE 原始信号 带延时的互补信号 仅需下降沿延时
DB_DISABLE 原始信号 原始信号 无死区需求

避坑指南:死区时间不是越大越好。太大会导致占空比损失,电机在高速时力矩不足。我一般取功率管开关时间的1.5~2倍。比如IGBT开关时间200ns,死区设300~400ns就够。

3.4 PWM频率与分辨率计算

PWM频率和分辨率是一对矛盾。频率越高,分辨率越低。为什么?因为时基计数器是16位的,最大值65535。频率高了,TBPRD就小,可调节的占空比步数就少。

计算公式很简单:

// 递增递减模式
PWM频率 = SYSCLKOUT / (2 * TBPRD)
分辨率 = 1 / (2 * TBPRD) × 100%

// 举例:SYSCLKOUT = 100 MHz
// TBPRD = 2500 → PWM频率 = 20 kHz,分辨率 = 0.02%
// TBPRD = 500  → PWM频率 = 100 kHz,分辨率 = 0.1%

你看,20kHz时分辨率0.02%,够用。但100kHz时分辨率只有0.1%,对于高精度伺服来说就有点紧张了。

我的经验:伺服驱动PWM频率通常选10~20kHz。这个范围既能保证电流环带宽,分辨率也足够。如果非要高频,可以考虑用C2000的高分辨率PWM模块HRPWM,它能做到150ps级别的精度。

最后说一句,ePWM模块的配置顺序很重要。我习惯先配时基,再配比较器,然后动作限定,最后死区。一步步来,不容易出错。嗯,这一章的内容就到这儿,你先把这些基础啃透,后面调参才能得心应手。