尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

DSP28335 ePWM模块配置详解:从互补PWM到死区时间设置

DSP28335 ePWM模块配置详解:从互补PWM到死区时间设置 1. 项目概述为什么DSP28335的PWM与死区如此关键如果你正在用DSP28335驱动一个电机或者控制一个功率变换器那么“输出PWM波并设置死区”这个操作几乎是你项目成败的第一个技术门槛。这听起来像是一个基础的配置动作但背后牵扯到硬件安全、系统稳定性和最终的性能表现。我见过不少项目代码逻辑写得漂亮算法也很精妙最后却因为PWM配置不当特别是死区时间没设对导致桥臂直通、MOS管炸机一切努力付诸东流。DSP28335作为TI经典的C2000系列控制器其增强型脉宽调制ePWM模块功能强大且灵活是进行高性能数字电源、电机驱动等应用的利器。所谓“输出两路PWM”通常不是指两个独立的、毫不相关的信号而是特指一对互补的、带死区的PWM信号用于驱动一个半桥或全桥电路的上、下管。而“设置死区”就是在这对互补信号之间插入一个两者都为低电平的短暂时间确保一个管子完全关断后另一个管子才开启从根本上避免电源直通短路。这个项目标题的核心就是教你如何正确、安全地驾驭DSP28335的ePWM模块生成可靠的驱动信号。无论你是刚接触DSP的新手还是从STM32等平台迁移过来的开发者理清这里的配置逻辑和细节都至关重要。2. 核心思路与方案设计理解ePWM的模块化架构在动手写代码之前我们必须先理解DSP28335的ePWM模块是如何工作的。它与许多通用单片机如STM32的定时器PWM输出有显著区别其设计完全面向电力电子和电机控制因此结构上更复杂但也更专业和强大。2.1 ePWM模块的组成与信号生成流程DSP28335的每个ePWM模块例如ePWM1, ePWM2...都是一个高度独立的子系统可以生成多达两路互补的PWM输出EPWMxA和EPWMxB。其核心部件包括时间基准TB子模块负责产生时基计数器TBCTR决定PWM的周期和频率。你可以把它看作一个心脏它的跳动节拍决定了PWM的节奏。计数比较CC子模块包含两个比较寄存器CMPA和CMPB。将时基计数器的值与这两个寄存器值进行比较是产生不同占空比波形的关键。动作限定AQ子模块这是“导演”角色。它根据时基计数器状态比如等于0、等于周期值、等于CMPA值等来“指挥”输出引脚应该做什么动作置高、拉低或者翻转。我们想要的PWM波形就是在这里被定义出来的。死区DB子模块这是本项目的重中之重。它接收来自AQ模块的原始信号然后按照我们配置的延迟模式在上升沿或下降沿插入延迟从而生成最终那对带死区的互补信号。其他子模块如事件触发ET、数字比较DC等用于更高级的联动和保护初期可以稍后关注。生成一对带死区互补PWM的典型流程是TB模块产生时基锯齿波或三角波 - CC模块设定比较点 - AQ模块根据比较点产生一对原始的、互补但无死区的信号比如A高B低A低B高 - DB模块在这对原始信号的边沿插入延迟生成最终的EPWMxA和EPWMxB。2.2 关键设计决策边沿对齐与对称PWM在配置之前有一个基础但重要的选择采用递增计数模式边沿对齐PWM还是递增-递减计数模式对称PWM边沿对齐模式时基计数器从0递增到周期值TBPRD然后复位回0。这样产生的PWM波形其脉冲前沿是固定的后沿移动。这是最常用的模式控制简单但开关损耗相对较大。对称PWM模式时基计数器从0递增到周期值再递减回0。这样产生的PWM波形是关于中心对称的。它的主要优势是能产生三次谐波注入提高直流母线电压利用率并且在相同的开关频率下等效载波频率翻倍谐波特性更好常用于电机控制。对于大多数入门和基础应用边沿对齐模式更直观易懂。因此在本项目的核心配置中我们将采用此模式。但你需要知道在DSP28335的数据手册中对称PWM模式是它的一个特色功能。注意选择计数模式不仅影响波形还会影响比较寄存器的加载方式。在边沿对齐模式下我们通常在一个周期结束时更新占空比使用TBCTR 0或TBCTR TBPRD作为加载事件以避免在一个PWM周期中间出现毛刺。3. 核心寄存器配置详解与实操要点理解了架构我们就可以深入到寄存器层面。DSP28335的配置本质上是填写一系列寄存器。下面我将分步骤拆解并解释每个关键寄存器设置背后的原因。3.1 时基TB子模块配置设定PWM的心跳时基子模块配置是整个PWM的基石它决定了信号的频率和相位。// 假设我们配置 ePWM1 模块 // 1. 配置时钟预分频和时基周期 EPwm1Regs.TBCTL.bit.CTRMODE TB_COUNT_UP; // 设置为递增模式边沿对齐 EPwm1Regs.TBCTL.bit.PHSEN TB_DISABLE; // 禁止相位加载作为主模块 EPwm1Regs.TBCTL.bit.PRDLD TB_SHADOW; // 周期寄存器使用影子寄存器缓冲 EPwm1Regs.TBCTL.bit.SYNCOSEL TB_SYNC_DISABLE; // 同步输出选择主模块通常禁用 EPwm1Regs.TBCTL.bit.HSPCLKDIV TB_DIV1; // 高速时钟预分频设为1 EPwm1Regs.TBCTL.bit.CLKDIV TB_DIV1; // 时钟预分频设为1 // 这里先不分频让时基计数器以系统时钟例如150MHz运行方便计算。 // 2. 设置PWM周期频率 // 假设系统时钟 SYSCLKOUT 150MHz我们希望PWM频率为 20kHz。 // 计算公式PWM_Period (SYSCLKOUT / (HSPCLKDIV * CLKDIV)) / PWM_Freq // 代入PWM_Period 150e6 / 20e3 7500 Uint16 period 7500; EPwm1Regs.TBPRD period; // 设置周期寄存器的主动值 // 影子寄存器会自动在更新事件时加载此值确保周期切换无毛刺。 // 3. 初始化时基计数器 EPwm1Regs.TBCTR 0; // 从0开始计数配置解析与要点CTRMODETB_COUNT_UP这是我们之前选择的边沿对齐模式。PRDLDTB_SHADOW这是关键的安全配置。影子寄存器相当于一个缓冲器。我们写入TBPRD的值是先放到影子寄存器里只有在特定的“更新事件”如计数器归零发生时影子寄存器的值才会真正加载到工作的周期寄存器中。这避免了在计数器运行中途更改周期值可能导致的中途周期跳变产生非法的PWM脉冲。频率计算是基本功。务必根据你的实际系统时钟和所需频率准确计算TBPRD值。过高的TBPRD值低频可能导致控制精度不够过低的TBPRD值高频可能超出计数器范围或导致分辨率不足。3.2 计数比较CC子模块配置定义占空比比较寄存器CMPA和CMPB的值直接决定了PWM输出高电平的宽度占空比。// 配置计数比较子模块 EPwm1Regs.CMPCTL.bit.SHDWAMODE CC_SHADOW; // CMPA使用影子寄存器 EPwm1Regs.CMPCTL.bit.SHDWBMODE CC_SHADOW; // CMPB使用影子寄存器 EPwm1Regs.CMPCTL.bit.LOADAMODE CC_CTR_ZERO; // 在TBCTR0时加载CMPA影子寄存器 EPwm1Regs.CMPCTL.bit.LOADBMODE CC_CTR_ZERO; // 在TBCTR0时加载CMPB影子寄存器 // 设置初始占空比例如50% // 占空比 CMPx / TBPRD Uint16 duty period / 2; // 50%占空比 EPwm1Regs.CMPA.half.CMPA duty; // 设置CMPA值 // 假设我们只用CMPA来控制一对PWMCMPB可以用于其他模式或暂不设置。配置解析与要点SHDWxMODECC_SHADOW与周期寄存器同理为比较寄存器启用影子寄存器是必须的这是实现占空比无毛刺更新的核心机制。LOADxMODECC_CTR_ZERO这指定了影子寄存器何时生效。我们选择在计数器归零TBCTR0时加载。这意味着在一个PWM周期开始时新的占空比值才生效整个周期内占空比保持不变。这是最安全、最常用的方式。如果选择在TBCTRTBPRD周期匹配时加载效果类似具体看波形中心点。占空比计算在边沿对齐模式下CMPA值小于TBPRD时输出高电平的宽度就是CMPA值对应的时钟周期数。当CMPA为0时占空比0%等于TBPRD时占空比100%需注意AQ模块动作设置。3.3 动作限定AQ子模块配置指挥波形动作这是将比较事件转化为实际电平动作的环节。我们需要定义当时基计数器等于CMPA和周期值时输出引脚做什么。// 配置动作限定子模块生成一对互补的原始信号 // 我们目标是EPWM1A输出常规PWMEPWM1B输出其反相。 // 以EPWM1A为例设置其在以下事件触发动作 EPwm1Regs.AQCTLA.bit.CAU AQ_SET; // 当TBCTR CMPA 且递增时置高EPWM1A EPwm1Regs.AQCTLA.bit.PRD AQ_CLEAR; // 当TBCTR TBPRD周期值时拉低EPWM1A // 对于EPWM1B我们希望它与EPWM1A反相 EPwm1Regs.AQCTLB.bit.CAU AQ_CLEAR; // 当TBCTR CMPA 且递增时拉低EPWM1B EPwm1Regs.AQCTLB.bit.PRD AQ_SET; // 当TBCTR TBPRD周期值时置高EPWM1B配置解析与要点CAU代表“Counter equals CMPA on Up-count”递增时等于CMPA。PRD代表“Counter equals period”等于周期值。这样配置的结果是每个PWM周期开始时TBCTR从0开始递增。在达到CMPA值之前EPWM1A和1B保持上一个事件后的状态需要初始化见下文。当TBCTR等于CMPA时EPWM1A被置高EPWM1B被拉低。当TBCTR计数到TBPRD时EPWM1A被拉低EPWM1B被置高。然后TBCTR归零开始下一个周期。初始化输出状态在第一个周期开始前我们需要一个确定的初始状态。通常通过AQCTLA.bit.ZRO计数器等于0事件来设置。例如在计数器为0时将EPWM1A拉低EPWM1B置高形成一个确定的起始点。EPwm1Regs.AQCTLA.bit.ZRO AQ_CLEAR; // TBCTR0时清除EPWM1A EPwm1Regs.AQCTLB.bit.ZRO AQ_SET; // TBCTR0时设置EPWM1B至此我们已经得到了一对完美的、互补的、但没有死区的PWM信号EPWM1A和EPWM1B。如果直接用它驱动半桥会立刻导致短路。3.4 死区DB子模块配置插入安全屏障死区模块是保障功率电路安全的最后一道也是最关键的一道软件防线。// 配置死区子模块 EPwm1Regs.DBCTL.bit.OUT_MODE DB_FULL_ENABLE; // 使能EPWMxA和EPWMxB的完整死区控制 EPwm1Regs.DBCTL.bit.POLSEL DB_ACTV_HI; // 设定有效电平为高根据你的驱动芯片决定 EPwm1Regs.DBCTL.bit.IN_MODE DBA_ALL; // 死区输入源为EPWMxA来自AQ模块的原始信号 // 选择死区信号路径模式我们常用“上升沿延迟”模式 // 即对EPWMxA的上升沿和EPWMxB的下降沿插入延迟。 EPwm1Regs.DBCTL.bit.OUTSWAP DB_DISABLE; // 通常不交换输出 // 设置死区时间值 // 死区时间 DBFED/DBRED * 死区时钟周期 // 死区时钟周期 EPWM时钟周期 * (HSPCLKDIV * CLKDIV) // 假设我们之前HSPCLKDIV和CLKDIV都为1系统时钟150MHz则死区时钟周期为6.67ns。 // 假设我们需要2us的死区时间。 // 所需计数值 死区时间 / 死区时钟周期 2e-6 / 6.67e-9 ≈ 300 Uint16 deadband_val 300; EPwm1Regs.DBFED deadband_val; // 下降沿延迟值Falling Edge Delay EPwm1Regs.DBRED deadband_val; // 上升沿延迟值Rising Edge Delay配置解析与要点OUT_MODE必须使能为DB_FULL_ENABLE才能对两路输出都进行死区控制。POLSEL这是极易出错的地方。它定义了经过死区模块后什么样的电平被认为是“有效”的驱动电平。如果你的驱动芯片如IR2110是高电平有效就设为DB_ACTV_HI如果是低电平有效很多自举电路下管常用则设为DB_ACTV_LO。务必与你的硬件电路匹配设反了会导致输出常闭或常开。IN_MODE指定哪一路原始信号作为死区计算的参考源。通常选择DBA_ALL即以EPWMxA来自AQ模块为基准生成两路带死区的输出。死区时间计算这是硬件设计的核心参数。死区时间必须大于功率器件MOSFET/IGBT的关断延迟时间与开启延迟时间之差并留有充足裕量。通常根据器件数据手册确定例如1us到3us。计算出的DBFED和DBRED值写入寄存器它们分别控制下降沿和上升沿的延迟。通常两者设为相同值形成对称死区。模式选择DBCTL中还有SEL位域用于选择具体的延迟模式如仅上升沿延迟、仅下降沿延迟、双边沿延迟等。最常用的是DB_CTL_MODE 0x1或0x2即上文所述的“上升沿延迟”模式它能确保在任何切换时刻两路信号之间都有一个全低电平的死区窗口。4. 完整代码实现与初始化流程将上述所有配置整合到一个初始化函数中并考虑整个系统的启动顺序。// 函数InitEPwm1 // 描述初始化ePWM1模块输出一对频率20kHz初始占空比50%死区2us的互补PWM。 // 参数无 // 返回无 void InitEPwm1(void) { // 步骤1使能ePWM1模块的时钟通常在系统初始化中完成这里假设已使能 // 步骤2配置时基(TB)子模块 EPwm1Regs.TBCTL.bit.CTRMODE TB_COUNT_UP; // 递增模式 EPwm1Regs.TBCTL.bit.PHSEN TB_DISABLE; // 禁用相位加载 EPwm1Regs.TBCTL.bit.PRDLD TB_SHADOW; // 周期寄存器影子加载 EPwm1Regs.TBCTL.bit.SYNCOSEL TB_SYNC_DISABLE; // 主模块不同步输出 EPwm1Regs.TBCTL.bit.HSPCLKDIV TB_DIV1; EPwm1Regs.TBCTL.bit.CLKDIV TB_DIV1; // 设置PWM频率为20kHz系统时钟150MHz EPwm1Regs.TBPRD 7500; // 周期值 EPwm1Regs.TBCTR 0; // 时基计数器清零 // 步骤3配置计数比较(CC)子模块 EPwm1Regs.CMPCTL.bit.SHDWAMODE CC_SHADOW; EPwm1Regs.CMPCTL.bit.SHDWBMODE CC_SHADOW; EPwm1Regs.CMPCTL.bit.LOADAMODE CC_CTR_ZERO; // 零点加载 EPwm1Regs.CMPCTL.bit.LOADBMODE CC_CTR_ZERO; EPwm1Regs.CMPA.half.CMPA 3750; // 初始占空比50% (7500/2) // 步骤4配置动作限定(AQ)子模块 // 初始化状态计数器为0时A低B高 EPwm1Regs.AQCTLA.bit.ZRO AQ_CLEAR; // CTR0, 清除A EPwm1Regs.AQCTLB.bit.ZRO AQ_SET; // CTR0, 设置B // 动作事件CMPA匹配时A高B低周期匹配时A低B高 EPwm1Regs.AQCTLA.bit.CAU AQ_SET; // CTRCMPA up, 设置A EPwm1Regs.AQCTLA.bit.PRD AQ_CLEAR; // CTRPRD, 清除A EPwm1Regs.AQCTLB.bit.CAU AQ_CLEAR; // CTRCMPA up, 清除B EPwm1Regs.AQCTLB.bit.PRD AQ_SET; // CTRPRD, 设置B // 步骤5配置死区(DB)子模块 EPwm1Regs.DBCTL.bit.OUT_MODE DB_FULL_ENABLE; // 使能双路死区 EPwm1Regs.DBCTL.bit.POLSEL DB_ACTV_HI; // 高电平有效根据硬件调整 EPwm1Regs.DBCTL.bit.IN_MODE DBA_ALL; // 以A路为输入源 // 设置死区时间2us (150MHz时钟下计数值300) EPwm1Regs.DBFED 300; EPwm1Regs.DBRED 300; // 步骤6可选配置事件触发(ET)子模块用于产生ADC采样中断 EPwm1Regs.ETSEL.bit.INTSEL ET_CTR_ZERO; // 选择计数器为零时触发中断 EPwm1Regs.ETSEL.bit.INTEN 1; // 使能ePWM中断 EPwm1Regs.ETPS.bit.INTPRD ET_1ST; // 第一次事件就产生中断 }初始化流程与操作心得顺序很重要建议按照TB - CC - AQ - DB - ET的顺序配置。因为TB定义了基础节奏CC和AQ依赖于TBDB又处理AQ的输出。影子寄存器的加载时机我们统一设置在TBCTR0时加载LOADAMODECC_CTR_ZERO。这意味着你可以在中断服务程序如EPWM1_INT中安全地更新CMPA的影子寄存器值EPwm1Regs.CMPA.half.CMPA newDuty;新的占空比将在下一个PWM周期开始时生效实现平滑更新。GPIO复用配置上述代码只配置了ePWM模块内部别忘了还有最重要的一步将DSP28335对应的引脚如GPIO0/GPIO1对应EPWM1A/1B通过GPIO MUX寄存器配置为ePWM功能模式。这一步通常在系统初始化早期完成。EALLOW; GpioCtrlRegs.GPAMUX1.bit.GPIO0 1; // GPIO0 配置为 EPWM1A 功能 GpioCtrlRegs.GPAMUX1.bit.GPIO1 1; // GPIO1 配置为 EPWM1B 功能 EDIS;启动完成所有配置后ePWM模块会自动开始运行因为TBCTL.CTRMODE已设置为非停止模式。你可以通过示波器测量GPIO0和GPIO1引脚应该能看到一对频率20kHz、占空比50%、带有2us死区的互补PWM波。5. 调试技巧、常见问题与故障排查即使代码配置看起来正确实际调试中也可能遇到各种问题。下面分享一些实战中积累的排查经验和技巧。5.1 无输出或输出异常排查清单当你用示波器看不到预期的波形时可以按照以下清单逐项检查时钟与电源确认DSP核心时钟SYSCLKOUT是否正确配置并运行可以用一个GPIO翻转来测试时钟大致频率。确认ePWM外设时钟是否使能检查PCLKCR0寄存器中对应EPWM1ENCLK位。检查芯片供电和复位电路是否稳定。GPIO复用配置这是最常见的问题源。确认你使用的引脚如GPIO0/1是否已正确映射到ePWM功能GPAMUX1寄存器。确认引脚没有被其他外设如ADC、SPI占用。确认引脚方向寄存器GPADIR已自动设置为输出当复用为ePWM功能时。ePWM模块使能虽然配置了寄存器但有些开发板或最小系统可能需要额外的使能步骤。确认没有全局禁用ePWM的配置。寄存器配置顺序与值使用CCS的Expressions或Memory Browser视图在线调试时查看EPwm1Regs所有关键寄存器的值与你代码中设置的是否一致。特别注意TBCTL.CTRMODE不能是00停止模式。检查TBPRD和CMPA的值是否合理CMPATBPRD。死区模块是否被旁路检查DBCTL.OUT_MODE是否为00禁用。必须为01,10,11之一。输出极性如果输出信号固定为高或固定为低检查AQCTL的初始化动作ZRO事件设置是否正确。检查DBCTL.POLSEL是否与驱动电路匹配。如果设反可能导致输出有效电平相反。一个简单的测试方法是将POLSEL从DB_ACTV_HI改为DB_ACTV_LO或者交换EPWMxA和EPWMxB的输出引脚观察。5.2 死区时间不生效或异常死区时间测量用示波器的两个通道分别测量EPWM1A和EPWM1B并打开上升沿/下降沿延时测量功能。确保两路信号在任何跳变沿之间都存在一个两者都为低电平的“空白区”这个空白区的宽度应等于你设定的死区时间约2us。如果看不到死区首先检查DBCTL.OUT_MODE是否已使能。死区值计算错误重新核算死区时间。DBFED/DBRED寄存器的单位是“死区时钟周期”。死区时钟来源于系统时钟经过HSPCLKDIV和CLKDIV分频。如果你的HSPCLKDIV或CLKDIV不为1那么死区时钟周期会变长同样的寄存器值对应的实际死区时间也会变长。公式实际死区时间 DBFED * (1/(SYSCLKOUT)) * HSPCLKDIV * CLKDIV。模式理解错误DBCTL.SEL选择了错误的延迟模式。例如如果你选择了“仅对A路上升沿延迟”那么B路的下降沿可能没有延迟导致死区不对称。仔细阅读数据手册中关于死区模式的说明图。5.3 占空比更新不稳定或抖动影子寄存器未使用这是导致占空比更新出现毛刺或半个脉冲的罪魁祸首。确保CMPCTL.SHDWAMODE和CMPCTL.LOADAMODE已正确配置为影子模式和在CTRZERO/PRD时加载。在错误的时间点更新CMPA避免在PWM周期中间例如在中断服务程序中随意直接写入CMPA的主动寄存器。永远只更新影子寄存器EPwm1Regs.CMPA.half.CMPA并依靠硬件在CTRZERO或CTRPRD时自动加载。中断响应延迟如果你在PWM周期中断中更新占空比但中断响应太慢可能错过一个加载点导致更新延迟一个周期。这通常不影响稳态但会影响动态响应。优化中断服务程序代码确保其执行时间远小于PWM周期。5.4 高级调试技巧利用CCS的图形化工具Code Composer Studio的Tools - Graph功能可以实时绘制内存中的数据。你可以将EPwm1Regs.TBCTR的地址添加到图形中观察时基计数器是否在0和TBPRD之间规律变化直观判断ePWM模块是否在运行。GPIO模拟法在复杂配置出错时可以暂时注释掉ePWM配置改用简单的GPIO翻转和延时函数来模拟一对带死区的PWM信号。这能帮你快速验证硬件电路驱动芯片、MOS管是否正常隔离软件配置问题。从简单到复杂不要一开始就配置死区、互补等所有功能。可以先尝试配置单路PWM输出只使用EPWMxA让它正常工作。然后再加入互补输出配置AQ模块最后再使能死区模块。这种分步调试法能快速定位问题阶段。配置DSP28335的ePWM输出带死区的互补PWM是一个将软件逻辑与硬件安全紧密结合的典型任务。它要求开发者不仅理解寄存器每一位的含义更要清楚这些配置在功率电路上产生的实际效果。每一次寄存器值的计算每一次极性的选择都直接关系到系统的可靠性与寿命。我个人的体会是在功率电子开发中示波器是你的眼睛数据手册是你的地图而严谨的配置代码则是你安全抵达目的地的保障。当你第一次在示波器上看到那对干净、对称、中间带着清晰安全间隔的PWM波形时你会觉得这些繁琐的配置都是值得的。最后一个小建议在正式上电驱动大功率负载前务必先用一个阻性负载如大功率电阻或一个灯泡作为假负载进行测试观察波形和电流这是保护你宝贵功率器件的最有效方法。
返回列表