基于 TMS320F28377D eQEP 的三丰位移传感器采集驱动设计
文档版本:V1.0
编写日期:2026-07-23
适用平台:TMS320F28377D + AM26LS32ACDR + 三丰位移传感器
目录
-
系统概述
-
硬件设计
-
2.1 系统硬件架构
-
2.2 AM26LS32ACDR 差分接收器
-
2.3 硬件连接详表
-
2.4 PCB 布局建议
-
-
eQEP 模块概述
-
3.1 模块简介
-
3.2 主要功能单元
-
3.3 输入信号说明
-
3.4 eQEP 基地址与寄存器映射
-
-
eQEP 编程实现方法
-
4.1 GPIO 引脚配置
-
4.2 eQEP 模块初始化
-
4.3 位置计数器工作模式
-
4.4 4倍频计数原理
-
4.5 位置数据读取
-
4.6 中断配置
-
4.7 DriverLib 函数速查
-
-
本驱动软件实现
-
5.1 数据结构定义
-
5.2 初始化函数实现
-
5.3 定时中断读取实现
-
5.4 双核通信实现
-
5.5 主程序调用流程
-
-
寄存器参考速查表
-
注意事项与扩展建议
-
总结
-
附录:完整源代码
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 封装)
| 引脚 | 名称 | 类型 | 功能描述 |
|---|---|---|---|
| 1 | 1A | 输入 | 通道1 差分输入(同相) |
| 2 | 1B | 输入 | 通道1 差分输入(反相) |
| 3 | 1Y | 输出 | 通道1 单端逻辑输出 |
| 4 | G | 输入 | 高电平有效使能 |
| 5 | G | 输入 | 低电平有效使能 |
| 6 | 2A | 输入 | 通道2 差分输入(同相) |
| 7 | 2B | 输入 | 通道2 差分输入(反相) |
| 8 | GND | 电源 | 地 |
| 9 | 3B | 输入 | 通道3 差分输入(反相) |
| 10 | 3A | 输入 | 通道3 差分输入(同相) |
| 11 | 3Y | 输出 | 通道3 单端逻辑输出 |
| 12 | 4B | 输入 | 通道4 差分输入(反相) |
| 13 | 4Y | 输出 | 通道4 单端逻辑输出 |
| 14 | 4A | 输入 | 通道4 差分输入(同相) |
| 15 | G | 输入 | 低电平有效使能(内部连接) |
| 16 | VCC | 电源 | +5V 电源 |
2.2.3 核心功能
-
差分信号接收与转换:芯片内部每个接收器将差分输入对(A+ / A-)的电压差与内置阈值(典型值 ±200mV)进行比较,转换为单端 TTL 电平输出。差分传输方式使得信号在长距离传输时仍能保持良好的信号完整性。
-
使能控制:四个接收器共用使能功能,提供高电平有效(G) 和 低电平有效(G) 两种控制输入,可灵活配置接收器的启用/禁用状态。
-
失效防护:当输入端处于开路状态时,失效防护设计可确保输出始终为高电平,避免不确定状态。
-
输入迟滞:50mV 的输入迟滞有效提升了抗干扰能力,防止信号在阈值附近抖动时输出不稳定。
2.2.4 功能真值表(每个接收器)
| 差分输入(A - B) | G | G | 输出 Y |
|---|---|---|---|
| ≥ VIT+(≥ 200mV) | H | X | H |
| ≤ VIT-(≤ -200mV) | H | X | L |
| 不确定区间 | H | X | 不确定 |
| X | L | X | Z(高阻) |
| X | X | H | Z(高阻) |
| 开路 | H | X | H |
注: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 配置
| 信号 | 引脚 | 复用功能 | 配置说明 |
|---|---|---|---|
| EQEP3A | GPIO10 | eQEP3 功能 | 同步输入模式 |
| EQEP3B | GPIO11 | eQEP3 功能 | 同步输入模式 |
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 模块 | 起始地址 | 结束地址 |
|---|---|---|
| EQep1Regs | 0x0000_5100 | 0x0000_513F |
| EQep2Regs | 0x0000_5140 | 0x0000_517F |
| EQep3Regs | 0x0000_5180 | 0x0000_51BF |
关键寄存器列表:
| 偏移地址 | 寄存器 | 功能 |
|---|---|---|
| 0x00 | QPOSCNT | 当前位置计数器(32位) |
| 0x02 | QPOSINIT | 初始化位置值 |
| 0x04 | QPOSMAX | 最大位置计数值 |
| 0x06 | QPOSCMP | 位置比较值 |
| 0x08 | QPOSILAT | 索引位置锁存 |
| 0x0A | QPOSSLAT | 选通位置锁存 |
| 0x0C | QPOSLAT | 位置锁存 |
| 0x0E | QUTMR | 单元定时器 |
| 0x10 | QUPRD | 单元周期寄存器 |
| 0x12 | QWDTMR | 看门狗定时器 |
| 0x13 | QWDPRD | 看门狗周期寄存器 |
| 0x14 | QDECCTL | 解码控制寄存器 |
| 0x15 | QEPCTL | eQEP 控制寄存器 |
| 0x16 | QCAPCTL | 捕获控制寄存器 |
| 0x17 | QPOSCTL | 位置比较控制寄存器 |
| 0x18 | QEINT | 中断使能寄存器 |
| 0x19 | QFLG | 中断标志寄存器 |
| 0x1A | QCLR | 中断清除寄存器 |
| 0x1B | QFRC | 中断强制寄存器 |
| 0x1C | QEPSTS | 状态寄存器 |
| 0x1D | QCTMR | 捕获定时器 |
| 0x1E | QCPRD | 捕获周期寄存器 |
| 0x1F | QCTMRLAT | 捕获定时器锁存 |
| 0x20 | QCPRDLAT | 捕获周期锁存 |
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/1 | 0=双边沿计数(2x),1=单边沿计数 |
| SWAP[10] | A/B 输入交换 | 0/1 | 交换 QEPA/QEPB 输入 |
| IGATE[9] | 索引门控 | 0/1 | 用选通信号门控索引脉冲 |
| QAP[8] | QEPA 输入极性 | 0/1 | 0=不反相,1=反相 |
| QBP[7] | QEPB 输入极性 | 0/1 | 0=不反相,1=反相 |
| QIP[6] | QEPI 输入极性 | 0/1 | 0=不反相,1=反相 |
| QSP[5] | QEPS 输入极性 | 0/1 | 0=不反相,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/1 | 0=复位/禁用,1=使能 |
| QCLM[2] | 锁存模式 | 0/1 | 0=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 同时跳变(无效状态转换) |
| QDC | QEP 方向改变 | 方向变化 |
| 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. 寄存器参考速查表
| 寄存器 | 偏移地址 | 复位值 | 位宽 | 功能描述 | 本驱动使用 |
|---|---|---|---|---|---|
| QPOSCNT | 0x00 | 0x00000000 | 32 | 当前位置计数器 | ✅ 每次中断读取 |
| QPOSINIT | 0x02 | 0x00000000 | 32 | 初始化位置值 | ✅ 默认0 |
| QPOSMAX | 0x04 | 0x00000000 | 32 | 最大位置计数值 | ✅ 设为0xFFFFFFFF |
| QPOSCMP | 0x06 | 0x00000000 | 32 | 位置比较值 | ❌ 未使用 |
| QPOSILAT | 0x08 | 0x00000000 | 32 | 索引位置锁存 | ❌ 未使用 |
| QPOSSLAT | 0x0A | 0x00000000 | 32 | 选通位置锁存 | ❌ 未使用 |
| QPOSLAT | 0x0C | 0x00000000 | 32 | 位置锁存 | ❌ 未使用 |
| QUTMR | 0x0E | 0x00000000 | 32 | 单元定时器 | ❌ 未使用 |
| QUPRD | 0x10 | 0x00000000 | 32 | 单元周期寄存器 | ✅ 设为2000000 |
| QWDTMR | 0x12 | 0x0000 | 16 | 看门狗定时器 | ❌ 未使用 |
| QWDPRD | 0x13 | 0x0000 | 16 | 看门狗周期寄存器 | ❌ 未使用 |
| QDECCTL | 0x14 | 0x0000 | 16 | 解码控制寄存器 | ✅ 配置正交模式 |
| QEPCTL | 0x15 | 0x0000 | 16 | eQEP 控制寄存器 | ✅ 配置复位/使能 |
| QCAPCTL | 0x16 | 0x0000 | 16 | 捕获控制寄存器 | ✅ 配置但不使用 |
| QPOSCTL | 0x17 | 0x0000 | 16 | 位置比较控制寄存器 | ❌ 未使用 |
| QEINT | 0x18 | 0x0000 | 16 | 中断使能寄存器 | ❌ 未使用 |
| QFLG | 0x19 | 0x0000 | 16 | 中断标志寄存器 | ✅ 读取状态 |
| QCLR | 0x1A | 0x0000 | 16 | 中断清除寄存器 | ✅ 清除标志 |
| QFRC | 0x1B | 0x0000 | 16 | 中断强制寄存器 | ❌ 未使用 |
| QEPSTS | 0x1C | 0x0000 | 16 | 状态寄存器 | ✅ 清除标志 |
| QCTMR | 0x1D | 0x0000 | 16 | 捕获定时器 | ❌ 未使用 |
| QCPRD | 0x1E | 0x0000 | 16 | 捕获周期寄存器 | ❌ 未使用 |
| QCTMRLAT | 0x1F | 0x0000 | 16 | 捕获定时器锁存 | ❌ 未使用 |
| QCPRDLAT | 0x20 | 0x0000 | 16 | 捕获周期锁存 | ❌ 未使用 |
7. 注意事项与扩展建议
7.1 硬件注意事项
-
电源稳定性:AM26LS32ACDR 需稳定的 5V 供电,建议使用 LDO 或 DC-DC 稳压器
-
信号完整性:差分信号走线应尽量短且等长,避免阻抗不匹配
-
滤波设计:若传感器信号受干扰,可在 GPIO 配置中启用内部滤波,或在信号路径添加 RC 滤波器
-
ESD 防护:在传感器接口处添加 TVS 二极管,保护器件免受静电冲击
-
工作温度:AC 版本工作温度 0~70°C,若在严苛环境需使用 AI 版本(-40~85°C)
7.2 软件注意事项
-
GPIO 配置顺序:先配置
GPyGMUX,再配置GPyMUX,避免引脚毛刺 -
中断优先级:确保 ePWM 中断不被其他中断长时间阻塞,以免丢失位移数据
-
双核同步:使用 IPC 时需注意共享资源保护,本驱动采用简单变量传递,无竞争风险
-
计数器溢出:QPOSMAX 设为 0xFFFFFFFF 时,计数器不会溢出,但需注意位移量的符号处理
-
寄存器访问:部分 eQEP 寄存器受 EALLOW 保护,修改前需解锁
7.3 扩展建议
| 功能扩展 | 实现方法 | 参考章节 |
|---|---|---|
| 速度测量 | 使用 QCAPCTL 捕获单元和 QUPRD 单元定时器 | 4.2.3 |
| 索引精确定位 | 配置 QEPCTL.IEL 为索引事件标志锁存模式 | 4.2.2 |
| 位置比较触发 | 配置 QPOSCMP 和 QPOSCTL | 3.4 |
| 方向检测 | 读取 QEPSTS.QDF 标志位 | 4.5 |
| 看门狗保护 | 配置 QWDPRD 和 QEPCTL.WDE | 4.2.2 |
| eQEP 硬件中断 | 配置 QEINT 和 PIE | 4.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 后续优化方向
-
增加速度测量功能,实现速度闭环控制
-
使用 eQEP 硬件中断,提高实时响应能力
-
配置看门狗定时器,监测信号丢失
-
增加位移缓冲队列,实现波形记录与回放
-
使用 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;
}
更多推荐



所有评论(0)