4. PWM 基础与死区配置:ePWM 模块原理、频率与分辨率、死区插入
各位工程师,大家好。欢迎来到第四章。
这一章,我们聊聊伺服系统里最基础、也最关键的环节——PWM 生成。说白了,电机转得快不快、稳不稳,最终都得靠 PWM 波去驱动功率管。而 ePWM 模块,就是 C2000 干这活的“心脏”。
我刚开始接触 C2000 时,总觉得 PWM 配置就是设个频率、占空比,没什么难的。直到有一次,驱动器在满载时突然炸管……嗯,从那以后,我才真正重视起死区配置和分辨率这些细节。今天,我把这些经验掰开揉碎了讲给你听。
4.1 ePWM 模块的核心架构
C2000 的 ePWM 模块,每个模块包含两个独立的 PWM 输出:ePWMxA 和 ePWMxB。它们可以配置成互补输出,也可以独立工作。每个模块内部,主要由以下几个部分组成:
- 时基模块 (TB):负责产生计数时钟和周期。
- 比较模块 (CC):设定占空比和比较值。
- 动作模块 (AQ):根据计数状态和比较结果,决定输出是高电平还是低电平。
- 死区模块 (DB):插入死区时间,防止上下桥臂直通。
- 事件触发模块 (ET):产生中断或启动 ADC 转换。
你想想看,这五个模块协同工作,才构成了一个完整的 PWM 通道。我个人习惯,在配置任何 PWM 之前,先画一张模块连接图,理清信号流向。下面这张图,就是 ePWM 模块的内部数据流。
从这张图你可以看到,信号从时基模块出发,经过比较、动作、死区,最终输出到功率管。每个环节都影响最终的 PWM 质量。
4.2 PWM 频率与分辨率设置
PWM 频率,由时基模块的时钟分频和周期寄存器共同决定。公式很简单:
PWM 频率 = SYSCLKOUT / (TBCLK 分频系数 × TBPRD + 1)
举个例子,假设系统时钟 SYSCLKOUT = 100 MHz,我们想要 20 kHz 的 PWM 频率。如果 TBCLK 不分频(分频系数 = 1),那么:
TBPRD = 100,000,000 / 20,000 - 1 = 4999
这里要注意,TBPRD 的值决定了 PWM 的周期。值越大,周期越长,频率越低。
💡 我的经验: 伺服系统常用的 PWM 频率在 10 kHz ~ 20 kHz 之间。频率太低,电机噪音大;频率太高,开关损耗增加。我个人习惯,通用伺服选 16 kHz,既能避开人耳敏感区,又能平衡损耗。
4.2.1 分辨率问题
分辨率,说白了就是 PWM 占空比能细调到什么程度。它由时基计数器的位数决定。C2000 的 ePWM 模块使用 16 位计数器,理论上分辨率是 1/65536。但实际中,受限于系统时钟和 PWM 频率,有效分辨率会下降。
为什么会这样?因为 PWM 周期越长,每个计数步长对应的时间就越长,占空比调节的粒度就越粗。举个例子:
| PWM 频率 | 系统时钟 | TBPRD | 占空比步长 |
|---|---|---|---|
| 10 kHz | 100 MHz | 9999 | 0.01% |
| 50 kHz | 100 MHz | 1999 | 0.05% |
| 100 kHz | 100 MHz | 999 | 0.1% |
你看,频率越高,分辨率越低。对于高精度伺服,我建议 PWM 频率不要超过 20 kHz,否则电流环的调节精度会受影响。
⚠️ 注意: 我曾经在一个高速主轴项目中,为了追求低噪音,把 PWM 频率设到了 40 kHz。结果电流环抖动厉害,电机发热严重。后来才发现,分辨率太低,导致电流纹波过大。所以,频率和分辨率之间,一定要权衡。
4.3 死区时间插入
死区时间,是伺服系统里绝对不能忽视的一环。它的作用,是防止上下桥臂的功率管同时导通。你想想看,如果上下管同时导通,电源直接短路,瞬间大电流就会烧毁功率管。
死区模块的工作原理,是在 PWM 信号的上升沿或下降沿插入一段延迟。C2000 的死区模块支持多种模式:
- 上升沿延迟:只在上升沿插入死区。
- 下降沿延迟:只在下降沿插入死区。
- 上升沿和下降沿都延迟:双边插入。
- 互补输出模式:自动生成互补 PWM,并插入死区。
我个人最常用的是互补输出模式。配置起来也很简单:
// 死区配置示例
EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // 使能死区
EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIGH; // 高电平有效
EPwm1Regs.DBRED.bit.DBRED = 100; // 上升沿死区 100 个 TBCLK
EPwm1Regs.DBFED.bit.DBFED = 100; // 下降沿死区 100 个 TBCLK
这段代码配置了 100 个 TBCLK 周期的死区时间。如果 TBCLK = 100 MHz,那么死区时间就是 1 µs。
4.3.1 死区时间怎么选?
死区时间不是越大越好,也不是越小越好。太大会导致波形失真,影响电流控制精度;太小又可能无法完全防止直通。
一般来说,死区时间取决于功率管的开关特性。IGBT 的开关速度较慢,死区时间通常在 1 µs ~ 3 µs;MOSFET 的开关速度快,死区时间可以短到 200 ns ~ 500 ns。
🔧 避坑指南: 我曾经在一个项目中,为了追求极致的电流响应,把死区时间设到了 100 ns。结果在满载测试时,功率管瞬间炸裂。后来检查发现,MOSFET 的关断延迟时间本身就超过 100 ns,死区时间根本不够。所以,死区时间一定要大于功率管的最大关断延迟时间,并留出 20%~30% 的余量。
4.4 实战配置步骤
好了,理论讲完了,我们直接上手配置。下面是一个完整的 ePWM 初始化流程:
- 使能 ePWM 模块时钟:在系统控制寄存器中使能对应外设时钟。
- 配置 GPIO 复用功能:将 GPIO 引脚设置为 ePWM 输出模式。
- 配置时基模块:设置时钟分频、计数模式(向上/向下/上下)、周期值。
- 配置比较模块:设置 CMPA 和 CMPB 的初始值。
- 配置动作模块:定义计数到零、周期、比较匹配时的输出动作。
- 配置死区模块:选择死区模式,设置上升沿和下降沿延迟。
- 配置事件触发:如果需要中断或 ADC 触发,配置 ET 模块。
- 启动时基计数器:使能计数器开始工作。
下面是一个完整的初始化代码示例:
void EPwm1_Init(void)
{
// 1. 使能 ePWM1 时钟
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0; // 停止所有 ePWM 时钟
CpuSysRegs.PCLKCR2.bit.EPWM1 = 1; // 使能 ePWM1 时钟
// 2. 配置 GPIO0 和 GPIO1 为 ePWM1A 和 ePWM1B
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // GPIO0 = EPWM1A
GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1; // GPIO1 = EPWM1B
// 3. 时基配置:100 MHz TBCLK,向上计数,周期 5000(20 kHz)
EPwm1Regs.TBCTL.bit.CLKDIV = 0; // 不分频
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0; // 高速时钟不分频
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // 向上计数
EPwm1Regs.TBPRD = 5000; // 周期值
// 4. 比较配置:初始占空比 50%
EPwm1Regs.CMPA.bit.CMPA = 2500;
// 5. 动作配置:计数到零时置高,匹配 CMPA 时置低
EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;
// 6. 死区配置:互补输出,死区时间 1 µs(100 个 TBCLK)
EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIGH;
EPwm1Regs.DBRED.bit.DBRED = 100;
EPwm1Regs.DBFED.bit.DBFED = 100;
// 7. 启动时基
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1; // 启动所有 ePWM 时钟
}
这段代码配置了一个 20 kHz 的互补 PWM 输出,死区时间 1 µs。你可以直接复制到你的工程里,稍作修改就能用。
💡 小技巧: 调试时,我习惯先用示波器观察 PWM 波形,确认频率和死区时间是否正确。特别是死区时间,一定要放大看,确保没有重叠。我曾经遇到过死区配置正确,但波形仍有重叠的情况,最后发现是 GPIO 的压摆率设置太慢导致的。所以,别忘了检查 GPIO 的驱动能力。
4.5 本章小结
这一章,我们深入探讨了 ePWM 模块的原理、频率与分辨率的关系,以及死区时间的配置方法。记住几个关键点:
- PWM 频率和分辨率是矛盾的,需要根据应用场景权衡。
- 死区时间必须大于功率管的关断延迟,并留出余量。
- 配置时,按照时基→比较→动作→死区的顺序,不容易出错。