TMS320F2837xD eQEP边沿捕获单元:实现伺服电机极低速高精度测速
1. 项目概述与核心价值
在伺服电机、机器人关节、精密转台这类对低速平稳性要求极高的运动控制场景里,工程师们最头疼的问题之一,就是如何精确测量极低转速下的电机速度。你可能会想,用高分辨率编码器不就行了?但实际情况是,当电机转速低到每分钟只有几转甚至更低时,编码器脉冲的间隔时间会变得非常长。如果单纯依赖CPU去定时读取位置计数器并做软件差分,不仅会消耗大量宝贵的CPU周期,更会因为软件延迟和中断响应时间的不确定性,引入难以校准的测量误差,导致速度环产生低频抖动,整个系统的控制性能大打折扣。
这时,像TI TMS320F2837xD这类高性能微控制器内置的 增强型正交编码器脉冲(eQEP) 模块的 边沿捕获单元(Edge Capture Unit) ,其价值就凸显出来了。它不是一个简单的计数器,而是一个专为“时间间隔测量”而生的硬件加速器。它的核心任务,就是自动、精准地捕获“单位位置事件”之间的时间差(ΔT)。这个“单位位置事件”可以灵活配置,比如可以是编码器产生的每1个、4个、16个正交时钟边沿。硬件会在这个事件发生的瞬间,“咔嚓”一下把内部一个高速运行的自由运行定时器的当前值锁存下来。两次锁存值之差,就是精确的ΔT,其时间基准直接来源于系统主频(SYSCLKOUT),分辨率可以轻松达到纳秒级。
这样一来,低速速度计算就从一个复杂的软件定时问题,简化成了一个简单的硬件读数问题:
速度 v = (固定的位置增量 ΔX) / (硬件捕获的时间差 ΔT)
。CPU只需要在需要的时候(比如速度环控制周期到来时),去读取两个锁存寄存器(
QCPRDLAT
,
QPOSLAT
),就能直接获得高精度的速度信息,几乎不占用CPU资源。这对于实现高带宽、高精度的电流环、速度环、位置环全闭环控制至关重要。今天,我就结合手册和实际调参经验,把这个eQEP边沿捕获单元从原理到寄存器配置,再到实际编程和避坑指南,给你彻底讲透。
2. eQEP边沿捕获单元的核心原理与架构拆解
要玩转这个边沿捕获单元,不能只停留在“怎么配寄存器”的层面,必须吃透它的工作原理。你可以把它想象成一个专为编码器脉冲“掐表”的精密计时系统。
2.1 核心测量模型:v(k) = ΔX / ΔT
所有低速测量的理论基础都是这个公式:
v(k) = ΔX / ΔT
。
-
ΔX (位置增量)
:这是一个“固定”的单位位移量。它由你的编码器线数和
QCAPCTL[UPPS](单位位置事件预分频器)共同决定。例如,一个1000线的编码器,四倍频后每转产生4000个QCLK(正交时钟)。如果你设置UPPS=0010(即除以4),那么一个“单位位置事件”(UPEVNT)就对应着4000 / 4 = 1000个QCLK,也就是电机正好转了1/4圈。这个ΔX就是1/4圈对应的机械位移(例如,如果丝杠导程是10mm,那么ΔX就是2.5mm)。 关键在于,这个ΔX在你的测量周期内是已知的常数。 -
ΔT (时间增量)
:这就是边沿捕获单元要测量的核心数据。它代表电机走过上述固定位移
ΔX所花费的真实时间。这个时间由硬件捕获定时器QCTMR测量,并在每个单位位置事件发生时,将其计数值锁存到QCPRD寄存器中。ΔT就等于连续两次锁存值之差(QCPRD(k) - QCPRD(k-1))乘以捕获时钟的周期。
为什么这个模型适合低速测量? 在高速时,我们常用“M法测速”(固定时间间隔内数脉冲个数)。但在低速时,固定时间内可能只收到寥寥几个甚至零个脉冲,测量分辨率极低,误差巨大。而“T法测速”(测量固定脉冲数之间的时间间隔)在低速时,由于脉冲间隔长,时间测量值大,相对误差小,分辨率高。eQEP的边沿捕获单元就是硬件实现的T法测速。
2.2 硬件架构与数据流
根据手册中的图17-15,整个边沿捕获单元的硬件流水线可以分解为以下几个关键环节:
-
时钟源与预分频
:整个单元的时基来源于
SYSCLKOUT(系统时钟)。它首先经过一个由QCAPCTL[CCPS]控制的3位分频器,产生CAPCLK,作为捕获定时器QCTMR的计数时钟。CCPS可以从/1配置到/128,这让你能根据电机最高速度和测量精度需求来调整QCTMR的计数频率,避免溢出。 -
单位位置事件生成
:编码器输入经过解码后产生
QCLK(正交时钟)和QDIR(方向信号)。QCLK再经过一个由QCAPCTL[UPPS]控制的4位分频器,产生“单位位置事件”(UPEVNT)信号。UPPS的分频系数从/1到/2048,这直接决定了你的ΔX有多大。UPPS是软件定义“单位位移”大小的关键 。 -
捕获与锁存机制
:这是最精妙的部分。
QCTMR是一个16位的自由运行向上计数器,始终由CAPCLK驱动。每当一个UPEVNT事件发生时,硬件会立即执行两个动作:-
锁存
:将
QCTMR的当前值锁存到捕获周期寄存器QCPRD中。 -
复位
:将
QCTMR清零,重新开始计数。 同时,状态寄存器QEPSTS中的UPEVNT标志位会被置1,告知CPU有新的数据可用。CPU在读取QCPRD之前,应先检查该标志位。
-
锁存
:将
-
双缓冲锁存器
:为了避免CPU在读取
QCPRD时,该值被新的捕获事件覆盖,模块提供了锁存寄存器QCPRDLAT和QCTMRLAT。根据QEPCTL[QCLM]位的设置,锁存触发方式有两种:-
QCLM=0:当CPU读取位置计数器QPOSCNT时,自动将QCTMR和QCPRD的值分别锁存到QCTMRLAT和QCPRDLAT。这种方式适合在任意时刻采样速度。 -
QCLM=1:当“单位超时事件”(由另一个独立的32位单元定时器QUTMR与QUPRD比较产生)发生时,自动将QPOSCNT、QCTMR、QCPRD的值分别锁存到QPOSLAT、QCTMRLAT、QCPRDLAT。这种方式适合在固定的、周期性的控制中断里同步获取位置和速度信息,是最常用、最可靠的方式。
-
2.3 关键约束条件与错误处理
硬件不是万能的,它有两个重要的约束条件,在编程中必须处理:
-
无溢出条件 :
QCTMR是一个16位计数器,最大计数值为65535。手册明确指出, 两个连续的单位位置事件之间,QCTMR的计数值不能超过65535 。如果超过了,QEPSTS[COEF](捕获溢出错误标志)会被置1,并且QCPRDLAT会被设置为0xFFFF。此时读取的ΔT无效。-
应对策略
:通过合理设置
CCPS分频比来降低CAPCLK频率,确保在最低预期转速下,QCTMR也不会溢出。这需要计算。
-
应对策略
:通过合理设置
-
无方向改变条件 :在测量两个单位位置事件之间的时间ΔT时,电机的旋转方向必须保持不变。如果方向改变了,
QEPSTS[CDEF](捕获方向错误标志)会被置1,QCPRDLAT同样被置为0xFFFF。-
应对策略
:在速度计算中断服务程序中,读取数据前必须先检查
CDEF标志。如果置位,说明此次测量无效,应丢弃该速度值,并清除标志位。通常可以沿用上一次的有效速度值或进行滤波处理。
-
应对策略
:在速度计算中断服务程序中,读取数据前必须先检查
注意 :手册中特别用
CAUTION强调了QCAPCTL[UPPS](单位事件预分频器) 不能动态修改 。也就是说,你不能在捕获单元使能后,运行时去改变UPPS的值,否则会导致未定义行为。CCPS(捕获时钟预分频器)虽然可以动态修改,但 必须在捕获单元禁用(QCAPCTL[CEN]=0)的情况下进行 。这是一个非常容易踩坑的地方,务必在初始化阶段就确定好分频参数,运行时不要更改UPPS。
3. 低速测量实战:从寄存器配置到速度计算
理论清楚了,我们直接上干货,看看在TMS320F2837xD的C代码里,如何一步步配置并读出可靠的低速值。
3.1 硬件与软件初始化配置
假设我们使用eQEP1外设,编码器为2500线(四倍频后每转10000个QCLK),系统时钟
SYSCLKOUT
为200MHz。我们希望测量低至1RPM左右的速度,并且速度环控制频率为10kHz(即每100us计算一次速度)。
步骤1:确定单位位置事件(ΔX)
我们希望速度更新率(与控制频率同步)为10kHz,但单位位置事件不能太快,否则在低速时
QCTMR
计数值太小,量化误差大。我们折中一下,让单位位置事件频率约为速度更新频率的10-100倍。这里设定单位位置事件对应电机旋转1/100转。
- 每转QCLK数 = 2500 * 4 = 10000。
- 对应1/100转的QCLK数 = 10000 / 100 = 100。
-
因此,需要配置
UPPS,使得UPEVNT = QCLK / N中的 N = 100。查手册,UPPS是2的幂次分频(1,2,4,...,2048)。100不是2的幂,我们选择最接近的128(UPPS=7h)。此时,一个UPEVNT实际对应 10000 / 128 ≈ 78.125 个QCLK。我们的ΔX就是这78.125个QCLK对应的机械位移。 记住这个实际值,后续计算速度要用它 。
步骤2:配置捕获时钟,防止溢出 首先估算最低转速下的最大ΔT。在1RPM时:
- 电机每秒转数 = 1 / 60 ≈ 0.01667 RPS。
- 每转时间 = 1 / 0.01667 ≈ 60秒。
-
一个
UPEVNT事件的时间(对应1/100转)≈ 60 / 100 = 0.6秒。 我们需要确保在0.6秒内,QCTMR从0计数到最大值65535也不会溢出。 -
QCTMR计数频率 =CAPCLK=SYSCLKOUT/CCPS_DIV。 -
要求:
0.6秒 * CAPCLK < 65535。 -
推导出:
CAPCLK < 65535 / 0.6 ≈ 109225 Hz。 -
已知
SYSCLKOUT=200MHz,所以分频比CCPS_DIV> 200e6 / 109225 ≈ 1831。 查手册,CCPS最大分频为128。200MHz / 128 = 1.5625MHz,这远大于109kHz, 在1RPM时依然会溢出! 这说明,在极低速(1RPM)且单位事件划分较细(1/100转)的情况下,16位QCTMR可能不够用。我们有三个选择: -
选择A:增大单位事件
。将
UPPS设为256或512,让ΔX变大,这样相同转速下UPEVNT间隔时间变短,不易溢出。但会降低速度测量的“颗粒度”。 - 选择B:接受更高的最低测量转速 。例如,将最低测量转速设定为10RPM,重新计算。
-
选择C:在软件中处理溢出
。如果溢出发生(
COEF=1),则本次速度值无效。这对于偶尔的极低速情况可以接受。 这里为了演示,我们选择B,假设最低测量转速为10RPM。重新计算: -
10RPM下,一个
UPEVNT时间 ≈ (60/10) / 100 = 0.06秒。 -
要求
CAPCLK < 65535 / 0.06 ≈ 1.09MHz。 -
CCPS_DIV> 200e6 / 1.09e6 ≈ 183。选择CCPS=7(分频128),CAPCLK=1.5625MHz,满足要求。 结论 :配置CCPS=7(CAPCLK = SYSCLKOUT/128)。
步骤3:初始化代码示例
// 假设使用eQEP1
void InitEQEP1_EdgeCapture(void)
{
// 1. 首先禁用eQEP模块,进行整体配置
EQep1Regs.QEPCTL.bit.QPEN = 0; // 禁用位置计数器,复位内部状态
// 2. 配置解码器控制 (根据实际硬件接线)
EQep1Regs.QDECCTL.bit.QSRC = 0; // 00: 正交计数模式(标准编码器模式)
EQep1Regs.QDECCTL.bit.XCR = 1; // 1x分辨率(仅上升沿计数)。对于高分辨率编码器,也可选0(2x,上升下降沿都计数)
// QAP, QBP, QIP, QSP 根据编码器信号极性配置,默认0(不取反)
// 3. 配置边沿捕获单元
EQep1Regs.QCAPCTL.bit.UPPS = 7; // UPPS=7: UPEVNT = QCLK / 128 (对应我们约1/100转的事件)
EQep1Regs.QCAPCTL.bit.CCPS = 7; // CCPS=7: CAPCLK = SYSCLKOUT / 128 = 200MHz/128 ≈ 1.5625MHz
EQep1Regs.QCAPCTL.bit.CEN = 1; // 使能捕获单元
// 4. 配置单元定时器,用于周期性锁存(QCLM=1模式)
// 速度环频率10kHz,即周期100us。SYSCLKOUT=200MHz,周期为5ns。
// 单元定时器计数值 = 时间间隔 / 时钟周期 = 100us / 5ns = 20000
EQep1Regs.QUPRD = 20000; // 设置单元定时器周期
EQep1Regs.QEPCTL.bit.UTE = 1; // 使能单元定时器
EQep1Regs.QEPCTL.bit.QCLM = 1; // 锁存模式:在单元超时事件时锁存(推荐!)
// 5. 配置中断(可选,如果需要利用UTO中断触发速度计算)
EQep1Regs.QEINT.bit.UTO = 1; // 使能单元超时中断
// 6. 最后,使能eQEP位置计数器
EQep1Regs.QEPCTL.bit.QPEN = 1;
// 7. 初始化变量(软件层面)
g_i32PrevQcpLat = 0;
g_i32PrevPosLat = 0;
g_fSpeedRpm = 0.0;
}
3.2 速度计算与数据处理流程
配置好后,速度计算通常在单元超时中断(UTO)服务程序或主循环的定时任务中进行。这里以UTO中断服务程序为例:
// 全局变量
int32_t g_i32PrevQcpLat = 0; // 上一次锁存的捕获周期值
int32_t g_i32PrevPosLat = 0; // 上一次锁存的位置值
float g_fSpeedRpm = 0.0; // 计算得到的转速(RPM)
const float g_fMechScaler = 60.0f / (10000.0f / 128.0f); // 速度计算标尺,后面解释
__interrupt void eQEP1_ISR(void)
{
// 1. 检查中断源
if(EQep1Regs.QFLG.bit.UTO == 1) // 单元超时中断
{
// 2. 读取锁存寄存器(在QCLM=1模式下,UTO事件会自动锁存)
int32_t i32CurrQcpLat = (int32_t)EQep1Regs.QCPRDLAT; // ΔT对应的计数值
int32_t i32CurrPosLat = (int32_t)EQep1Regs.QPOSLAT; // 当前位置值
// 3. 检查捕获错误标志
if(EQep1Regs.QEPSTS.bit.CDEF == 1)
{
// 方向在测量期间发生变化,本次ΔT无效
// 可以丢弃本次计算,或使用上一次的有效速度值
// 清除错误标志
EQep1Regs.QEPSTS.bit.CDEF = 1;
}
else if(EQep1Regs.QEPSTS.bit.COEF == 1)
{
// 捕获定时器溢出,本次ΔT无效(发生在转速过低时)
// 处理策略:可以标记速度无效,或尝试增大CCPS分频比(需重新初始化)
// 清除错误标志
EQep1Regs.QEPSTS.bit.COEF = 1;
}
else
{
// 4. 计算时间增量ΔT(单位:秒)
// ΔT = (当前捕获值 - 上一次捕获值) / CAPCLK频率
// 注意:QCTMR是16位计数器,但QCPRDLAT也是16位,相减可能为负(由于计数器复位),需处理。
// 实际上,因为UTO周期固定,且QCTMR在每个UPEVNT事件复位,两次UTO间的QCPRDLAT差值
// 直接反映了最后一个UPEVNT周期的时间。
// 更稳健的方法是:ΔT = i32CurrQcpLat / CAPCLK_Freq
// 但i32CurrQcpLat是本次UTO时刻锁存的QCTMR值,它记录的是上个UTO到本次UTO之间,
// 最后一个UPEVNT事件发生后的“残余”时间。这不是一个完整的UPEVNT周期。
// 因此,更准确的方法是利用UPEVNT标志和QCPRD(非锁存)寄存器。
// 这里演示一种在UTO中断中,且确保一个UTO周期内至少发生一次UPEVNT的简化方法:
if(g_i32PrevQcpLat != 0) // 非第一次进入
{
// 计算ΔT(假设一个UTO周期内只有一个主要的UPEVNT,其周期被锁存在QCPRD)
// 注意:需要将QCPRD的值从QCTMR计数值转换为时间。
float fDeltaT = (float)EQep1Regs.QCPRD / CAPCLK_FREQ; // CAPCLK_FREQ = 1.5625e6 Hz
// 5. 计算速度
// ΔX = (1转的位移) / (每转的UPEVNT数)
// 每转UPEVNT数 = (编码器线数 * 4) / UPPS分频系数 = 10000 / 128 = 78.125
// 因此,每��UPEVNT对应的机械角度 = 360度 / 78.125 ≈ 4.608度
// 或者,每个UPEVNT对应的转数 = 1 / 78.125 ≈ 0.0128 转。
// 速度 v (转/秒) = ΔX (转) / ΔT (秒) = (1/78.125) / fDeltaT
// 速度 v (RPM) = v (转/秒) * 60 = 60 / (78.125 * fDeltaT)
// 代入 fDeltaT = QCPRD / CAPCLK_FREQ
// 得到:v_rpm = 60 * CAPCLK_FREQ / (78.125 * QCPRD)
// 定义常量 g_fMechScaler = 60.0 * CAPCLK_FREQ / 78.125
if(EQep1Regs.QCPRD != 0) // 避免除零
{
g_fSpeedRpm = g_fMechScaler / (float)EQep1Regs.QCPRD;
}
}
// 更新上一次的捕获值(用于错误检测或备用计算)
g_i32PrevQcpLat = i32CurrQcpLat;
g_i32PrevPosLat = i32CurrPosLat;
}
// 6. 清除中断标志
EQep1Regs.QCLR.bit.UTO = 1; // 写1清除UTO中断标志
EQep1Regs.QCLR.bit.INT = 1; // 写1清除全局中断标志
}
// 其他中断源处理...
PieCtrlRegs.PIEACK.all = PIEACK_GROUP4; // 确认PIE组中断
}
关于速度计算标尺
g_fMechScaler
的详细推导:
这是将硬件读数转换为物理速度的关键常数。
-
公式:
v_rpm = (ΔX_revolution / ΔT_second) * 60 -
其中:
-
ΔX_revolution = 1 / UPEVNT_per_revolution(每个单位位置事件对应的转数) -
UPEVNT_per_revolution = (Encoder_PPR * 4) / UPPS_Divider-
Encoder_PPR: 编码器每转脉冲数(线数),本例为2500。 -
4: 四倍频。 -
UPPS_Divider:UPPS设置的分频系数,本例为128。
-
-
所以,
ΔX_revolution = 1 / ((2500*4)/128) = 128 / 10000 = 0.0128 转。
-
-
ΔT_second = QCPRD / CAPCLK_Freq-
QCPRD: 硬件捕获的寄存器值(无单位,计数个数)。 -
CAPCLK_Freq = SYSCLKOUT / CCPS_Divider = 200e6 / 128 = 1.5625e6 Hz。
-
-
代入公式:
v_rpm = (0.0128 / (QCPRD / 1.5625e6)) * 60 = (0.0128 * 1.5625e6 * 60) / QCPRD= (1200000) / QCPRD。 -
因此,本例中的
g_fMechScaler = 1200000.0。
这个推导过程至关重要
。在实际项目中,你需要根据自己电机的编码器参数和
UPPS
、
CCPS
的配置,重新计算这个标尺因子。
4. 高级应用与配置技巧
掌握了基础的速度计算,我们再来看看如何利用边沿捕获单元实现更稳定、更鲁棒的应用。
4.1 使用“单位超时”模式实现同步采样
如前所述,将
QEPCTL[QCLM]
设置为1是最推荐的方式。在这种模式下,位置
QPOSLAT
、捕获定时器
QCTMRLAT
、捕获周期
QCPRDLAT
这三个值会在
同一个时刻
(即单元定时器
QUTMR
匹配
QUPRD
产生
UTO
事件的时刻)被硬件自动锁存。这保证了位置和速度采样在时间上是严格同步的,对于控制算法来说消除了采样不同步带来的相位误差。
配置要点 :
-
根据你的控制频率(如10kHz)设置
QUPRD。 -
使能单元定时器(
UTE=1)。 -
设置
QCLM=1。 -
在
UTO中断中,同时读取QPOSLAT和QCPRDLAT(或QCTMRLAT),分别用于位置环和速度环计算。
4.2 低速测量的滤波与抗扰处理
在极低速或电机堵转时,测量容易受到干扰,产生跳变。可以加入软件滤波:
-
中值滤波/滑动平均滤波 :连续采样多个速度值(如5个),取中值或平均值作为最终输出。这能有效抑制偶然的野值。
#define SPEED_FILTER_SIZE 5 float speedBuffer[SPEED_FILTER_SIZE] = {0}; int speedIndex = 0; float GetFilteredSpeed(float newSpeed) { speedBuffer[speedIndex] = newSpeed; speedIndex = (speedIndex + 1) % SPEED_FILTER_SIZE; float sum = 0; for(int i=0; i<SPEED_FILTER_SIZE; i++) sum += speedBuffer[i]; return sum / SPEED_FILTER_SIZE; } -
无效数据剔除 :在中断服务程序中,如果检测到
CDEF或COEF错误标志,或者计算出的速度值超过物理极限(如额定转速的120%),则丢弃该次数据,维持上一次的有效速度或输出零速。 -
死区处理 :当计算出的速度绝对值小于一个很小的阈值(例如0.1%额定转速)时,直接将其设为零。这可以避免因测量噪声或微小抖动导致电机在零速指令下仍有微动。
4.3 全速度范围测量:结合M/T法思想
eQEP的边沿捕获单元本质是T法(测周法),在低速时优势明显,但在高速时,
UPEVNT
事件间隔很短,
QCTMR
计数值很小,量化误差占比会变大。对于宽速度范围的应用,理想的方案是
低速用T法,高速用M法
。
eQEP模块本身没有直接提供M法测量,但我们可以利用其资源实现一个“软M/T法”:
-
M法(高速区)
:在固定的单元超时周期(
UTO,如100us)内,读取QPOSLAT的增量ΔX_cnt(位置计数器差值)。速度v = ΔX_cnt / (T * K),其中T是固定周期,K是每个QCLK对应的位移。 -
切换逻辑
:在软件中判断。当用T法计算出的速度值高于某个阈值(例如额定转速的5%),且
QCPRD值小于某个阈值(表示脉冲周期短,T法误差大)时,切换到M法计算。反之,则使用T法。
实现提示
:
QPOSLAT
在
UTO
事件时锁存,正好提供了固定周期T内的位置增量,非常适合做M法计算。你可以在同一个
UTO
中断里,同时用T法(基于
QCPRD
)和M法(基于本次和上次的
QPOSLAT
差)计算两个速度值,然后根据逻辑选择输出哪一个。
5. 常见问题排查与调试心得
调过这个模块的工程师,多少都踩过一些坑。下面是我总结的几个典型问题和解决方法。
5.1 问题排查清单
| 现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 读出的速度值始终为0或极大 |
1. 捕获单元未使能。
2.
UPPS
设置过大,单位事件未产生。
3. 编码器信号未正确接入或极性配置错误。 |
1. 检查
QCAPCTL[CEN]
是否为1。
2. 用示波器或IO翻转调试,检查
UPEVNT
信号是否产生。减小
UPPS
值。
3. 检查
QDECCTL
中
QSRC
、
XCR
、
QAP
、
QBP
配置。用示波器看QEPA、QEPB波形,并监控
QPOSCNT
是否随电机转动变化。
|
| 速度值波动大,噪声明显 |
1. 转速过低,接近测量下限。
2.
CCPS
分频太小,
CAPCLK
过高,
QCTMR
计数值太小,量化误差大。
3. 机械振动或编码器信号噪声。 |
1. 尝试增大
UPPS
,以增大
ΔX
,提高T法信噪比。
2. 增大
CCPS
分频比,降低
CAPCLK
,使
QCTMR
在低速下也有足够大的计数值。
3. 检查编码器连接,使用双绞线,并确保电源稳定。在软件中加入滤波。 |
| 偶尔出现速度跳变到极大值 |
1.
QCPRD
寄存器读到了0。
2. 发生了捕获溢出(
COEF
)或方向错误(
CDEF
)。
|
1. 在速度计算前判断
if(QCPRD == 0)
,则跳过本次计算或使用上次值。
2. 在读取速度前,先检查
QEPSTS[COEF]
和
[CDEF]
标志,若置位则处理错误并清除标志。
|
UTO
中断不产生或速度更新慢
|
1. 单元定时器未使能或
QUPRD
设置过大。
2. eQEP模块全局中断未使能,或PIE、CPU中断未配置。 3.
QCLM
模式配置错误。
|
1. 检查
QEPCTL[UTE]
是否为1,计算
QUPRD
值是否正确。
2. 检查
QEINT
、PIEIER、CPU IER等中断使能位。在中断服务程序中确认标志位清除。
3. 如果希望在
UTO
中断中读取锁存值,确保
QEPCTL[QCLM]=1
。
|
| 测量值存在固定偏差 |
速度计算标尺因子
g_fMechScaler
计算错误。
|
重新核对公式:编码器线数、四倍频、
UPPS
分频系数、
SYSCLKOUT
频率、
CCPS
分频系数。最好通过实际测试校准:让电机以恒定已知转速(如用高精度测速仪标定)运行,反算出实际的比例因子。
|
5.2 调试心得与最佳实践
-
先调通位置,再调速度
:务必先确保
QPOSCNT能正确反映电机正反转。这是所有功能的基础。可以通过让电机缓慢手动旋转,观察QPOSCNT的变化方向和增量是否正确。 - 善用GPIO翻转调试 :在初始化代码和中断服务程序的关键位置(如进入中断、读完寄存器后)用GPIO输出高低电平,用示波器观察时序。这能帮你确认中断是否按时发生,程序执行时间是否超预期。
-
寄存器配置顺序
:建议按照“先功能后使能”的顺序。例如,先配置好
QCAPCTL的所有分频参数,最后再置位CEN;先配置好QUPRD,再使能UTE。对于UPPS,务必在初始化时一次设好,运行中切勿改动。 -
理解“锁存”与“实时”寄存器的区别
:
QCPRD是实时寄存器,每次UPEVNT事件都会更新。而QCPRDLAT是锁存寄存器,其更新时刻由QCLM位决定。在QCLM=1模式下,UTO事件发生时,硬件会把 那一刻 的QCPRD值锁存到QCPRDLAT。这意味着QCPRDLAT捕获的可能是两个UPEVNT中间某个时刻的QCPRD值,不一定是一个完整的UPEVNT周期。对于精确的T法,更推荐在UPEVNT中断(如果使能了)里直接读QCPRD,或者在UTO中断里采用我上面提到的简化处理/滤波方法。 -
为极端情况做好准备
:你的代码必须能处理电机堵转(
COEF溢出)、瞬间反转(CDEF错误)、以及上电初始化期间寄存器值为0的情况。健壮的错误处理是产品稳定性的保证。
最后,再强调一下那个最容易忽略的坑:
UPPS
不能动态修改!
如果你需要在运行中改变测量分辨率,一个可行的方案是准备两套配置(例如一套
UPPS=7
用于低速,一套
UPPS=3
用于高速),然后在确保捕获单元禁用(
CEN=0
)的情况下,切换整个
QCAPCTL
寄存器的配置,再重新使能。但这会带来速度测量的短暂中断,需要软件做平滑过渡。
更多推荐
所有评论(0)