手把手教你用TMS320F28335的EQEP模块搞定电机编码器(附完整CCS工程代码)
手把手教你用TMS320F28335的EQEP模块实现高精度电机控制
在工业自动化和机器人控制领域,精确的电机位置检测是实现闭环控制的关键。TMS320F28335作为TI公司经典的DSP控制器,其内置的增强型正交编码脉冲(eQEP)模块为电机控制工程师提供了强大的硬件支持。本文将带你从零开始,一步步实现基于EQEP模块的编码器数据采集系统。
1. 硬件准备与环境搭建
1.1 所需硬件组件
- TMS320F28335开发板(如TI官方ControlCARD)
- 增量式正交编码器(推荐2500线以上分辨率)
- 电机驱动板(如DRV8323)
- 调试用USB转串口模块
- 示波器(用于信号质量检查)
1.2 CCS开发环境配置
首先确保已安装以下软件:
- Code Composer Studio v10+
- C2000ware软件包(包含F28335外设驱动库)
- Uniflash编程工具
提示:建议使用最新版C2000ware,其中包含优化后的EQEP驱动示例代码。
创建新工程时,关键配置如下:
# 工程属性设置示例 Compiler version: TI v20.2.4.LTS Runtime model: --float_support=fpu32 Include paths: ${C2000WARE_ROOT}/device_support/f28335/common/include2. EQEP模块原理与寄存器解析
2.1 正交解码工作原理
增量式编码器输出两路相位差90°的方波信号(A/B相),通过检测两信号的相对相位关系可判断旋转方向:
| 旋转方向 | A相边沿时B相电平 | 计数方向 |
|---|---|---|
| 顺时针 | 高电平 | 递增 |
| 逆时针 | 低电平 | 递减 |
2.2 关键寄存器功能说明
EQEP模块的核心寄存器组及其功能:
// 位置计数器寄存器(32位) volatile struct QPOSCNT_REG { Uint32 QPOSCNT:32; // 当前位置计数值 } QPOSCNT; // 解码控制寄存器 volatile struct QDECCTL_REG { Uint16 QSRC:2; // 计数模式选择 Uint16 XCR:1; // 外部计数使能 Uint16 SOEN:1; // 同步输出使能 Uint16 SPSEL:1; // 同步脉冲选择 Uint16 IGATE:1; // 索引门控使能 Uint16 SWAP:1; // AB相交换 Uint16 reserved:9; } QDECCTL;3. 实战代码编写与调试
3.1 GPIO引脚配置
正确配置GPIO复用功能是第一步,以下是EQEP1的引脚初始化代码:
void InitEQep1Gpio(void) { EALLOW; // 使能上拉,配置为eQEP功能 GpioCtrlRegs.GPBPUD.bit.GPIO50 = 0; // EQEP1A GpioCtrlRegs.GPBPUD.bit.GPIO51 = 0; // EQEP1B GpioCtrlRegs.GPBQSEL2.bit.GPIO50 = 0; // 同步到SYSCLKOUT GpioCtrlRegs.GPBQSEL2.bit.GPIO51 = 0; GpioCtrlRegs.GPBMUX2.bit.GPIO50 = 1; // 配置为EQEP1A功能 GpioCtrlRegs.GPBMUX2.bit.GPIO51 = 1; // 配置为EQEP1B功能 EDIS; }3.2 EQEP模块初始化
完整的模块初始化流程包含以下关键步骤:
- 使能外设时钟
- 配置解码模式
- 设置位置计数器
- 使能捕获单元
- 启动模块
void InitEQep1(void) { // 单位定时器设置(100Hz @150MHz SYSCLKOUT) EQep1Regs.QUPRD = 1500000; // 正交解码模式配置 EQep1Regs.QDECCTL.all = 0x0000; EQep1Regs.QDECCTL.bit.QSRC = 0; // 正交计数模式 // 位置计数器配置 EQep1Regs.QEPCTL.all = 0x0000; EQep1Regs.QEPCTL.bit.FREE_SOFT = 2;// 仿真模式设置 EQep1Regs.QEPCTL.bit.PCRM = 0; // 索引事件复位计数器 EQep1Regs.QPOSMAX = 0xFFFFFFFF; // 最大计数值 // 使能捕获单元 EQep1Regs.QCAPCTL.bit.UPPS = 5; // 单位位置1/32分频 EQep1Regs.QCAPCTL.bit.CCPS = 7; // 捕获时钟1/128分频 EQep1Regs.QCAPCTL.bit.CEN = 1; // 使能捕获 // 最后使能整个模块 EQep1Regs.QEPCTL.bit.QPEN = 1; }4. 数据处理与性能优化
4.1 位置数据读取策略
为避免数据竞争,推荐采用以下读取顺序:
int32_t GetPosition(void) { int32_t pos; pos = EQep1Regs.QPOSCNT; // 读取位置计数器 EQep1Regs.QCLRCTL.bit.SW = 1; // 软件强制锁存 return pos; }4.2 速度计算算法
结合单位定时器实现速度测量:
float GetSpeedRPM(void) { float speed; Uint16 pos_diff; // 获取位置差值(自动处理32位溢出) pos_diff = EQep1Regs.QPOSLAT - EQep1Regs.QPOSILAT; // 转换为RPM值(假设1000线编码器,4倍频) speed = (float)pos_diff * 60.0 / (4000.0 * EQep1Regs.QUPRD * SysCtrlRegs.PLLSTS.bit.DIVSEL); return speed; }4.3 常见问题排查
- 计数方向错误:检查AB相序,必要时设置QDECCTL.SWAP位
- 信号抖动问题:调整GPIO输入滤波(GPxQSEL寄存器)
- 计数器溢出:合理设置QPOSMAX值或启用索引复位模式
5. 高级应用技巧
5.1 多电机同步控制
当需要控制多个电机时,EQEP模块的同步功能非常有用:
// 配置EQEP1作为主设备,输出同步脉冲 EQep1Regs.QDECCTL.bit.SOEN = 1; // 使能同步输出 EQep1Regs.QDECCTL.bit.SPSEL = 0; // 选择单位超时作为同步源 // 配置EQEP2作为从设备 EQep2Regs.QDECCTL.bit.SOEN = 0; // 禁用同步输出 EQep2Regs.QFLG.bit.IEL = 1; // 使能索引锁存5.2 位置比较单元应用
利用QPOSCMP实现精确位置触发:
// 设置比较值(90度位置) EQep1Regs.QPOSCMP = 1000; // 配置比较控制 EQep1Regs.QEPCTL.bit.PCSHDW = 1; // 使能影子寄存器 EQep1Regs.QEPCTL.bit.PCLOAD = 0; // 单位超时时加载5.3 低功耗模式优化
在电池供电应用中,可通过以下方式降低功耗:
// 进入低功耗模式前 EQep1Regs.QEPCTL.bit.QPEN = 0; // 禁用模块 GpioCtrlRegs.GPBPUD.bit.GPIO50 = 1;// 禁用上拉电阻 GpioCtrlRegs.GPBPUD.bit.GPIO51 = 1; // 唤醒后重新初始化 InitEQep1Gpio(); InitEQep1();