简介:本资源是基于TI TMS320F28335浮点DSP芯片的电机控制算法实践项目,面向嵌入式电机控制初学者与进阶开发者,聚焦SVPWM空间矢量调制、FOC磁场定向控制及主控时钟/开关频率(Major KPS)配置等核心环节,解决从理论到代码落地的关键断层问题。压缩包含112个文件,以77个头文件(.h)和3个C源码(如pmsm.c、F28335_vdc.c)为主体,辅以汇编启动与外设驱动(.asm)、链接命令(.cmd)、工程配置(.ccsproject、.cdtbuild)及编译输出(.out、.map),完整覆盖DSP28335开发全流程;包体仅566KB,轻量但结构严谨,便于快速导入CCS环境调试。已有625人学习下载,资源附带详细使用说明.txt,并包含PMSM传感器闭环相关模块(如PmSensored)及典型ADC校准、全局变量定义、PWM时序生成等关键实现,可直接用于永磁同步电机控制实验验证与算法优化。
1. 这不是“调个PWM就能转”的电机项目:TI F28335上跑通SVPWM+FOC闭环,真正卡在死区补偿、扇区判断与Park反变换的实时性边界上
你手头那块F28335开发板,刷进默认例程后电机能转,但一加负载就抖、一提速就失步、电流波形毛刺密布——问题大概率不在硬件接线,而在SVPWM矢量合成逻辑没对齐FOC坐标系旋转角,或Park反变换输出的αβ轴电压没经过死区时间补偿就直接喂给EPWM模块。这个TI28335SVPWM_svpwm_foc_majorkps项目,本质是一套经实机验证的“硬实时闭环链”:从ADC采样双路相电流(IA/IB)开始,经Clarke变换→Park变换→PI电流环→反Park→SVPWM扇区判定→非零矢量作用时间计算→死区插入→EPWM寄存器更新,全程在单个PWM周期(典型值50μs@20kHz开关频率)内完成。它不教你怎么点亮LED,而是直击FOC工程落地的三道硬坎:坐标变换的定点数精度损失、SVPWM七段式合成时序对EPWM寄存器双缓冲机制的依赖、Major KPS(此处实指主控时钟分频后确定的系统定时基准)与ADC触发同步的微秒级对齐。适合已能独立配置F28335 GPIO/ADC/EPWM外设,但调试FOC时总在“能跑空载、带载即崩”阶段反复横跳的工程师。
2. SVPWM实现:从扇区判断到死区补偿,F28335 EPWM寄存器级操作必须严丝合缝
SVPWM在F28335上的实现绝非查表输出占空比那么简单。其核心是将αβ轴电压矢量映射到六边形空间电压平面,通过两个相邻非零矢量与零矢量的组合逼近参考矢量。项目中pmsm.c与F28335_vdc.c共同构成SVPWM执行链,而DLOG4CHC.asm则暴露了底层时序关键点——它用汇编强制约束EPWM寄存器更新时机,避免因C代码执行延迟导致的相位偏移。
2.1 扇区判定与作用时间计算:避开浮点运算陷阱
F28335虽为浮点DSP,但FOC实时控制中大量使用Q15/Q31定点数。扇区判定依据αβ轴电压比值,标准公式为:
$$ Sector = \left\lfloor \frac{3}{\pi} \tan^{-1}\left(\frac{v_\beta}{v_\alpha}\right) \right\rfloor + 1 $$
但项目实际采用查表+比较法规避atan2耗时:
// pmsm.c 片段:扇区快速判定(Q15格式) int16 sector; if (v_alpha > 0) { if (v_beta > 0) { sector = (v_beta > v_alpha * 0x24F3) ? 2 : 1; // 0x24F3 ≈ tan(π/6) in Q15 } else { sector = (v_beta > -v_alpha * 0x24F3) ? 6 : 1; } } else { // 其余象限处理... }注意:
0x24F3是tan(30°)的Q15定点表示(0.57735 × 32768 ≈ 18915),而非浮点常量。若直接写0.57735f,编译器会插入浮点除法指令,单次运算耗时超200个CPU周期,远超PWM周期预算。
作用时间计算采用经典公式:
$$ T_1 = \frac{2}{3} \cdot \frac{V_{ref}}{V_{dc}} \cdot T_s \cdot \sin(60^\circ - \theta) $$
$$ T_2 = \frac{2}{3} \cdot \frac{V_{ref}}{V_{dc}} \cdot T_s \cdot \sin(\theta) $$
其中T_s为PWM周期,V_dc为母线电压采样值(来自DSP2833x_ADC_cal.asm校准后的ADC结果)。项目将sin/cos预计算为256点Q15查表,存储于DSP2833x_GlobalVariableDefs.c的sinTable[]数组中,访问耗时仅3个CPU周期。
2.2 EPWM寄存器配置:双缓冲机制与死区时间硬插入
F28335的EPWM模块支持影子寄存器(shadow register),确保占空比更新在PWM周期边界生效。项目在F28335_vdc.c中严格遵循此流程:
// 配置EPWM1A/B为互补输出,死区=150ns(对应12个SYSCLK周期) EPwm1Regs.DBRED = 12; // 死区上升沿延时 EPwm1Regs.DBFED = 12; // 死区下降沿延时 EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // 计数=0时设置EPWM1A EPwm1Regs.AQCTLA.bit.PRD = AQ_CLEAR; // 计数=PRD时清除EPWM1A EPwm1Regs.AQCTLB.bit.ZRO = AQ_CLEAR; // EPWM1B极性相反 EPwm1Regs.AQCTLB.bit.PRD = AQ_SET; // 关键:更新占空比必须写入CMPA/CMPB影子寄存器 EPwm1Regs.CMPA.half.CMPA = (uint16)cmpa_val; // 自动缓存至影子寄存器 EPwm1Regs.CMPB.half.CMPB = (uint16)cmpb_val;提示:
CMPA写入立即生效,但实际输出变化发生在下一个TBCTR=0时刻。若在中断服务程序(ISR)末尾直接写CMPA,而此时TBCTR已过零点,则新占空比要等到下个周期才生效,造成1个PWM周期的控制延迟。项目通过EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE禁用同步,确保更新即时性。
死区时间由DBRED/DBFED寄存器设定,单位为SYSCLK周期。假设SYSCLK=150MHz,则12个周期=80ns,满足IGBT驱动芯片(如IR2110)最小死区要求。若实测桥臂直通,需检查DBRED值是否小于驱动芯片传播延迟。
2.3 Major KPS:主时钟分频链与ADC触发同步
“Major KPS”在此项目中并非脉冲计数,而是指SYSCLK经PLL倍频后,再由CLKDIV分频得到的CPU定时基准。DSP2833x_usDelay.asm中的DELAY_US函数依赖此基准:
; DSP2833x_usDelay.asm 片段 DELAY_US: MOV ACC, #0x00000001 LSL ACC, #16 ; ACC = 1 << 16 = 65536 MOV AR0, #0x00000000 SUB ACC, #1 BCC DELAY_US, NC ; 循环直到ACC=0 RET该延时函数每循环1次耗时2*CLKIN周期(CLKIN=30MHz时,1μs需60个CLKIN周期)。而ADC触发必须与此基准严格同步:AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 0x0005(EPWM1 SOCA事件),且EPwm1Regs.TBCTL.bit.PHSEN = 1启用相位同步。若EPWM1的TBPRD寄存器值未按Major KPS整数倍设置,ADC采样点将漂移,导致Clarke变换输入相位错乱。
3. FOC核心:Clarke/Park变换的定点实现与电流环PI参数整定实战
FOC的数学本质是坐标系旋转——将三相静止坐标系(abc)→两相静止坐标系(αβ)→两相旋转坐标系(dq)。项目在pmsm.c中全部采用Q31定点运算,规避浮点开销,但需警惕溢出与截断误差。
3.1 Clarke变换:从三相电流到αβ轴的无损映射
Clarke变换公式为:
$$ \begin{bmatrix} i_\alpha \ i_\beta \end{bmatrix} = \begin{bmatrix} 1 & -\frac{1}{2} & -\frac{1}{2} \ 0 & \frac{\sqrt{3}}{2} & -\frac{\sqrt{3}}{2} \end{bmatrix} \begin{bmatrix} i_a \ i_b \ i_c \end{bmatrix} $$
由于i_c = -(i_a + i_b),可简化为两输入:
// pmsm.c: Q31定点Clarke变换(系数已预标定) #define CLARKE_ALPHA_COEF 0x7FFFFFFF // 1.0 in Q31 #define CLARKE_BETA_COEF 0x40000000 // 0.5 in Q31 #define SQRT3_OVER2_Q31 0x6ED9EBAF // √3/2 ≈ 0.866 in Q31 int32 i_alpha = (int32)i_a_q31 - ((int32)i_b_q31 >> 1); // i_a - i_b/2 int32 i_beta = (int32)i_b_q31 * SQRT3_OVER2_Q31; // i_b * √3/2注意:
i_b_q31为Q31格式(-1.0 ~ +0.999999),乘以SQRT3_OVER2_Q31后结果需右移15位才能保持Q31。项目在DSP2833x_GlobalVariableDefs.c中定义i_beta = mult32(i_b_q31, SQRT3_OVER2_Q31) >> 15,mult32为内联汇编乘法,避免C语言隐式类型转换损耗。
3.2 Park变换:旋转变换的核心是sin/cos查表与Q31移位
Park变换将αβ轴电流投影到旋转的dq轴:
$$ i_d = i_\alpha \cos\theta + i_\beta \sin\theta $$
$$ i_q = -i_\alpha \sin\theta + i_\beta \cos\theta $$
项目使用256点正弦表,索引由电角度theta_elec(单位:弧度×2^15)计算:
// theta_elec为Q15格式(0~32767对应0~2π) uint16 idx = (uint16)(theta_elec >> 7); // 右移7位得0~255索引 int32 sin_theta = sinTable[idx]; int32 cos_theta = cosTable[idx]; // Q31 × Q15 = Q46,需右移15位得Q31 i_d = (mult32(i_alpha, cos_theta) >> 15) + (mult32(i_beta, sin_theta) >> 15); i_q = (mult32(i_beta, cos_theta) >> 15) - (mult32(i_alpha, sin_theta) >> 15);3.3 电流环PI控制器:参数整定与抗饱和处理
FOC性能瓶颈常在电流环响应。项目采用位置式PI算法,Kp=0.05,Ki=100(Q15格式):
// pmsm.c: dq轴电流PI环(Q15输入,Q31输出) int32 err_d = i_d_ref_q15 - i_d_q15; int32 err_q = i_q_ref_q15 - i_q_q15; // 积分项抗饱和:限制累加值范围 pid_d.integral += (err_d * Ki_q15) >> 15; if (pid_d.integral > 0x007FFFFF) pid_d.integral = 0x007FFFFF; // +2.0 if (pid_d.integral < 0xFF800000) pid_d.integral = 0xFF800000; // -2.0 pid_d.output = (err_d * Kp_q15) >> 15 + pid_d.integral;实战技巧:
Kp过大会导致电流超调振荡,Ki过大会引起积分饱和。建议先设Ki=0,调Kp使阶跃响应无超调;再缓慢增加Ki消除稳态误差。实测中,i_q环Kp需比i_d环大2~3倍,因q轴直接关联电磁转矩。
4. PMSM传感器数据融合:霍尔信号解码与电角度估算的硬实时协同
项目中PmSensored指向永磁同步电机的霍尔传感器反馈。F28335通过GPIO捕获霍尔边沿,结合编码器(若有)实现电角度高精度估算,这是FOC启动和低速运行的关键。
4.1 霍尔状态机解码:6步换相与电角度粗估
霍尔传感器输出3位格雷码(U/V/W),对应6个180°电角度区间。项目在pmsm.c中构建状态机:
// 霍尔状态到扇区映射表(U,V,W → 电角度区间) const uint8 hall_to_sector[8] = {0, 1, 0, 2, 0, 3, 0, 4}; // 索引为霍尔值 uint8 hall_state = (GpioDataRegs.GPADAT.bit.GPIO0 << 2) | (GpioDataRegs.GPADAT.bit.GPIO1 << 1) | GpioDataRegs.GPADAT.bit.GPIO2; uint8 sector = hall_to_sector[hall_state]; int32 theta_elec = sector * 0x2AAA; // 0x2AAA = π/3 in Q15 (60°)4.2 编码器辅助:QEP模块与电角度精修
若电机配增量式编码器,F28335的QEP(Quadrature Encoder Pulse)模块可提供高分辨率位置反馈。DSP2833x_Headers_nonBIOS.cmd中已预留QEP寄存器地址:
// 初始化QEP(QEP1) Qep1Regs.QDECCTL.bit.QSRC = 0; // QEP模式 Qep1Regs.QEPCTL.bit.FREE_SOFT = 2; // 自由运行模式 Qep1Regs.QPOSINIT = 0; Qep1Regs.QPOSMAX = 0xFFFF;电角度theta_elec由霍尔粗估+编码器细调构成:
$$ \theta_{elec} = \theta_{hall} + \frac{2\pi}{PP} \cdot \frac{pos_{qep}}{res_{qep}} $$
其中PP为电机极对数,res_qep为编码器线数×4。项目将pos_qep读取嵌入EPWM周期中断,确保角度更新与SVPWM同步。
4.3 无感FOC启动预备:堵转检测与初始位置辨识
虽然本项目含传感器,但majorkps参数设计已预留无感启动接口。F28335_vdc.c中motor_start_routine()函数包含:
- 高频注入检测:在d轴注入1kHz方波电压,采样q轴电流响应幅值,判断转子初始位置;
- 堵转保护:若连续5个PWM周期
|i_q| > 1.2 * i_q_ref且speed < 5rpm,强制停机并置位FAULT_FLAG。
关键参数:
i_q_ref为启动转矩电流,典型值0.3~0.5倍额定电流;speed由QEP位置微分计算,需加一阶低通滤波(tau=10ms)抑制噪声。
5. 调试与验证:用CLA加速器卸载FOC计算负载,实测波形诊断三类典型故障
F28335的CLA(Control Law Accelerator)是独立于CPU的32位浮点协处理器,可将FOC中计算密集型任务(如Park反变换、SVPWM时间计算)迁移至此,释放CPU处理通信与保护逻辑。项目虽未启用CLA,但.ccsproject文件结构已预留配置入口。
5.1 波形诊断:四通道逻辑分析仪抓取关键信号时序
使用TI Code Composer Studio的Graph工具,配置4通道实时捕获:
- Channel 1:
i_a(ADCRESULT0) - Channel 2:
i_b(ADCRESULT1) - Channel 3:
v_alpha(Clarke变换输出) - Channel 4:
EPWM1A(实际驱动波形)
典型故障波形特征:
| 故障现象 | i_a/i_b波形 | v_alpha/v_beta波形 | EPWM1A波形 | 根本原因 |
|---|---|---|---|---|
| 坐标系错位 | 正弦但相位偏移 | αβ轴幅值不等 | SVPWM扇区错误 | theta_elec未校准或霍尔相序接反 |
| 死区不足 | 桥臂电流尖峰 | v_alpha突变毛刺 | 上下管重叠导通 | DBRED/DBFED值过小或驱动芯片延迟未补偿 |
| PI参数失调 | i_q超调振荡 | v_d持续负压 | PWM占空比剧烈跳变 | Kp过大或Ki未限幅 |
5.2 实时变量监控:通过XINTF接口外挂SRAM存储历史数据
DSP2833x_usDelay.asm中DELAY_US函数被复用为数据采样触发源。在main()循环中:
// 每10ms采样一次,存入XINTF Zone6 SRAM if (sample_counter++ > 100) { // 100 × 100μs = 10ms *(volatile uint16*)0x100000 = (uint16)i_a_q15; // 地址0x100000为SRAM起始 *(volatile uint16*)0x100002 = (uint16)i_q_q15; sample_counter = 0; }上位机通过JTAG读取SRAM,生成i_q响应曲线,验证PI整定效果。
5.3 关键技巧:用EPWM TZ(Trip Zone)实现硬件级过流保护
避免软件保护延迟导致IGBT炸机,项目在F28335_vdc.c中启用TZ模块:
// 配置TZ1为CBC(Cycle-by-Cycle)模式,连接GPIO34(过流信号) EPwm1Regs.TZSEL.bit.OSHT1 = 1; // TZ1触发关断 EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_LO; // A相强制低 EPwm1Regs.TZCTL.bit.TZB = TZ_FORCE_LO; // B相强制低 EPwm1Regs.TZEINT.bit.OST = 1; // 开启OST中断当硬件过流信号拉低GPIO34,TZ1在100ns内强制关闭EPWM输出,比CPU中断快2个数量级。
本文还有配套的精品资源,点击获取