文档版本:V1.0
编写日期:2026-07-23
适用平台:TMS320F28377D + AM26LS32ACDR + 三丰位移传感器

目录

  1. 系统概述

  2. 硬件设计

    • 2.1 系统硬件架构

    • 2.2 AM26LS32ACDR 差分接收器

    • 2.3 硬件连接详表

    • 2.4 PCB 布局建议

  3. eQEP 模块概述

    • 3.1 模块简介

    • 3.2 主要功能单元

    • 3.3 输入信号说明

    • 3.4 eQEP 基地址与寄存器映射

  4. eQEP 编程实现方法

    • 4.1 GPIO 引脚配置

    • 4.2 eQEP 模块初始化

    • 4.3 位置计数器工作模式

    • 4.4 4倍频计数原理

    • 4.5 位置数据读取

    • 4.6 中断配置

    • 4.7 DriverLib 函数速查

  5. 本驱动软件实现

    • 5.1 数据结构定义

    • 5.2 初始化函数实现

    • 5.3 定时中断读取实现

    • 5.4 双核通信实现

    • 5.5 主程序调用流程

  6. 寄存器参考速查表

  7. 注意事项与扩展建议

  8. 总结

  9. 附录:完整源代码


1. 系统概述

本文档描述了一套基于 TMS320F28377D 的增强型正交编码器脉冲(eQEP)模块,用于采集 三丰(Mitutoyo)位移传感器 输出信号并实现位移检测的驱动程序。该驱动已在实际焊接控制系统中部署,通过 eQEP 硬件解码、定时中断读取和双核通信,实现了高精度、低延迟的位移监控。

1.1 技术指标

  • 传感器类型:三丰位移传感器(差分正交信号输出)

  • 信号调理:AM26LS32ACDR 差分接收器

  • 主控芯片:TMS320F28377D(双核 C28x,200MHz)

  • eQEP 模块:EQEP3(正交计数模式)

  • 采样频率:2kHz(ePWM3 周期中断)

  • 位置分辨率:32 位(最大 0xFFFFFFFF)

  • 通信方式:IPC 共享内存(CPU1 → CPU2)

1.2 应用场景

本驱动适用于以下工业控制场景:

  • 电阻焊焊接位移监控

  • 缝焊位置控制

  • 多级限位报警

  • 位置闭环控制


2. 硬件设计

2.1 系统硬件架构

整个位移采集系统的硬件信号链如下:

三丰位移传感器(差分信号)→ AM26LS32ACDR(差分转单端)→ TMS320F28377D eQEP模块(GPIO)

三丰位移传感器通常输出差分正交信号(A+、A-、B+、B-),这类信号采用 RS-422 电气标准,具有抗共模干扰能力强、适合长距离传输(可达 1000 米)的特点。但 F28377D 的 eQEP 模块直接接受的是单端 TTL 电平信号,因此需要在传感器与 DSP 之间加入一个信号调理环节——差分线路接收器

2.2 AM26LS32ACDR 差分接收器

AM26LS32ACDR 是德州仪器(TI)推出的一款四路差分线路接收器,专为工业级长距离、高抗干扰通信场景设计。其核心功能是将差分信号(如 RS-422 标准)转换为标准 TTL 逻辑电平输出。

2.2.1 主要电气特性
参数规格
接收器数量4路独立接收器
电源电压单 5V 供电(4.75V ~ 5.25V)
数据速率最高 10 Mbps
共模输入范围±7V
输入灵敏度±200mV
输入迟滞50mV(典型值)
输入阻抗最小 12kΩ
输出类型三态输出,TTL 兼容
工作温度(AC 版本)0°C ~ 70°C
工作温度(AI 版本)-40°C ~ 85°C
封装SOIC-16、PDIP-16、TSSOP-16 等
2.2.2 引脚功能说明(SOIC-16 封装)
引脚名称类型功能描述
11A输入通道1 差分输入(同相)
21B输入通道1 差分输入(反相)
31Y输出通道1 单端逻辑输出
4G输入高电平有效使能
5G输入低电平有效使能
62A输入通道2 差分输入(同相)
72B输入通道2 差分输入(反相)
8GND电源
93B输入通道3 差分输入(反相)
103A输入通道3 差分输入(同相)
113Y输出通道3 单端逻辑输出
124B输入通道4 差分输入(反相)
134Y输出通道4 单端逻辑输出
144A输入通道4 差分输入(同相)
15G输入低电平有效使能(内部连接)
16VCC电源+5V 电源
2.2.3 核心功能
  1. 差分信号接收与转换:芯片内部每个接收器将差分输入对(A+ / A-)的电压差与内置阈值(典型值 ±200mV)进行比较,转换为单端 TTL 电平输出。差分传输方式使得信号在长距离传输时仍能保持良好的信号完整性。

  2. 使能控制:四个接收器共用使能功能,提供高电平有效(G) 和 低电平有效(G) 两种控制输入,可灵活配置接收器的启用/禁用状态。

  3. 失效防护:当输入端处于开路状态时,失效防护设计可确保输出始终为高电平,避免不确定状态。

  4. 输入迟滞:50mV 的输入迟滞有效提升了抗干扰能力,防止信号在阈值附近抖动时输出不稳定。

2.2.4 功能真值表(每个接收器)
差分输入(A - B)GG输出 Y
≥ VIT+(≥ 200mV)HXH
≤ VIT-(≤ -200mV)HXL
不确定区间HX不确定
XLXZ(高阻)
XXHZ(高阻)
开路HXH

:H = 高电平,L = 低电平,X = 无关,Z = 高阻抗

2.3 硬件连接详表

2.3.1 AM26LS32ACDR 引脚连接

本设计使用 AM26LS32ACDR 的通道1 和通道2 分别处理 A 相和 B 相信号:

AM26LS32ACDR 引脚连接目标说明
1A(引脚1)传感器 A+差分输入正端
1B(引脚2)传感器 A-差分输入负端
1Y(引脚3)F28377D EQEP3A(GPIO10)单端 A 相输出
6(引脚6)传感器 B+差分输入正端
7(引脚7)传感器 B-差分输入负端
5(引脚5)F28377D EQEP3B(GPIO11)单端 B 相输出
G(引脚4)+5V高电平使能(始终使能)
G(引脚5)GND低电平使能(始终使能)
VCC(引脚16)+5V电源
GND(引脚8)GND
2.3.2 F28377D GPIO 配置
信号引脚复用功能配置说明
EQEP3AGPIO10eQEP3 功能同步输入模式
EQEP3BGPIO11eQEP3 功能同步输入模式
2.3.3 电平兼容性说明

AM26LS32ACDR 在 5V 供电时输出高电平典型值接近 5V,最低保证 2.7V。F28377D 的 GPIO 为 5V 容忍(5V Tolerant) 设计,因此 输出引脚(1Y、2Y)可直接连接到 F28377D 的 EQEPxA 和 EQEPxB 引脚,无需额外的电平转换电路。

2.4 PCB 布局建议

  • 旁路电容:在 VCC 与 GND 之间靠近芯片位置放置 0.1μF 旁路电容,以抑制电源噪声

  • 差分走线:差分输入走线应成对、靠近布线,以保持差分阻抗匹配并减少共模噪声耦合

  • 走线隔离:输入走线尽量远离电源或输出走线,避免寄生耦合

  • 地平面:建议使用完整的地平面,降低 EMI 和信号串扰

  • 输入保护:可在信号输入端添加 TVS 二极管以防静电和过压


3. eQEP 模块概述

3.1 模块简介

增强型正交编码器脉冲(eQEP)模块用于直接与线性或旋转增量式编码器接口,获取旋转机械的位置、方向和速度信息,广泛应用于高性能运动与位置控制系统。

TMS320F28377D 器件具有多达 3 个 eQEP 模块(EQEP1、EQEP2、EQEP3),本设计选用 EQEP3

3.2 主要功能单元

eQEP 外设包含以下主要功能单元:

功能单元缩写功能描述
可编程输入滤波GPIO MUX每个引脚可配置输入同步与滤波
正交解码器单元QDU解码 A/B 相信号,生成时钟和方向
位置计数器与控制单元PCCU位置测量、计数器复位与锁存
正交边沿捕获单元QCAP低速测量,测量单位位置事件间的时间
单元时基UTIME速度/频率测量的时间基准
看门狗定时器QWDOG检测电机堵转(无 QCLK 事件)

3.3 输入信号说明

eQEP 模块包含以下输入引脚:

信号功能本设计使用情况
QEPA正交 A 相信号(或时钟输入)✅ 使用
QEPB正交 B 相信号(或方向输入)✅ 使用
QEPI索引/零位信号,用于绝对位置参考❌ 未使用
QEPS选通输入,通用位置锁存信号❌ 未使用

3.4 eQEP 基地址与寄存器映射

eQEP 模块起始地址结束地址
EQep1Regs0x0000_51000x0000_513F
EQep2Regs0x0000_51400x0000_517F
EQep3Regs0x0000_51800x0000_51BF

关键寄存器列表

偏移地址寄存器功能
0x00QPOSCNT当前位置计数器(32位)
0x02QPOSINIT初始化位置值
0x04QPOSMAX最大位置计数值
0x06QPOSCMP位置比较值
0x08QPOSILAT索引位置锁存
0x0AQPOSSLAT选通位置锁存
0x0CQPOSLAT位置锁存
0x0EQUTMR单元定时器
0x10QUPRD单元周期寄存器
0x12QWDTMR看门狗定时器
0x13QWDPRD看门狗周期寄存器
0x14QDECCTL解码控制寄存器
0x15QEPCTLeQEP 控制寄存器
0x16QCAPCTL捕获控制寄存器
0x17QPOSCTL位置比较控制寄存器
0x18QEINT中断使能寄存器
0x19QFLG中断标志寄存器
0x1AQCLR中断清除寄存器
0x1BQFRC中断强制寄存器
0x1CQEPSTS状态寄存器
0x1DQCTMR捕获定时器
0x1EQCPRD捕获周期寄存器
0x1FQCTMRLAT捕获定时器锁存
0x20QCPRDLAT捕获周期锁存

4. eQEP 编程实现方法

4.1 GPIO 引脚配置

eQEP 输入 GPIO 引脚必须配置为同步输入模式(带或不带输入滤波),不能使用异步模式。

c

void InitEQep3Gpio(void)
{
    EALLOW;

    // 配置引脚复用功能
    GpioCtrlRegs.GPAMUX1.bit.GPIO10 = 1;  // GPIO10 → EQEP3A
    GpioCtrlRegs.GPAMUX1.bit.GPIO11 = 1;  // GPIO11 → EQEP3B

    // 配置为同步输入模式(带 3 个采样周期的输入滤波)
    GpioCtrlRegs.GPAQSEL1.bit.GPIO10 = 2; // 3-sample qualification
    GpioCtrlRegs.GPAQSEL1.bit.GPIO11 = 2;

    // 可选:使能内部上拉电阻
    GpioCtrlRegs.GPAPUD.bit.GPIO10 = 0;
    GpioCtrlRegs.GPAPUD.bit.GPIO11 = 0;

    EDIS;
}

重要:配置 GPIO 时应先配置 GPyGMUX 位,再配置 GPyMUX 位,以避免引脚上产生毛刺。

4.2 eQEP 模块初始化

4.2.1 解码控制寄存器(QDECCTL)
位域功能选项说明
QSRC[15:14]位置计数器时钟源选择00正交计数模式
01方向-计数模式
10上升计数模式(频率测量)
11下降计数模式(频率测量)
SOEN[13]同步输出使能0/1位置比较同步输出
SPSEL[12]同步输出引脚选择0/1索引引脚或选通引脚
XCR[11]外部时钟倍率0/10=双边沿计数(2x),1=单边沿计数
SWAP[10]A/B 输入交换0/1交换 QEPA/QEPB 输入
IGATE[9]索引门控0/1用选通信号门控索引脉冲
QAP[8]QEPA 输入极性0/10=不反相,1=反相
QBP[7]QEPB 输入极性0/10=不反相,1=反相
QIP[6]QEPI 输入极性0/10=不反相,1=反相
QSP[5]QEPS 输入极性0/10=不反相,1=反相
4.2.2 eQEP 控制寄存器(QEPCTL)
位域功能选项说明
FREE_SOFT[15:14]仿真模式00暂停时立即停止
01暂停时完成当前周期后停止
10/11暂停时不受影响
PCRM[13:12]位置计数器复位模式00索引事件复位
01最大位置复位
10首次索引事件复位
11单元超时复位
SEI[11:10]选通事件初始化00/01禁用
10选通上升沿初始化
11方向相关边沿初始化
IEI[9:8]索引事件初始化00/01禁用
10索引上升沿初始化
11索引下降沿初始化
SWI[7]软件初始化0/1写1初始化位置计数器
SEL[6]选通事件锁存0/1选通边沿锁存位置计数器
IEL[5:4]索引事件锁存00保留
01索引上升沿锁存
10索引下降沿锁存
11索引事件标志锁存(软件索引标志)
QPEN[3]eQEP 使能0/10=复位/禁用,1=使能
QCLM[2]锁存模式0/10=CPU读取时锁存,1=单元超时时锁存
UTE[1]单元定时器使能0/1使能单元定时器
WDE[0]看门狗使能0/1使能看门狗定时器
4.2.3 完整初始化代码

c

void POSSPEED_Init(void)
{
    //-------------------------------------------------------------------------
    // 1. 解码控制寄存器 (QDECCTL)
    //-------------------------------------------------------------------------
    EQep3Regs.QDECCTL.bit.QSRC = 00;    // 正交计数模式
    EQep3Regs.QDECCTL.bit.XCR = 0;      // 2x 分辨率(双边沿计数)
    EQep3Regs.QDECCTL.bit.SWAP = 0;     // 不交换 A/B 输入
    EQep3Regs.QDECCTL.bit.QAP = 0;      // QEPA 不反相
    EQep3Regs.QDECCTL.bit.QBP = 0;      // QEPB 不反相

    //-------------------------------------------------------------------------
    // 2. eQEP 控制寄存器 (QEPCTL)
    //-------------------------------------------------------------------------
    EQep3Regs.QEPCTL.bit.FREE_SOFT = 2; // 仿真暂停时计数器继续运行
    EQep3Regs.QEPCTL.bit.PCRM = 00;     // 索引事件复位位置计数器
    EQep3Regs.QEPCTL.bit.IEI = 2;       // 索引上升沿初始化位置计数器
    EQep3Regs.QEPCTL.bit.SEI = 0;       // 选通事件初始化禁用
    EQep3Regs.QEPCTL.bit.SEL = 0;       // 选通事件锁存禁用
    EQep3Regs.QEPCTL.bit.IEL = 0;       // 索引事件锁存禁用
    EQep3Regs.QEPCTL.bit.UTE = 1;       // 使能单元定时器
    EQep3Regs.QEPCTL.bit.QCLM = 1;      // 单元超时时锁存位置
    EQep3Regs.QEPCTL.bit.WDE = 0;       // 禁用看门狗(本应用未使用)

    //-------------------------------------------------------------------------
    // 3. 位置计数器配置 (QPOSMAX / QPOSINIT)
    //-------------------------------------------------------------------------
    EQep3Regs.QPOSMAX = 0xFFFFFFFF;     // 32 位最大计数值
    EQep3Regs.QPOSINIT = 0;             // 初始化位置值

    //-------------------------------------------------------------------------
    // 4. 捕获单元配置 (QCAPCTL) - 用于低速测速(本设计未使用)
    //-------------------------------------------------------------------------
    EQep3Regs.QCAPCTL.bit.UPPS = 5;     // 每 32 个 QCLK 产生单位位置事件
    EQep3Regs.QCAPCTL.bit.CCPS = 2;     // 捕获时钟 = SYSCLK/4
    EQep3Regs.QCAPCTL.bit.CEN = 1;      // 使能捕获单元

    //-------------------------------------------------------------------------
    // 5. 单元定时器配置 (QUPRD)
    //-------------------------------------------------------------------------
    EQep3Regs.QUPRD = 2000000;          // 200MHz 下产生 100Hz 超时

    //-------------------------------------------------------------------------
    // 6. 使能 eQEP 模块
    //-------------------------------------------------------------------------
    EQep3Regs.QEPCTL.bit.QPEN = 1;      // QEP 使能
}

4.3 位置计数器工作模式

位置计数器可通过 QEPCTL[PCRM] 位配置为以下四种模式:

PCRM 值模式正向计数反向计数
00索引事件复位索引事件时复位为 0索引事件时复位为 QPOSMAX
01最大位置复位达到 QPOSMAX 时复位为 0达到 0 时复位为 QPOSMAX
10首次索引事件复位首次索引事件复位为 0,后续按最大位置模式运行
11单元超时复位单元超时事件时复位

本设计采用 PCRM = 00(索引事件复位) 模式,配合 IEI = 2(索引上升沿初始化),使位置计数器在每个索引脉冲的上升沿复位。

4.4 4倍频计数原理

eQEP 模块通过在 QEPA 和 QEPB 信号的上升沿和下降沿均产生计数脉冲(QCLK),实现 4 倍频 的位置分辨率提升:

  • 传感器每输出一个完整的 A/B 周期,位置计数器增加 4 个计数值

  • 例如:1000 线/转的编码器,eQEP 可提供 4000 个计数/转 的分辨率

计数方向判定

  • 正向旋转:QEPA 信号领先 QEPB 信号 90°

  • 反向旋转:QEPB 信号领先 QEPA 信号 90°

4.5 位置数据读取

读取当前位置计数器值,可直接访问 QPOSCNT 寄存器:

c

// 读取 32 位位置计数值
int32 position = EQep3Regs.QPOSCNT;

// 或使用 DriverLib 函数
int32 position = EQEP_getPosition(EQEP3_BASE);

状态标志读取

c

// 读取方向标志(1=正向,0=反向)
uint16_t direction = EQep3Regs.QEPSTS.bit.QDF;

// 读取单元位置事件标志
uint16_t upevent = EQep3Regs.QEPSTS.bit.UPEVNT;

// 清除标志位(写1清除)
EQep3Regs.QEPSTS.bit.UPEVNT = 1;

4.6 中断配置

eQEP 模块支持 11 种中断事件:

中断事件标志位说明
PCE位置计数器错误索引事件时 QPOSCNT 不等于 0 或 QPOSMAX
PHE正交相位错误QEPA 和 QEPB 同时跳变(无效状态转换)
QDCQEP 方向改变方向变化
WTO看门狗超时看门狗定时器超时
PCU位置计数器上溢计数超过 QPOSMAX
PCO位置计数器下溢计数低于 0
PCR位置比较就绪影子寄存器加载完成
PCM位置比较匹配QPOSCNT 等于 QPOSCMP
SEL选通事件锁存选通信号锁存位置计数器
IEL索引事件锁存索引信号锁存位置计数器
UTO单元超时单元定时器超时

中断使能配置示例

c

// 使能单元超时中断
EQep3Regs.QEINT.bit.UTO = 1;

// 使能位置比较匹配中断
EQep3Regs.QEINT.bit.PCM = 1;

// 在 PIE 中使能 eQEP 中断(eQEP3 中断在 PIE 组 3.4)
PieCtrlRegs.PIEIER3.bit.INTx4 = 1;
IER |= M_INT3;

中断服务程序框架

c

__interrupt void eqep3_isr(void)
{
    // 检查中断源
    if(EQep3Regs.QFLG.bit.UTO == 1)
    {
        // 处理单元超时事件
        // ...
        
        // 清除中断标志
        EQep3Regs.QCLR.bit.UTO = 1;
    }
    
    if(EQep3Regs.QFLG.bit.PCM == 1)
    {
        // 处理位置比较匹配事件
        // ...
        EQep3Regs.QCLR.bit.PCM = 1;
    }
    
    // 清除全局中断标志
    EQep3Regs.QCLR.bit.INT = 1;
    
    // 应答 PIE
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}

4.7 DriverLib 函数速查

TI C2000Ware 提供了 eQEP 的 DriverLib 函数,常用函数列表如下:

功能分类DriverLib 函数说明
位置读取EQEP_getPosition(base)读取当前计数值
位置设置EQEP_setPosition(base, value)设置计数值
初始位置EQEP_setInitialPosition(base, value)设置初始化值
最大位置EQEP_setPositionCounterConfig(base, max, mode)配置最大值和模式
解码配置EQEP_setDecoderConfig(base, config)配置解码模式
输入极性EQEP_setInputPolarity(base, config)配置输入极性
模块使能EQEP_enableModule(base)使能 eQEP
模块禁用EQEP_disableModule(base)禁用 eQEP
捕获配置EQEP_setCaptureConfig(base, config)配置捕获单元
捕获使能EQEP_enableCapture(base)使能捕获单元
中断使能EQEP_enableInterrupt(base, intFlags)使能指定中断
中断禁用EQEP_disableInterrupt(base, intFlags)禁用指定中断
中断标志EQEP_getInterruptStatus(base)读取中断标志
中断清除EQEP_clearInterruptStatus(base, intFlags)清除中断标志
方向读取EQEP_getDirection(base)读取当前方向
状态读取EQEP_getStatus(base)读取状态寄存器
位置锁存EQEP_getPositionLatch(base)读取锁存位置

5. 本驱动软件实现

5.1 数据结构定义

5.1.1 位移结构体

c

// 位移参数结构体
typedef struct {
    int32 Val;            // 当前计数值
    uint16 Level1Val;     // 阈值1(微米或计数单位)
    uint16 Level2Val;     // 阈值2
    uint16 Level3Val;     // 阈值3
    uint16 Level1Out;     // 比较结果位1
    uint16 Level2Out;     // 比较结果位2
    uint16 Level3Out;     // 比较结果位3
    uint16 Reset;         // 复位请求标志
} DisTypDef;

// 全局位移变量
volatile DisTypDef Dis;
5.1.2 中断计数变量

c

volatile Uint16 EndDelayCnt;      // 结束信号延时计数器
volatile Uint16 EndDelayCnt1;     // 机头电磁阀延时计数器
volatile int DisCNT;              // 位移采集计数
volatile int DisWave[10];         // 位移波形缓存(调试用)

5.2 初始化函数实现

c

void POSSPEED_Init(void)
{
    // 单元定时器周期:200MHz 下产生 100Hz 超时
    EQep3Regs.QUPRD = 2000000;

    // 解码控制:正交计数模式
    EQep3Regs.QDECCTL.bit.QSRC = 00;

    // 仿真模式:暂停时继续计数
    EQep3Regs.QEPCTL.bit.FREE_SOFT = 2;

    // 位置计数器复位模式:索引事件复位
    EQep3Regs.QEPCTL.bit.PCRM = 00;

    // 索引上升沿初始化位置计数器为 QPOSINIT(默认0)
    EQep3Regs.QEPCTL.bit.IEI = 2;

    // 使能单元定时器
    EQep3Regs.QEPCTL.bit.UTE = 1;

    // 单元超时时锁存位置值
    EQep3Regs.QEPCTL.bit.QCLM = 1;

    // 最大计数值(32位全范围)
    EQep3Regs.QPOSMAX = 0xFFFFFFFF;

    // 使能 eQEP 模块
    EQep3Regs.QEPCTL.bit.QPEN = 1;

    // 捕获单元配置(用于低速测速,本设计仅设置但未使用)
    EQep3Regs.QCAPCTL.bit.UPPS = 5;    // 每 32 个 QCLK 产生单位位置事件
    EQep3Regs.QCAPCTL.bit.CCPS = 2;    // 捕获时钟分频
    EQep3Regs.QCAPCTL.bit.CEN = 1;     // 使能捕获单元
}

5.3 定时中断读取实现

5.3.1 中断配置

本设计未使用 eQEP 硬件中断,而是采用 ePWM3 周期中断(2kHz)定时读取位置计数器:

c

// 主程序中配置中断
PieVectTable.EPWM3_INT = &prdTick;
IER |= M_INT3;
PieCtrlRegs.PIEIER3.bit.INTx3 = 1;
5.3.2 中断服务程序

c

__interrupt void prdTick(void)
{
    // 清除状态标志(单位位置事件和溢出标志)
    EQep3Regs.QEPSTS.all = 0x88;

    // 读取当前计数值(32位)
    Dis.Val = EQep3Regs.QPOSCNT;

    // 三级位置比较
    if(Dis.Val > Dis.Level1Val)
        Dis.Level1Out = 1;
    else
        Dis.Level1Out = 0;

    if(Dis.Val > Dis.Level2Val)
        Dis.Level2Out = 1;
    else
        Dis.Level2Out = 0;

    if(Dis.Val > Dis.Level3Val)
        Dis.Level3Out = 1;
    else
        Dis.Level3Out = 0;

    // 打包状态位(低3位),通过 IPC 传递给 CPU2
    usCPU01Buffer1[0] = Dis.Level1Out | 
                        (Dis.Level2Out << 1) | 
                        (Dis.Level3Out << 2);

    // 位移值采集(用于波形记录,调试用)
    if(Dis.Val > 50 && DisCNT < 10)
    {
        DisCNT++;
        DisWave[DisCNT] = Dis.Val;
    }

    // 延时计数器更新
    EndDelayCnt++;          // 结束信号延时
    EndDelayCnt1++;         // 机头电磁阀延时
    
    if(EndDelayCnt1 > 2100)
        EndDelayCnt1 = 2100;

    // 外部复位脉冲控制
    if(Dis.Reset)
    {
        DIS_RESET_ON;
        Dis.Reset = 0;
    }
    else
    {
        DIS_RESET_OFF;
    }

    // 清除中断标志
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
    EPwm3Regs.ETCLR.bit.INT = 1;
}

5.4 双核通信实现

位移比较结果(3个标志位)通过 IPC 共享内存 实时发送给 CPU2:

c

// 通信数组定义
volatile uint16_t usCPU01Buffer1[2];  // 快速状态传递

// 在中断中写入状态
usCPU01Buffer1[0] = Dis.Level1Out | 
                    (Dis.Level2Out << 1) | 
                    (Dis.Level3Out << 2);

// 状态位定义(CPU2 读取):
// Bit 0: Level1Out(位移超过阈值1)
// Bit 1: Level2Out(位移超过阈值2)
// Bit 2: Level3Out(位移超过阈值3)

5.5 主程序调用流程

c

void main(void)
{
    // 1. 系统初始化
    InitSysCtrl();
    InitGpio();
    InitPieCtrl();
    InitPieVectTable();
    
    // 2. 初始化 GPIO 引脚
    InitEQep3Gpio();
    
    // 3. 初始化 ePWM(用于中断定时)
    initEpwm();
    
    // 4. 配置中断向量
    PieVectTable.EPWM3_INT = &prdTick;
    IER |= M_INT3;
    PieCtrlRegs.PIEIER3.bit.INTx3 = 1;
    
    // 5. 初始化 eQEP 模块
    POSSPEED_Init();
    
    // 6. 设置位移阈值
    Dis.Level1Val = 1000;  // 1000μm
    Dis.Level2Val = 2000;  // 2000μm
    Dis.Level3Val = 3000;  // 3000μm
    
    // 7. 使能全局中断
    EINT;
    ERTM;
    
    // 8. 主循环
    while(1)
    {
        // 用户应用程序代码...
        // 读取 usCPU01Buffer1[0] 获取位移状态
    }
}

6. 寄存器参考速查表

寄存器偏移地址复位值位宽功能描述本驱动使用
QPOSCNT0x000x0000000032当前位置计数器✅ 每次中断读取
QPOSINIT0x020x0000000032初始化位置值✅ 默认0
QPOSMAX0x040x0000000032最大位置计数值✅ 设为0xFFFFFFFF
QPOSCMP0x060x0000000032位置比较值❌ 未使用
QPOSILAT0x080x0000000032索引位置锁存❌ 未使用
QPOSSLAT0x0A0x0000000032选通位置锁存❌ 未使用
QPOSLAT0x0C0x0000000032位置锁存❌ 未使用
QUTMR0x0E0x0000000032单元定时器❌ 未使用
QUPRD0x100x0000000032单元周期寄存器✅ 设为2000000
QWDTMR0x120x000016看门狗定时器❌ 未使用
QWDPRD0x130x000016看门狗周期寄存器❌ 未使用
QDECCTL0x140x000016解码控制寄存器✅ 配置正交模式
QEPCTL0x150x000016eQEP 控制寄存器✅ 配置复位/使能
QCAPCTL0x160x000016捕获控制寄存器✅ 配置但不使用
QPOSCTL0x170x000016位置比较控制寄存器❌ 未使用
QEINT0x180x000016中断使能寄存器❌ 未使用
QFLG0x190x000016中断标志寄存器✅ 读取状态
QCLR0x1A0x000016中断清除寄存器✅ 清除标志
QFRC0x1B0x000016中断强制寄存器❌ 未使用
QEPSTS0x1C0x000016状态寄存器✅ 清除标志
QCTMR0x1D0x000016捕获定时器❌ 未使用
QCPRD0x1E0x000016捕获周期寄存器❌ 未使用
QCTMRLAT0x1F0x000016捕获定时器锁存❌ 未使用
QCPRDLAT0x200x000016捕获周期锁存❌ 未使用

7. 注意事项与扩展建议

7.1 硬件注意事项

  1. 电源稳定性:AM26LS32ACDR 需稳定的 5V 供电,建议使用 LDO 或 DC-DC 稳压器

  2. 信号完整性:差分信号走线应尽量短且等长,避免阻抗不匹配

  3. 滤波设计:若传感器信号受干扰,可在 GPIO 配置中启用内部滤波,或在信号路径添加 RC 滤波器

  4. ESD 防护:在传感器接口处添加 TVS 二极管,保护器件免受静电冲击

  5. 工作温度:AC 版本工作温度 0~70°C,若在严苛环境需使用 AI 版本(-40~85°C)

7.2 软件注意事项

  1. GPIO 配置顺序:先配置 GPyGMUX,再配置 GPyMUX,避免引脚毛刺

  2. 中断优先级:确保 ePWM 中断不被其他中断长时间阻塞,以免丢失位移数据

  3. 双核同步:使用 IPC 时需注意共享资源保护,本驱动采用简单变量传递,无竞争风险

  4. 计数器溢出:QPOSMAX 设为 0xFFFFFFFF 时,计数器不会溢出,但需注意位移量的符号处理

  5. 寄存器访问:部分 eQEP 寄存器受 EALLOW 保护,修改前需解锁

7.3 扩展建议

功能扩展实现方法参考章节
速度测量使用 QCAPCTL 捕获单元和 QUPRD 单元定时器4.2.3
索引精确定位配置 QEPCTL.IEL 为索引事件标志锁存模式4.2.2
位置比较触发配置 QPOSCMP 和 QPOSCTL3.4
方向检测读取 QEPSTS.QDF 标志位4.5
看门狗保护配置 QWDPRD 和 QEPCTL.WDE4.2.2
eQEP 硬件中断配置 QEINT 和 PIE4.6

8. 总结

本驱动充分利用了 TMS320F28377D eQEP 模块的硬件解码能力,通过 AM26LS32ACDR 完成差分信号到单端 TTL 的转换,再经简单的初始化配置和定时中断读取,实现了对三丰位移传感器信号的精确采集和多级位置比较。

8.1 驱动特点

  • 硬件解码:利用 eQEP 模块自动解码正交信号,减轻 CPU 负担

  • 4 倍频计数:提高位置分辨率,实现微米级位移检测

  • 定时采集:2kHz 固定采样周期,与控制系统同步

  • 多级报警:三级位置阈值比较,可外接报警或控制信号

  • 双核通信:通过 IPC 实时传递位移状态给 CPU2

8.2 性能指标

  • 最大计数值:0xFFFFFFFF(约 42.9 亿)

  • 采样频率:2kHz(500µs 周期)

  • 位置分辨率:取决于传感器线数 × 4

  • 通信延迟:纳秒级(共享内存直接访问)

8.3 后续优化方向

  1. 增加速度测量功能,实现速度闭环控制

  2. 使用 eQEP 硬件中断,提高实时响应能力

  3. 配置看门狗定时器,监测信号丢失

  4. 增加位移缓冲队列,实现波形记录与回放

  5. 使用 DMA 自动传输位置数据,减少 CPU 开销


9. 附录:完整源代码

9.1 头文件:eqep_driver.h

c

#ifndef EQEP_DRIVER_H
#define EQEP_DRIVER_H

#include "F28x_Project.h"

//=============================================================================
// 数据结构定义
//=============================================================================

typedef struct {
    int32 Val;            // 当前计数值
    uint16 Level1Val;     // 阈值1(微米或计数单位)
    uint16 Level2Val;     // 阈值2
    uint16 Level3Val;     // 阈值3
    uint16 Level1Out;     // 比较结果位1
    uint16 Level2Out;     // 比较结果位2
    uint16 Level3Out;     // 比较结果位3
    uint16 Reset;         // 复位请求标志
} DisTypDef;

//=============================================================================
// 外部变量声明
//=============================================================================

extern volatile DisTypDef Dis;
extern volatile Uint16 EndDelayCnt;
extern volatile Uint16 EndDelayCnt1;
extern volatile int DisCNT;
extern volatile int DisWave[10];

//=============================================================================
// 函数声明
//=============================================================================

void POSSPEED_Init(void);
__interrupt void prdTick(void);

#endif // EQEP_DRIVER_H

9.2 源文件:eqep_driver.c

c

//=============================================================================
// 包含文件
//=============================================================================

#include "F28x_Project.h"
#include "eqep_driver.h"
#include "adc_epwm_cpu01.h"

//=============================================================================
// 全局变量定义
//=============================================================================

volatile DisTypDef Dis;
volatile Uint16 EndDelayCnt = 0;
volatile Uint16 EndDelayCnt1 = 0;
volatile int DisCNT = 0;
volatile int DisWave[10] = {0};

//=============================================================================
// POSSPEED_Init - 初始化 eQEP3 模块
//=============================================================================

void POSSPEED_Init(void)
{
    //-------------------------------------------------------------------------
    // 1. 解码控制寄存器 (QDECCTL)
    //-------------------------------------------------------------------------
    EQep3Regs.QDECCTL.bit.QSRC = 00;    // 正交计数模式
    EQep3Regs.QDECCTL.bit.XCR = 0;      // 2x 分辨率(双边沿计数)
    EQep3Regs.QDECCTL.bit.SWAP = 0;     // 不交换 A/B 输入
    EQep3Regs.QDECCTL.bit.QAP = 0;      // QEPA 不反相
    EQep3Regs.QDECCTL.bit.QBP = 0;      // QEPB 不反相

    //-------------------------------------------------------------------------
    // 2. eQEP 控制寄存器 (QEPCTL)
    //-------------------------------------------------------------------------
    EQep3Regs.QEPCTL.bit.FREE_SOFT = 2; // 仿真暂停时计数器继续运行
    EQep3Regs.QEPCTL.bit.PCRM = 00;     // 索引事件复位位置计数器
    EQep3Regs.QEPCTL.bit.IEI = 2;       // 索引上升沿初始化位置计数器
    EQep3Regs.QEPCTL.bit.SEI = 0;       // 选通事件初始化禁用
    EQep3Regs.QEPCTL.bit.SEL = 0;       // 选通事件锁存禁用
    EQep3Regs.QEPCTL.bit.IEL = 0;       // 索引事件锁存禁用
    EQep3Regs.QEPCTL.bit.UTE = 1;       // 使能单元定时器
    EQep3Regs.QEPCTL.bit.QCLM = 1;      // 单元超时时锁存位置
    EQep3Regs.QEPCTL.bit.WDE = 0;       // 禁用看门狗

    //-------------------------------------------------------------------------
    // 3. 位置计数器配置
    //-------------------------------------------------------------------------
    EQep3Regs.QPOSMAX = 0xFFFFFFFF;     // 32 位最大计数值
    EQep3Regs.QPOSINIT = 0;             // 初始化位置值

    //-------------------------------------------------------------------------
    // 4. 捕获单元配置(低速测速,本设计未使用)
    //-------------------------------------------------------------------------
    EQep3Regs.QCAPCTL.bit.UPPS = 5;     // 每 32 个 QCLK 产生单位位置事件
    EQep3Regs.QCAPCTL.bit.CCPS = 2;     // 捕获时钟 = SYSCLK/4
    EQep3Regs.QCAPCTL.bit.CEN = 1;      // 使能捕获单元

    //-------------------------------------------------------------------------
    // 5. 单元定时器配置
    //-------------------------------------------------------------------------
    EQep3Regs.QUPRD = 2000000;          // 200MHz 下产生 100Hz 超时

    //-------------------------------------------------------------------------
    // 6. 使能 eQEP 模块
    //-------------------------------------------------------------------------
    EQep3Regs.QEPCTL.bit.QPEN = 1;      // QEP 使能
}

//=============================================================================
// prdTick - ePWM3 周期中断服务程序(2kHz)
//=============================================================================

__interrupt void prdTick(void)
{
    // 清除状态标志(单位位置事件和溢出标志)
    EQep3Regs.QEPSTS.all = 0x88;

    // 读取当前计数值(32位)
    Dis.Val = EQep3Regs.QPOSCNT;

    // 三级位置比较
    if(Dis.Val > Dis.Level1Val)
        Dis.Level1Out = 1;
    else
        Dis.Level1Out = 0;

    if(Dis.Val > Dis.Level2Val)
        Dis.Level2Out = 1;
    else
        Dis.Level2Out = 0;

    if(Dis.Val > Dis.Level3Val)
        Dis.Level3Out = 1;
    else
        Dis.Level3Out = 0;

    // 打包状态位,用于 IPC 传递
    // Bit 0: Level1Out
    // Bit 1: Level2Out
    // Bit 2: Level3Out
    extern volatile uint16_t usCPU01Buffer1[];
    usCPU01Buffer1[0] = Dis.Level1Out | 
                        (Dis.Level2Out << 1) | 
                        (Dis.Level3Out << 2);

    // 位移波形采集(调试用)
    if(Dis.Val > 50 && DisCNT < 10)
    {
        DisCNT++;
        DisWave[DisCNT] = Dis.Val;
    }

    // 延时计数器
    EndDelayCnt++;
    EndDelayCnt1++;
    if(EndDelayCnt1 > 2100)
        EndDelayCnt1 = 2100;

    // 外部复位脉冲控制
    extern void DIS_RESET_ON(void);
    extern void DIS_RESET_OFF(void);
    
    if(Dis.Reset)
    {
        DIS_RESET_ON;
        Dis.Reset = 0;
    }
    else
    {
        DIS_RESET_OFF;
    }

    // 清除中断标志
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
    EPwm3Regs.ETCLR.bit.INT = 1;
}

//=============================================================================
// 文件结束
//=============================================================================

9.3 GPIO 初始化函数

c

//=============================================================================
// InitEQep3Gpio - 初始化 eQEP3 的 GPIO 引脚
//=============================================================================

void InitEQep3Gpio(void)
{
    EALLOW;

    // 配置引脚复用功能
    GpioCtrlRegs.GPAMUX1.bit.GPIO10 = 1;  // GPIO10 → EQEP3A
    GpioCtrlRegs.GPAMUX1.bit.GPIO11 = 1;  // GPIO11 → EQEP3B

    // 配置为同步输入模式(3 个采样周期滤波)
    GpioCtrlRegs.GPAQSEL1.bit.GPIO10 = 2;
    GpioCtrlRegs.GPAQSEL1.bit.GPIO11 = 2;

    // 使能内部上拉电阻
    GpioCtrlRegs.GPAPUD.bit.GPIO10 = 0;
    GpioCtrlRegs.GPAPUD.bit.GPIO11 = 0;

    EDIS;
}

更多推荐