1. 项目概述:为什么我们需要深入理解eQEP?
在电机控制、机器人关节定位或者任何需要精确知道“转了多少圈、转得多快”的场合,正交编码器几乎是工程师的首选传感器。它输出的两路相位差90度的方波信号(我们常说的A相和B相),就像一套精密的“运动语言”,硬件解码这套语言,我们就能实时获取位置和方向。而德州仪器(TI)C2000系列微控制器里的增强型正交编码器脉冲(eQEP)模块,就是一位精通这门语言的“同声传译官”。
它把繁琐的边沿检测、方向判断、计数累加这些活儿全包了,用硬件实现,速度快、不占CPU。但说实话,刚开始看TMS320F280015x的技术手册里那几十个寄存器时,我也头大。什么位置计数器初始化、边沿捕获、位置比较、看门狗,还有那个QMA模式适配器,每个功能好像都挺重要,但连起来看又有点懵。
这篇文章,我就结合自己这几年在伺服驱动器上折腾eQEP的经验,帮你把这些零散的知识点串起来。我们不只讲寄存器每个位是干嘛的——那个手册上都有。我们重点聊清楚:为什么TI要设计这些功能?在实际项目中怎么用它们?以及调试的时候最容易在哪儿栽跟头。目标是让你看完后,不仅能配置出一个能跑的eQEP,更能理解其设计哲学,在遇到复杂应用场景时,知道该动哪个“开关”。
2. eQEP模块整体架构与核心设计思路
拿到一个外设模块,我习惯先看它的整体框图和数据流。eQEP模块的核心任务很明确:精准、实时地翻译编码器的“运动语言”,并将其转化为微控制器能直接使用的数字信息(位置、速度)。为了实现这个目标,它的设计是分层、模块化的。
2.1 信号链路的起点:从引脚到内部信号
编码器的A、B、I(索引)、S(选通)信号首先进入引脚复用和输入极性控制环节。这里对应QDECCTL寄存器的QAP、QBP、QIP、QSP位。很多人会忽略这个配置,但它在实际接线中至关重要。比如你的编码器输出是低电平有效,或者为了抑制长线干扰需要将信号反相,就是在这里设置。一个关键经验:在硬件设计阶段,就要明确编码器信号的电气标准和有效电平,并在软件初始化时第一时间配置好极性,避免后续发现位置计数方向完全反了再回头查。
接下来是正交解码器(Quadrature Decoder),这是eQEP的心脏。QDECCTL[QSRC]位决定了它的工作模式:
- 正交计数模式(00):这是最常用的模式。模块内部会根据A、B相的上升沿和下降沿生成4倍频的时钟
QCLK,并根据A、B相的相位关系生成方向信号QDIR。对于一个1000线(每转1000个脉冲)的编码器,在此模式下每转能产生4000个计数,分辨率大大提高。 - 方向计数模式(01):此时,
QCLK直接来自A相(xCLK),QDIR直接来自B相(xDIR)。这种模式适用于只有脉冲和方向信号的增量式编码器或某些频率输出传感器。 - 上/下计数模式(10/11):这两种模式将eQEP变成一个简单的频率计数器,
QCLK来自A相,方向固定为上或下。常用于测量单个脉冲信号的频率。
设计思路解析:TI通过QSRC配置提供了极大的灵活性。正交模式用于高精度位置反馈,方向模式兼容更广泛的信号类型,而上/下计数模式则让eQEP能兼职做通用频率测量。这种设计避免了为简单应用浪费一个独立的定时器外设。
2.2 核心数据通路:位置、时间与同步
解码出QCLK和QDIR后,核心数据流兵分三路,这也是eQEP功能的三个支柱:
位置积分路径:
QCLK和QDIR驱动一个32位的位置计数器(QPOSCNT)。这是最核心的寄存器,它的值直接代表了从某个参考点开始的累计位移。计数器支持循环计数(达到QPOSMAX后归零或从0翻转)等多种复位模式,由QEPCTL[PCRM]控制。时间测量路径:为了计算速度,我们需要知道位置变化所花费的时间。这就是边沿捕获单元的职责。它包含一个以系统时钟分频(
QCAPCTL[CCPS])运行的16位定时器QCTMR和一个锁存器QCPRD。它可以配置为在固定的“单位位置事件”(由QCAPCTL[UPPS]定义,例如每64个QCLK)发生时,锁存QCTMR的值到QCPRD,然后复位QCTMR。这样,QCPRD里的值就是走过一段固定位移ΔX所花费的时间ΔT。速度v = ΔX / ΔT。这里有个大坑:UPPS(单位位置事件预分频)不能在捕获单元使能时动态修改!必须在CEN=0时配置好,否则行为未定义。同步与触发路径:这是eQEP高级功能的体现。位置比较单元允许你设置一个目标位置值(
QPOSCMP),当QPOSCNT与之匹配时,可以产生一个同步脉冲输出(PCSOUT),用来触发ADC转换或其他外设,实现非常精准的采样同步。此外,**索引(Index)和选通(Strobe)**事件可以用于位置计数器初始化或锁存瞬时位置,实现机械零点的标定或特定时刻的位置抓取。
模块化设计的价值:这三条路径相对独立,又可以通过QEPCTL等控制寄存器进行联动。例如,你可以让位置比较事件触发ADC,同时让单位超时事件(来自独立的单位定时器QUTMR)定期锁存位置和捕获周期值用于速度计算。这种设计让eQEP能同时服务于多个控制环路的需求。
3. 核心功能单元深度解析与配置要点
理解了整体框架,我们深入看看几个最容易出问题也最强大的子模块。
3.1 位置计数器初始化:建立可靠的参考原点
位置计数器QPOSCNT的初始化是定位控制的基石。eQEP提供了三种方式,通过QEPCTL的IEI、SEI和SWI位域控制:
- 索引事件初始化(IEI):这是最常用的机械原点回归方式。当编码器的Z信号(索引信号)边沿到来时,将
QPOSINIT寄存器的值加载到QPOSCNT。IEI=10为上升沿,IEI=11为下降沿。关键点:QPOSINIT通常设为0,这样每次经过索引点,位置都归零,实现绝对位置同步。但你也可以设为其他值,实现偏置。 - 选通事件初始化(SEI):与索引类似,但由外部数字信号(如限位开关)触发。
SEI=10在选通上升沿初始化;SEI=11则根据方向选择边沿(正转上升沿,反转下降沿),这在某些双向触发场景下很有用。 - 软件初始化(SWI):写1到
SWI位,立即将QPOSCNT设为QPOSINIT的值。重要警告:SWI位不会自动清零!如果你在SWI仍为1时再次写1,计数器会被再次初始化。这可能导致位置跳变。最佳实践是:SWI=1-> (等待至少一个时钟周期) ->SWI=0。
配置示例与避坑: 假设我们需要在索引信号的上升沿将位置计数器清零。
// 1. 首先,确保位置计数器使能位 QPEN 已使能(通常在整体初始化时设置) // 2. 配置索引信号初始化 EQep1Regs.QEPCTL.bit.IEI = 0x2; // 10b: 上升沿初始化 EQep1Regs.QPOSINIT = 0; // 初始化值为0 // 3. 如果需要,使能索引事件中断,以便在回零后进行后续操作 EQep1Regs.QEINT.bit.IEL = 1;避坑指南:在电机高速运行时,索引信号可能很窄。确保你的GPIO输入滤波和eQEP的采样时钟设置合理,避免错过索引脉冲。同时,初始化事件会触发中断(如果使能),在中断服务程序里要记得清除QFLG.IEL标志。
3.2 边沿捕获单元:低速度测量的利器
在高速度时,我们可以用单位定时器定期(如每10ms)读取位置计数器的差值来计算速度。但在极低转速下,两次采样间位置可能根本没变化,这种方法就失效了。此时,边沿捕获单元通过测量固定数量编码器脉冲之间的时间ΔT来计算速度,在低速下精度更高。
其核心公式是:速度 v = 单位位移 X / 捕获周期 ΔT。
X由编码器线数和QCAPCTL[UPPS]共同决定。例如,1000线编码器,4倍频后每转为4000个QCLK。若设置UPPS=4(即每16个QCLK为一个单位事件),则X = 16。ΔT就是捕获周期寄存器QCPRDLAT中的值,单位是捕获时钟CAPCLK的周期。CAPCLK = SYSCLKOUT / (2^CCPS)。
配置步骤与计算: 假设系统时钟SYSCLKOUT = 100MHz,编码器1000线,要求最低能测量到1 RPM(转/分钟)的速度。
- 计算最低速对应的频率:1 RPM = 1000 线/分钟 = 1000/60 ≈ 16.67 线/秒。4倍频后,
QCLK频率 ≈ 66.67 Hz。 - 设置
UPPS。为了让单位事件频率不至于太低,假设我们选择每128个QCLK一个事件(UPPS=6)。则单位事件频率 = 66.67 / 128 ≈ 0.52 Hz。单位位移X = 128(以QCLK个数计)。 - 设置
CCPS。ΔT的最大值不能超过16位定时器溢出值65535。ΔT = 1 / 单位事件频率 = 1 / 0.52 ≈ 1.92秒。需要的计时器计数 =ΔT * CAPCLK频率。为确保不溢出,CAPCLK频率要足够低。若选CCPS=7(128分频),CAPCLK = 100MHz / 128 = 781.25 kHz,周期为1.28us。则ΔT计数 = 1.92s / 1.28us ≈ 150万,远超65535,会溢出。因此需要更大的分频,或者接受更高的最低测量速度。这里就是权衡:CCPS越大,能测的速度越低,但速度更新的速率也越慢(因为要等更长的ΔT)。 - 最终,我们可能选择
CCPS=6(64分频),CAPCLK=1.5625MHz,周期0.64us。此时能测量的最长ΔT为655350.64us ≈ 42ms。对应的最低单位事件频率为~23.8Hz。结合UPPS=6,可反推出最低QCLK频率为23.8128≈3047Hz,对应电机转速约为(3047/4000)*60 ≈ 45.7 RPM。低于此速度,捕获单元会因定时器溢出而报错(QEPSTS.CDEF或COEF置位)。
代码配置:
// 使能捕获单元前,先配置预分频 EQep1Regs.QCAPCTL.bit.UPPS = 6; // 每128个QCLK为一个单位事件 EQep1Regs.QCAPCTL.bit.CCPS = 6; // CAPCLK = SYSCLKOUT / 64 EQep1Regs.QCAPCTL.bit.CEN = 1; // 使能捕获单元 // 在速度计算函数中(例如在单位超时中断中) if(EQep1Regs.QEPSTS.bit.UPEVNT) { // 检查是否有新的单位事件 unit_time = EQep1Regs.QCPRDLAT; // 读取锁存的周期值 EQep1Regs.QEPSTS.bit.UPEVNT = 1; // 写1清除标志 if (unit_time != 0xFFFF) { // 确保没有发生错误(溢出或方向改变) speed_low = (UNIT_POSITION * CAPCLK_FREQ) / unit_time; // 计算低速速度 } }3.3 位置比较单元与同步输出
位置比较单元是产生精准同步事件的神器。你设置一个目标位置QPOSCMP,当QPOSCNT等于它时,硬件会自动产生一个同步事件PCEVNT,并可以输出一个宽度可编程的脉冲PCSOUT。
关键配置:
QPOSCTL[PCSHDW]:阴影寄存器使能。使能后,你可以安全地在任何时间更新QPOSCMP,新值会先写入阴影寄存器,在下次加载条件满足时才生效,避免在比较过程中修改寄存器导致意外。QPOSCTL[PCLOAD]:阴影寄存器加载条件。0表示在QPOSCNT回零时加载;1表示在比较匹配时加载。后者常用于生成等间距的同步脉冲序列。QPOSCTL[PCSPW]:设置同步输出脉冲的宽度,单位是4个SYSCLKOUT周期。
应用场景: 在磁场定向控制(FOC)中,我们希望在特定的转子位置(例如,每个电角度周期)采样相电流。假设电机极对数为4,那么电角度每转4圈。我们可以将QPOSCMP设置为机械位置计数器的特定值(如每1/4转),并启用阴影加载模式(PCLOAD=1)。这样,每次匹配后,QPOSCMP会自动重载为QPOSCMP + 周期值,产生连续的同步脉冲去触发ADC,实现与转子位置严格同步的电流采样。
配置示例:
// 假设每转4000个计数,我们需要每1/4转(1000个计数)触发一次同步 EQep1Regs.QPOSCMP = 1000; // 初始比较值 EQep1Regs.QPOSCTL.bit.PCSHDW = 1; // 使能阴影模式 EQep1Regs.QPOSCTL.bit.PCLOAD = 1; // 在比较匹配时重载阴影值 EQep1Regs.QPOSCTL.bit.PCSPW = 10; // 设置脉冲宽度,例如 10 * 4 * SYSCLK周期 EQep1Regs.QPOSCTL.bit.PCE = 1; // 使能位置比较单元 // 如果需要,使能比较匹配中断 EQep1Regs.QEINT.bit.PCM = 1;3.4 看门狗与单位定时器:系统的安全网与节拍器
- 看门狗定时器(QWDTMR):这是一个简单的安全功能。它由一个以
SYSCLKOUT/64时钟驱动的计数器构成。每次有QCLK(编码器脉冲)事件,它就复位。如果电机卡住,没有QCLK事件,该计数器会一直累加到与QWDPRD匹配,从而触发超时中断(QFLG.WTO)。你可以在这个中断里执行故障安全操作,如关闭PWM输出。注意:看门狗时钟较慢,适用于检测完全堵转,对于轻微的速度波动不敏感。 - 单位定时器(QUTMR):这是一个32位定时器,时钟源为
SYSCLKOUT。它独立于编码器脉冲,提供一个固定的时间基准。当QUTMR计数到QUPRD设定的值时,产生单位超时事件(UTO),并自动复位。这个事件非常有用:- 定期速度计算:在
UTO中断中,读取QPOSLAT(在QCLM=1时,UTO事件会自动锁存位置)与上一次的位置差,除以单位时间T(= QUPRD / SYSCLKOUT),即可得到中高速下的速度。这是最常用的速度计算方式。 - 统一数据锁存:设置
QEPCTL[QCLM]=1,可以在UTO事件发生时,同时锁存位置计数器QPOSCNT、捕获定时器QCTMR和捕获周期QCPRD到它们对应的锁存寄存器。这保证了位置、时间数据在同一时刻被捕获,避免了因读取顺序带来的误差,对于高精度控制至关重要。
- 定期速度计算:在
4. 从零开始:eQEP模块的完整配置与调试流程
理论讲完了,我们来看一个针对TMS320F280015x的典型配置流程,用于连接一个1000线的增量式正交编码器,实现位置和速度反馈。
4.1 初始化步骤详解
步骤1:GPIO引脚复用配置这是第一步,也是最容易忘记的一步。你需要将对应的GPIO引脚配置为eQEP功能。
// 假设使用eQEP1,对应GPIO6/7/8/9 GPIO_setPinConfig(GPIO_6_EQEP1A); // A相 GPIO_setPinConfig(GPIO_7_EQEP1B); // B相 GPIO_setPinConfig(GPIO_8_EQEP1I); // 索引I GPIO_setPinConfig(GPIO_9_EQEP1S); // 选通S(如果使用) GPIO_setQualification(GPIO_6, GPIO_QUAL_ASYNC); // 根据信号质量设置输入滤波,高速时常用异步 GPIO_setQualification(GPIO_7, GPIO_QUAL_ASYNC); // ... 其他引脚步骤2:eQEP模块基本参数配置
// 使用DriverLib库函数或直接操作寄存器 // 1. 配置解码器控制寄存器 QDECCTL EQep1Regs.QDECCTL.bit.QSRC = 0; // 00: 正交计数模式 EQep1Regs.QDECCTL.bit.XCR = 1; // 1倍频还是2倍频?通常选1(仅上升沿)以降低计数频率,但会损失分辨率。对于1000线编码器,4倍频(XCR=0)更常见。 EQep1Regs.QDECCTL.bit.SWAP = 0; // 不交换A/B相 EQep1Regs.QDECCTL.bit.QAP = 0; // A相极性,根据实际接线调整 EQep1Regs.QDECCTL.bit.QBP = 0; // B相极性 EQep1Regs.QDECCTL.bit.QIP = 0; // 索引极性 EQep1Regs.QDECCTL.bit.QSP = 0; // 选通极性 // 2. 配置位置计数器模式 QEPCTL EQep1Regs.QEPCTL.bit.FREE_SOFT = 2; // 仿真挂起时,计数器继续运行 EQep1Regs.QEPCTL.bit.PCRM = 0; // 位置计数器复位模式:0=索引事件复位,2=首次索引事件复位,根据需求选 EQep1Regs.QEPCTL.bit.UTE = 1; // 使能单位定时器 EQep1Regs.QEPCTL.bit.QCLM = 1; // 在单位超时时锁存位置、捕获时间等(推荐) EQep1Regs.QEPCTL.bit.QPEN = 1; // 最后,使能位置计数器! // 3. 配置单位定时器周期 QUPRD // 假设SYSCLKOUT=100MHz,我们希望每10ms产生一次单位超时中断用于速度计算。 // QUPRD = 时间 * 频率 = 0.01s * 100e6 Hz = 1,000,000 EQep1Regs.QUPRD = 1000000; // 4. 配置捕获单元 QCAPCTL (用于低速测量) EQep1Regs.QCAPCTL.bit.UPPS = 5; // 例如,每32个QCLK为一个单位事件 (2^5) EQep1Regs.QCAPCTL.bit.CCPS = 3; // CAPCLK = SYSCLKOUT/8 EQep1Regs.QCAPCTL.bit.CEN = 1; // 使能捕获单元 // 5. 配置位置比较单元 QPOSCTL (如果需要同步输出) // EQep1Regs.QPOSCTL.bit.PCE = 1; // 暂时不使能,后续根据需要开启 // 6. 配置看门狗 QWDPRD // 假设我们允许电机最大停转检测时间为100ms // 看门狗时钟 = SYSCLKOUT/64 = 1.5625MHz // QWDPRD = 0.1s * 1.5625e6 = 156250 EQep1Regs.QWDPRD = 156250; EQep1Regs.QEPCTL.bit.WDE = 1; // 使能看门狗 // 7. 配置中断 // 使能单位超时中断和看门狗超时中断 EQep1Regs.QEINT.bit.UTO = 1; EQep1Regs.QEINT.bit.WTO = 1; // 在PIE控制器中使能对应的eQEP中断步骤3:编写中断服务程序(ISR)
// eQEP1的单位超时中断服务程序 __interrupt void eQEP1_ISR(void) { // 1. 检查中断源 if (EQep1Regs.QFLG.bit.UTO == 1) { // 2. 读取锁存的位置值(因为QCLM=1,UTO事件已自动锁存) int32_t current_pos = EQep1Regs.QPOSLAT; // 3. 计算速度(高速) // 假设上次位置为 last_pos,单位时间 T = QUPRD / SYSCLKOUT int32_t delta_pos = current_pos - last_pos; // 处理位置计数器溢出/下溢。对于32位计数器,简单的减法在溢出时依然正确,因为C语言处理无符号整数溢出。 // 但更稳健的做法是使用有符号32位,并考虑周期值(如QPOSMAX)。 float speed_rps = (float)delta_pos / (ENCODER_COUNTS_PER_REV) / UNIT_TIMER_PERIOD_S; float speed_rpm = speed_rps * 60.0; // 4. 检查并计算低速(使用捕获单元) if (EQep1Regs.QEPSTS.bit.UPEVNT) { uint16_t cap_period = EQep1Regs.QCPRDLAT; if ((cap_period != 0xFFFF) && (cap_period != 0)) { // 没有发生错误 float speed_low = (UNIT_POSITION * CAPCLK_FREQ) / (float)cap_period; // 单位:QCLK/s // 转换为RPM... } EQep1Regs.QEPSTS.bit.UPEVNT = 1; // 清除单位事件标志 } // 5. 更新上一次位置 last_pos = current_pos; // 6. 清除中断标志(重要!) EQep1Regs.QCLR.bit.UTO = 1; // 写1清除UTO标志 EQep1Regs.QCLR.bit.INT = 1; // 清除全局中断标志 } // 处理看门狗超时中断 if (EQep1Regs.QFLG.bit.WTO == 1) { // 电机可能堵转,执行保护操作 EPwm1Regs.TZFLG.bit.OST = 1; // 触发PWM强制关断 EQep1Regs.QCLR.bit.WTO = 1; EQep1Regs.QCLR.bit.INT = 1; } // 必须清除PIE中断应答位 PieCtrlRegs.PIEACK.all = PIEACK_GROUP4; // eQEP1通常在PIE组4 }4.2 调试技巧与常见问题排查
即使配置看起来正确,第一次上电eQEP也可能不工作。以下是我总结的排查清单:
没有计数(QPOSCNT不动)
- 检查GPIO配置:这是最常见的原因。确认引脚已正确复用为eQEP功能,而不是普通的GPIO输入。
- 检查信号质量:用示波器查看A、B相波形。确保是标准的正交方波,没有过冲或振铃。电压电平是否符合MCU要求(通常是3.3V)。
- 检查极性(QAP, QBP):如果方向相反,计数可能正常。如果完全没计数,尝试将
QAP或QBP取反(设为1)。有时编码器输出是推挽,有时是开集,需要上拉,硬件电路要匹配。 - 检查QPEN位:确保
QEPCTL[QPEN]已设置为1。我见过不止一个工程师查了半天,最后发现忘了使能计数器。 - 检查仿真器影响:在CCS调试时,如果代码在断点处停止,
QPOSCNT自然不更新。确保程序全速运行。
计数方向错误
- 交换电机的A、B相接线,或者在软件中交换
QDECCTL[SWAP]的设置。 - 检查
QEPSTS[QDF]位,它实时指示当前方向。
- 交换电机的A、B相接线,或者在软件中交换
索引信号不触发初始化或锁存
- 确认
QEPCTL[IEL]或IEI配置正确(边沿选择)。 - 检查索引信号是否确实连接到MCU引脚,并用示波器确认其边沿与编码器旋转对应。
- 检查
QEPSRCSEL[QEPISEL]寄存器,确保索引信号源选择正确(默认是引脚)。
- 确认
速度计算值跳动大或不准确
- 高速时:确保单位定时器中断周期
QUPRD设置合理。周期太短,位置差值delta_pos太小,量化误差大。周期太长,速度更新慢,动态响应差。通常选择控制周期(如电流环周期)的整数倍。 - 低速时:检查捕获单元配置。
UPPS设置是否过大,导致单位事件间隔时间太长?CCPS设置是否过小,导致CAPCLK太快,QCTMR在低速时容易溢出(QEPSTS.COEF置位)?务必在中断中检查QCPRDLAT是否为0xFFFF,并处理错误。 - 通用问题:
delta_pos的计算必须考虑位置计数器溢出。对于32位有符号位置值,直接相减在跨越0x7FFFFFFF到0x80000000时会产生巨大正跳变。需要使用模运算或判断溢出的方法进行处理。// 一种处理32位有符号位置溢出的方法 #define POS_MODULUS 0x100000000L // 2^32 int32_t get_delta_position(int32_t new_pos, int32_t old_pos) { int32_t delta = new_pos - old_pos; // 如果差值过大(超过一半模值),认为是溢出/下溢 if(delta > 0x7FFFFFFF) { delta -= POS_MODULUS; } else if(delta < -0x7FFFFFFF) { delta += POS_MODULUS; } return delta; }
- 高速时:确保单位定时器中断周期
看门狗频繁超时
- 电机是否真的停了?检查负载。
QWDPRD设置是否过小?计算一下对应的最大允许脉冲间隔时间。- 检查
QCLK是否正常产生。如果eQEP根本没收到底层脉冲,看门狗必然超时。
使用QMA模块的特殊情况
- 如果你的编码器信号默认状态为高电平(空闲为高),需要使用
QMA Mode-1(QMACTRL[MODE]=1)。 - 如果默认状态为低电平,使用
QMA Mode-2(=2)。 - 启用QMA后,务必确保eQEP本身配置为方向计数模式(
QDECCTL[QSRC]=01),因为QMA模块会输出处理后的时钟和方向信号给eQEP核心。
- 如果你的编码器信号默认状态为高电平(空闲为高),需要使用
5. 高级应用与性能优化
当基础功能跑通后,可以考虑以下优化来提升系统性能:
利用DMA减轻CPU负担:在高速应用中,频繁的中断(如单位超时中断)会消耗大量CPU资源。可以配置eQEP在单位超时或位置比较匹配时触发DMA,将
QPOSLAT、QCPRDLAT等数据自动搬运到指定的内存缓冲区。CPU只需定期处理缓冲区中的数据即可。结合ADC实现精准采样:如前所述,位置比较单元产生的
PCSOUT可以连接到ADC的SOC(Start-of-Conversion)触发源。在磁场定向控制中,这能确保电流采样时刻与转子位置严格同步,极大减少��算延迟带来的控制误差。需要在QEPSRCSEL寄存器中正确配置ADC触发源的选择。多圈绝对位置处理:eQEP的位置计数器是32位的,对于高分辨率编码器,很容易在高速下短时间内溢出。你需要在上层软件中维护一个“圈数”计数器。可以在位置计数器溢出(
PCO)或下溢(PCU)中断中,对这个软件计数器进行加减。同时,结合索引信号中断进行圈数校正,防止累计误差。抗噪声与滤波:工业环境噪声大。除了在硬件上做好屏蔽和滤波,eQEP的输入信号可以通过GPIO限定器进行数字滤波。但要注意,过度的滤波会引入相位延迟,影响高速性能。需要根据编码器最高频率和噪声情况折中设置
GPIO_setQualification的参数。动态改变配置:有些应用需要在运行中切换模式。例如,启动时用捕获单元测极低速,正常运行时用单位定时器测高速。切记:在改变
QCAPCTL[UPPS]或[CCPS]前,必须先禁用捕获单元(CEN=0)。改变QSRC等核心模式前,最好也先禁用位置计数器(QPEN=0),配置完成后再使能。
6. 寄存器速查与核心字段总结
手册中寄存器众多,开发时不必全部记住,但以下几个核心寄存器的关键位必须了然于胸:
| 寄存器 | 关键位域 | 功能简述 | 常用设置 |
|---|---|---|---|
| QDECCTL | QSRC | 计数模式选择 | 0(正交计数) |
XCR | 边沿计数模式 | 0(2倍频,4倍分辨率) | |
SWAP | 交换A/B相 | 根据电机转向调整 | |
QAP, QBP | 输入信号极性 | 根据硬件接线调整 | |
| QEPCTL | PCRM | 位置计数器复位模式 | 0(索引事件复位)或2(首次索引复位) |
IEI,SEI | 索引/选通事件初始化 | 2(上升沿) | |
QCLM | 捕获锁存模式 | 1(单位超时锁存,推荐) | |
UTE | 单位定时器使能 | 1(使能) | |
QPEN | 位置计数器使能 | 最后设置为1 | |
| QCAPCTL | UPPS | 单位位置事件预分频 | 根据最低测速要求选择(如5对应32) |
CCPS | 捕获时钟预分频 | 根据系统时钟和测速范围选择(如3对应8分频) | |
CEN | 捕获单元使能 | 1,但改UPPS前必须先0 | |
| QPOSCTL | PCE | 位置比较使能 | 需要同步输出时设为1 |
PCSHDW | 阴影模式 | 1(使能,安全) | |
PCLOAD | 阴影加载条件 | 1(比较匹配时加载) | |
| QEINT | UTO,IEL,WTO等 | 中断使能 | 按需开启,如UTO=1 |
最后,也是最实在的建议:充分利用TI提供的DriverLib库和示例代码。C2000Ware安装包里的eqep_ex2_pos_speed.c等例子,是极好的起点。不要从零开始写寄存器,先在这些例程的基础上修改、调试,理解每一行配置的意义,能帮你避开无数新手坑。调试时,把QPOSCNT、QEPSTS、速度变量等加入CCS的实时变量观察窗口,边转动电机边看数据变化,是理解eQEP行为最直观的方式。