ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

DSP28335实现SPWM波形生成:原理、寄存器配置与调优实战

DSP28335实现SPWM波形生成:原理、寄存器配置与调优实战 简介面向电机驱动、逆变器与电源控制方向的嵌入式开发人员这是一个基于TI TMS320F28335的SPWM工程源码包。SPWM通过调节脉冲宽度逼近正弦波输出在功率变换与伺服驱动中应用广泛压缩包将官方DSP2833x外设库与自定义应用代码整合在同一CCS工程中包含SPWM主程序、my_function功能模块、variable_define变量定义等源文件并配有DSP2833x_EPwm、DSP2833x_Adc、DSP2833x_CpuTimers等驱动文件能帮助读者从系统初始化一路看到SPWM波形生成的完整流程。资源共71个文件以c源文件、h头文件、asm汇编文件为主辅以project、cmd、ccxml等CCS工程配置与链接脚本、makefile编译脚本、readme.txt说明文档整体仅90KB精简且便于直接导入CCS开发调试。已有316人学习下载。对正在学习DSP28335的PWM定时器配置或希望快速落地SPWM算法的工程师这套代码提供了可运行的参考框架可以在此基础上修改载波频率、调制度与死区参数深入理解正弦脉宽调制的工程实现也方便迁移到其他功率变换项目。1. 从 DSP28335 放出 SPWM 波形先想清楚要管住哪几个量SPWM 的核心不是“把正弦波做出来”而是在固定开关频率下让 PWM 脉冲的占空比按正弦规律变化从而在滤波之后得到等效正弦电压。DSP28335 这类 150MHz 浮点 DSP 被大量用在变频器、UPS 和异步电机交流调速系统里原因有两个一是它的 ePWM 外设能产生带死区的高精度互补输出直接驱动 IGBT 半桥二是查表法和中断更新 CMPA 的实现非常顺不需要额外引入 FPGA 或模拟电路。这篇文章就顺着“查表法生成 SPWM”这条最常见的路线把 PWM 载波频率怎么定、正弦表怎么建、寄存器怎么配、死区调多大、波形怎么看这些事一次讲透。适合正在调 28335 驱动的电机或逆变项目并且想从“能转”推进到“能控”的工程师。2. SPWM 生成的原理和 DSP28335 外设里谁在干活2.1 为什么 SPWM 会落在“三角波与正弦波比较”上SPWM 的数学本质是面积等效原理让 PWM 脉冲在半个开关周期内的平均电压等于同一时间窗内正弦调制波的瞬时值。实际生成时工程上几乎不会去实时解方程而是把正弦调制波离散成 N 个采样点每个载波周期取一个采样值作为 PWM 比较值。这个比较值进入 ePWM 的比较寄存器后由硬件完成“三角载波计数与 CMPA 比较”输出引脚自然形成脉宽变化的方波。DSP28335 的 ePWM 模块工作模式是上升/下降计数计数器从 0 递增到 TBPRD再从 TBPRD 递减回 0正好形成对称三角载波。双极性 SPWM 在这种对称载波下有一个直观特性CMPA 大于 TBPRD 的一半输出高电平时间大于一半小于一半则反之。比较值围绕 TBPRD/2 摆动摆动幅度由调制度 M 控制。调制度 M 的定义是正弦波幅值与三角载波幅值之比在 28335 的配置里三角载波幅值直接等于 TBPRD/2。于是 CMPA 的瞬时值可以写成CMPA TBPRD/2 M * (TBPRD/2) * sin(θ)这是整个 SPWM 代码里最核心的一行数学关系。调制度 M 默认取 0.8原因是若 M 接近 1正弦峰值附近的占空比趋近 100%IGBT 的最小关断时间容易不够若 M 超过 1 进入过调制区输出电压会出现削顶THD 明显恶化。对异步电机调速来说M 还要配合 V/F 曲线做低频补偿这部分放到第 4 章展开。这里先留一个印象所有 SPWM 代码最终都在做同一件事——按电角度 θ 更新 CMPA。2.2 ePWM 模块能独立完成的四件事DSP28335 上共有 ePWM1 到 ePWM6 六组 PWM 通道每组由 ePWMxA 和 ePWMxB 两个输出组成。生成三相 SPWM 时通常用 ePWM1、ePWM2、ePWM3 三个模块每组分出 A/B 两路互补信号驱动上下桥臂。一个 ePWM 模块内部分成时基 TB、比较 CC、动作限定 AQ、死区 DB、事件触发 ET 几个子模块。它们各自的职责如下表所示。子模块寄存器操作对象SPWM 中的职责时基 TBTBPRD、TBCTR、TBCTL决定载波频率和计数模式上下计数形成三角波比较 CCCMPA、CMPB装载正弦查表值与计数器比较产生匹配事件动作限定 AQAQCTLA、AQCTLB定义计数递增/递减匹配时输出置高或置低死区 DBDBCTL、DBRED、DBFED在 A/B 输出之间插入死区防止桥臂直通事件触发 ETETSEL、ETPS周期匹配时触发中断用于更新下一个 CMPA这种分工的意义在于PWM 脉冲的产生完全由硬件完成中断只负责在每个载波周期到来时往 CMPA 里写一个新值。即使中断偶尔延迟几个微秒当前的 PWM 周期仍然按老比较值完整输出不会出现脉冲缺口。这正是 28335 在电机控制中比普通 MCU 更稳的原因——普通定时器翻转 IO 的方式要求中断在纳秒级精确定时稍有抖动就会在波形上留下毛刺。2.3 查找表法还是实时计算正弦28335 该怎么选产生 SPWM 调制波的常用做法是查表法。把 360 度正弦按 300 个点均匀取样每个载波周期取下一个点作为 CMPA 值。300 个点对应载波比 N300即载波频率是调制波频率的 300 倍。如果载波 15kHz、调制波 50HzN300 刚好匹配当输出频率变化时可以保持载波频率不变调制波频率由查表步进速度决定。这种方式的好处是查表时间恒定不受浮点运算波动影响中断服务程序负载极低。另一种做法是在中断里实时调用 sin() 函数代码更简洁但要注意 28335 虽然带 FPU单次 sin 计算也要几百纳秒多个轴同时运算时 CPU 负载抬高。在只控制一台电机的场景下实时计算完全可行。但若后续要加编码器读取、电流环 PID、通信任务建议还是用查找表。中断里只需要做一次数组访问加一次索引自增剩下时间全让给控制算法。索引步进还有一个额外好处改变输出频率时不用改表只调整步进和中断周期。3. 在 DSP28335 上搭建 SPWM 最小可运行工程3.1 一个干净的工程目录该有什么从实际项目经验看不建议从头写寄存器定义文件直接用 TI 官方提供的 DSP2833x 头文件和库函数作为底座自己只维护三个文件spwm.c、spwm.h、main.c。spwm.c 里放正弦表初始化、ePWM 初始化、中断服务函数spwm.h 导出初始化接口和外露的调制度变量main.c 只负责调用初始化并进入主循环。之所以坚持拆文件是因为后面加 V/F 控制、电流环或通信协议时改动不会波及 PWM 外设代码。工程需要包含的 DSP2833x 公共源文件有 DSP2833x_GlobalVariableDefs.c、DSP2833x_PieCtrl.c、DSP2833x_PieVect.c、DSP2833x_CpuTimers.c 等。cmd 文件用 28335_RAM_lnk.cmd 或 Flash 版本。编译选项里要确保使用 FPU 硬件浮点在 TI CCS 的工程属性里选择浮点支持并添加 FPU 快速模式库 rts2800_fpu32_fast_supplement.lib。这块经常被遗漏导致 sin() 运算慢到影响中断实时性。3.2 初始化代码载波 15kHz、300 点正弦表下面这段代码是 SPWM 初始化的核心直接把每个配置项对应的寄存器写清楚。正弦表在程序启动时计算一次300 个点对应 360 度电角度。#include DSP2833x_Device.h #include DSP2833x_Examples.h #define SPWM_TABLE_SIZE 300 // 载波比 N 300 #define SPWM_TBPRD 5000 // 对应载波 15kHz #define SPWM_MOD_INDEX 0.8f // 调制度 M Uint16 sinTable[SPWM_TABLE_SIZE]; volatile Uint16 tableIndex 0; void SPWM_InitSinTable(void) { Uint16 i; float angle; float step 2.0f * 3.1415926f / SPWM_TABLE_SIZE; for (i 0; i SPWM_TABLE_SIZE; i) { angle step * i; // CMPA 在 500 到 4500 之间摆动中心点 2500 sinTable[i] (Uint16)(SPWM_TBPRD / 2 SPWM_MOD_INDEX * (SPWM_TBPRD / 2) * sinf(angle)); } }逻辑说明sinTable 的每个值都是 0 到 5000 之间的整数直接写入 CMPA 寄存器。中心点 2500 对应占空比 50%调制度 0.8 时幅值为 2000表中最大值 4500、最小值 500对应占空比 90% 和 10%。这样设置留出了死区插入的时间余量也避免了接近满占空比时半桥驱动芯片可能出现的最小脉宽不足问题。3.3 ePWM 寄存器配置与中断服务程序接下来是 ePWM1 模块的完整初始化注意 AQ 动作要配合对称三角载波计数器递增时匹配 CMPA 则输出低递减匹配则输出高这样输出波形中心对称。死区配置采用高电平有效互补模式DBRED 和 DBFED 各写 150 个时钟周期对应 1μs 死区。void SPWM_InitEPwm(void) { EPwm1Regs.TBPRD SPWM_TBPRD; EPwm1Regs.TBPHS.bit.PHSEN 0; EPwm1Regs.TBPHS.half.TBPHS 0; EPwm1Regs.TBCTR 0; EPwm1Regs.TBCTL.bit.CTRMODE 2; // 上下计数 EPwm1Regs.TBCTL.bit.HSPCLKDIV 0; // 时钟不分频 EPwm1Regs.TBCTL.bit.CLKDIV 0; EPwm1Regs.CMPA.bit.CMPA SPWM_TBPRD / 2; EPwm1Regs.AQCTLA.bit.CAU 2; // 递增计数匹配时输出低 EPwm1Regs.AQCTLA.bit.CAD 1; // 递减计数匹配时输出高 // 死区设置高有效互补上升沿和下降沿各延迟 150 个时钟 EPwm1Regs.DBTCNF.bit.DBMODE 1; // 互补模式 EPwm1Regs.DBCTL.bit.POLSEL 2; // ePWMxA 不反相ePWMxB 不反相 EPwm1Regs.DBRED.bit.DBRED 150; // 上升沿死区 EPwm1Regs.DBFED.bit.DBFED 150; // 下降沿死区 EPwm1Regs.ETSEL.bit.INTEN 1; // 使能中断 EPwm1Regs.ETSEL.bit.INTSEL 1; // 周期匹配触发 EPwm1Regs.ETPS.bit.INTPRD 1; // 每个周期触发一次 EPwm1Regs.ETCLR.bit.INT 1; }中断服务程序更新下一个 CMPA 值。载波 15kHz所以中断频率 15kHz每次中断只做数组访问、索引加一和标志清除执行时间在几百纳秒内interrupt void EPWM1_INT_ISR(void) { EPwm1Regs.CMPA.bit.CMPA sinTable[tableIndex]; tableIndex; if (tableIndex SPWM_TABLE_SIZE) { tableIndex 0; } EPwm1Regs.ETCLR.bit.INT 1; PieCtrlRegs.PIEACK.all PIEACK_GROUP3; }参数说明INTSEL 设为 1 表示在时基计数器等于 0 时触发中断也就是三角载波的谷底。在这个时间点更新 CMPA 最安全因为动作限定模块真正使用新比较值要等到下一次匹配事件不会出现写入过程被硬件读取的竞争状态。PIEACK_GROUP3 对应 ePWM1 中断所在的中断组清除这个标志才能继续响应后续中断。3.4 GPIO 引脚复用与使能DSP28335 的 ePWM 输出引脚需要配置为外设功能。GPIO0 到 GPIO5 分别对应 ePWM1A 到 ePWM3B。在 GPIO 初始化里必须把复用位切到 ePWM 模式否则引脚保持默认 GPIO 输入状态波形出不来。void SPWM_InitGPIO(void) { EALLOW; GpioCtrlRegs.GPAMUX1.bit.GPIO0 1; // GPIO0 - EPWM1A GpioCtrlRegs.GPAMUX1.bit.GPIO1 1; // GPIO1 - EPWM1B GpioCtrlRegs.GPAMUX1.bit.GPIO2 1; // GPIO2 - EPWM2A GpioCtrlRegs.GPAMUX1.bit.GPIO3 1; // GPIO3 - EPWM2B GpioCtrlRegs.GPAMUX1.bit.GPIO4 1; // GPIO4 - EPWM3A GpioCtrlRegs.GPAMUX1.bit.GPIO5 1; // GPIO5 - EPWM3B GpioCtrlRegs.GPADIR.bit.GPIO0 1; // 输出方向 GpioCtrlRegs.GPADIR.bit.GPIO1 1; GpioCtrlRegs.GPADIR.bit.GPIO2 1; GpioCtrlRegs.GPADIR.bit.GPIO3 1; GpioCtrlRegs.GPADIR.bit.GPIO4 1; GpioCtrlRegs.GPADIR.bit.GPIO5 1; EDIS; }逻辑说明GPAMUX1 寄存器的低 12 位控制 GPIO0 到 GPIO11 的功能选择每一位写 1 表示切换到外设功能。GPADIR 是为保险起见设置的输出方向虽然外设功能下方向位不影响输出电路但显式配置可以避免调试时误判引脚状态。MID。三相使用时另外两组 ePWM 的相位需要相差 120 度电角度对应表索引偏移 100 个点即 SPWM_TABLE_SIZE/3。4. SPWM 参数调优载波频率、调制度与死区边界4.1 载波频率与载波比该怎么定载波频率直接影响 IGBT 开关损耗和输出谐波。DSP28335 的 ePWM 计数时钟来自系统时钟 150MHz载波频率由 TBPRD 决定公式为f_carrier SYSCLKOUT / (2 * TBPRD)TBPRD 设为 5000 时载波为 15kHz设为 10000 则载波降到 7.5kHz。工程上电机驱动的常见载波范围是 4kHz 到 20kHz。低于 6kHz 时电机噪声明显高于 20kHz 则开关损耗过大散热器体积上涨。这里有个现实矛盾异步电机变频调速要求调制波从 0 到 50Hz 连续变化而载波频率保持不变于是载波比 N 在低频时很大、高频时变小。N 太小会导致一个正弦周期内采样点不足波形阶梯感明显这时候要切到异步调制甚至分段同步调制。调制方式载波比 N适用频率范围特点同步调制固定整数如 30010~50Hz三相严格对称谐波小异步调制固定载波0~10Hz低频分辨率高高频 N 变小分段同步调制分频段切换全范围兼顾低频精度和高温升限制DSP28335 工程里最省事的做法是采用异步调制载波恒定 15kHz只在查表索引步进上调整输出频率。当输出频率高于 30Hz 时N 下降到 500 以下仍然足够平滑。但要注意载波频率越高每个周期留给死区的时间比例越大输出基波电压会被压缩这个损失需要在 V/F 曲线里补偿。4.2 调制度 M 的边界与过调制现象调制度 M 的取值范围和表现可以归纳成三个区间。M 小于 1 是线性调制区输出基波电压与 M 成正比适合闭环控制进行调节。M 等于 1 时正弦峰值对应的 CMPA 到达 0 或 TBPRD占空比 100%。M 大于 1 进入过调制区此时正弦波的峰被水平削掉实际输出基波电压不再线性跟随 M而是以更慢的速度趋向方波极限。过调制的好处是能提升直流母线电压利用率逆变器最大输出线电压可以从 0.866 倍母线电压提升到约 1.0 倍代价是低次谐波显著增加电机电流畸变和转矩脉动变大。对异步电机交流调速系统来说直流母线电压利用率直接影响电机能否达到额定转速。三相 SPWM 的线电压峰值极限是直流母线电压的 0.866 倍如果电机额定电压是 380V母线电压至少要 439V。实际工程里母线电压 540V留有富余一般不需要进入过调制区。反而更常见的问题是 M 设太大导致最小脉冲宽度不足。IGBT 驱动芯片和光耦都有最小导通时间限制通常在 1 到 3μs。正弦波峰值附近占空比超过 97% 时小于 3μs 的窄脉冲会导致驱动输出畸变。28335 的死区模块不会自动修剪窄脉冲需要软件限制 M 上限例如 15kHz 载波周期 66.7μs留 2μs 最小脉宽最大占空比可到 93%此时 M 理论上限约为 0.93。Usual 取 0.85 到 0.9 比较稳妥。4.3 死区时间设置的两个边界条件死区时间不能拍脑袋定。下限由 IGBT 关断时间和驱动芯片传输延迟决定如果死区小于功率器件关断时间上下桥臂就会短暂直通轻则电流尖峰重则炸模块。上限由允许的输出电压误差决定死区时间越长电压损失越大低速时甚至引起电流畸变。以常见的 IGBT 模块为例比如英飞凌的 IKW40N120H3关断延迟典型值约 300ns加上驱动芯片的传输延迟死区 1μs 可以接受如果驱动是 PLC 光耦方案延迟更大建议死区给到 1.5 到 2μs。而 MOSFET 方案的关断速度更快500ns 到 1μs 即可。// 以 SYSCLKOUT 150MHz 为例 // 1μs 死区 150 个时钟周期 // 1.5μs 死区 225 个时钟周期 EPwm1Regs.DBRED.bit.DBRED 150; EPwm1Regs.DBFED.bit.DBFED 150;注意死区补偿的代码要在配置 DBRED 和 DBFED 之后立即写入 DBCTL 寄存器某些 28335 的勘误表提到 DBCTL 写入时死区长度寄存器软锁存不按顺序写会出现死区时间不对称。还有一个容易忽略的点ePWMxB 通道经过死区模块后相位比 ePWMxA 延迟 1μs而两者产生的平均电压不同。在闭环电流采样时刻上要避开死区边沿附近ADC 触发建议放在三角载波的波峰或波谷即占空比变化最剧烈的时刻过去之后。否则采到的电流包含死区效应导致的高频振荡分量。4.4 三相 SPWM 的相位偏移实现三相 SPWM 需要的三路调制波相差 120 度。在查表法实现里不用额外计算只要三个 ePWM 模块的 CMPA 分别从正弦表的不同偏移位置取值。ePWM2 的索引在 ePWM1 基础上加 100ePWM3 加 200对应 120 度和 240 度。但这里有一个载波相位的问题需要想清楚如果三路 ePWM 的计数器和 TBPRD 完全同相位那么三路三角载波重合SPWM 波形在任意时刻只有一个桥臂在切换共模电压较低。实现方式是把三个模块的计数器同步启动。// 同一时刻启动三路计数器 EPwm1Regs.TBCTL.bit.SWFSYNC 1;代码说明SWFSYNC 写 1 会产生同步信号同步脉冲会同时作用于 ePWM2 和 ePWM3 的 TBPHS 寄存器条件是这两个模块的 PHSEN 使能且 TBPHS 已预置。配置 ePWM2 和 ePWM3 时把 TBPHS 写入 0相位寄存器全零三路载波即同相。这是 Space Vector PWM 和 SPWM 在实现上的一个关键区别——SVPWM 通常让各相载波相错 120 度SPWM 传统上三相共用一个载波谐波特性和母线电压纹波都不同。5. 快速验证 SPWM 波形的三个有效手段5.1 用示波器确认载波周期和死区时间先接入直流母线电压较低的状态做测试。示波器探头接 ePWM1A 和 GND单次触发模式下观察 PWM 频率是否为 15kHz高电平时间是否在 10μs 到 55μs 之间缓慢变化。把时基拉到 20μs/div能看到占空比呈正弦规律变化。然后切到差分探头同时观察 ePWM1A 与 ePWM1B 的波形放大到 2μs/div检查两者是否在任何时刻都不会同时为高死区宽度是否符合设定值。5.2 死区不对称的一个快速判定法死区不对称会让输出电压产生偶次谐波电动机电流波形的正负半周明显不对称。用示波器测量 ePWM1A 高电平宽度在正弦波峰值和谷值附近分别记录数据两组数据的偏差不应超过 100ns。28335 死区计数器使用的时钟与系统时钟相同理论精度极高实际不对称主要来自死区寄存器配置的 SCALE 因子。DBRED 和 DBFED 都写 150 时若发现死区时间不等检查 DBCTL 寄存器的 DEDB_MODE 位是否被错误配置为双边对称模式。提示验证完一路后再扩展到三相。三相波形之间应有固定的 120 度相位关系用示波器的迟滞触发功能以 ePWM1A 作为触发源观察 ePWM2A 是否稳定偏移 2.22ms。这个时间对应 50Hz 频率下的 120 度相位差。如果相位偏移不稳定优先检查三个模块的 TBPHS 配置和同步信号是否正常。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进