1. HPM6E80 QEIV2外设ABZ功能深度解析
先辑半导体HPM6E80微控制器内置的QEIV2正交编码器接口模块,为电机控制和位置检测应用提供了强大的硬件支持。这个模块最让我惊喜的是其灵活的可配置性和丰富的功能集成,下面我将结合实际项目经验,详细剖析ABZ编码器接口的实现细节。
1.1 QEIV2硬件架构与核心特性
QEIV2模块在设计上充分考虑了工业控制场景的需求,主要具备以下核心能力:
- 多模式输入支持:除了标准的ABZ正交编码器接口,还兼容电机HALL传感器输入、单向/双相正交输入等多种信号类型
- 可编程计数逻辑:用户可自由配置相位计数最大值(PHMAX)、Z相触发条件等参数
- 双轨测速机制:同时提供基于脉冲数和基于时长的两种速度测量方式
- 硬件快照功能:通过周期计数器和脉冲计数器的配合,实现关键数据的硬件级锁存
在实际项目中,我使用10000线ABZ增量式编码器进行测试,引脚分配如下:
c复制PB7 - QEI0_A // A相脉冲输入
PB6 - QEI0_B // B相脉冲输入
PB5 - QEI0_Z // Z相零点信号
1.2 寄存器配置关键点
配置QEIV2时需要特别注意几个关键寄存器:
- PHCFG寄存器:设置相位计数器的最大值(PHMAX),对于10000线编码器应设为10000
- CR控制寄存器:
- BIT21(PHCALIZ):Z相校准使能
- BIT20(Z_ONLY_EN):仅Z相计数模式
- PHIDX寄存器:指定相位计数器的复位值
重要提示:当使用Z相校准时,必须确保PHIDX值设置正确,否则会导致位置基准错误。我在初期调试时就因为忽略这个参数导致多次位置跳变。
2. ABZ编码器接口实现细节
2.1 初始化流程详解
完整的初始化过程需要遵循以下步骤:
c复制void BSP_QEIV2_ABZInit(void) {
// 1. 时钟配置
clock_add_to_group(clock_qei0, 0);
// 2. GPIO复用设置
HPM_IOC->PAD[IOC_PAD_PB07].FUNC_CTL = IOC_PB07_FUNC_CTL_QEI0_A;
HPM_IOC->PAD[IOC_PAD_PB06].FUNC_CTL = IOC_PB06_FUNC_CTL_QEI0_B;
HPM_IOC->PAD[IOC_PAD_PB05].FUNC_CTL = IOC_PB05_FUNC_CTL_QEI0_Z;
// 3. 工作模式配置
qeiv2_mode_config_t mode_config = {0};
mode_config.work_mode = qeiv2_work_mode_abz;
mode_config.phcnt_max = QEIV2_AB_RES;
mode_config.z_count_inc_mode = qeiv2_z_count_inc_on_phase_count_max;
qeiv2_config_mode(HPM_QEI0, &mode_config);
// 4. 初始值设置
qeiv2_set_z_phase(HPM_QEI0, 0);
qeiv2_set_phase_cnt(HPM_QEI0, 0);
// 5. 测速功能配置
qeiv2_set_cycle0_num(HPM_QEI0, 80000); // 400us周期
qeiv2_config_abz_uvw_signal_edge(HPM_QEI0, 1, 1, 0, 1, 1);
qeiv2_enable_trig_cycle0(HPM_QEI0);
qeiv2_sw_restart_cycle0(HPM_QEI0);
// 6. 中断使能
qeiv2_enable_irq(HPM_QEI0, QEIV2_EVENT_CYCLE0_FLAG_MASK | QEIV2_EVENT_Z_PHASE_FLAG_MASK);
intc_m_enable_irq_with_priority(IRQn_QEI0, 1);
}
2.2 测速算法实现原理
QEIV2提供了两种测速方式,各有优缺点:
| 测速方式 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 基于脉冲数 | 固定时间内统计脉冲数 | 高速时精度高 | 低速时分辨率低 |
| 基于时长 | 测量特定脉冲间的时间间隔 | 低速时精度高 | 高速时可能溢出 |
在项目中我采用基于时长的测速方法,关键计算公式如下:
code复制转速(°/s) = (脉冲数 / 编码器线数) × 360° / 时间间隔(s)
对应的代码实现:
c复制fSpdDuPs = (pulse_snap0) / (float)QEIV2_AB_RES * 360.0f / ((float)(cycle_snap0) * QEIV2_Cycle_To_S);
3. 调试问题与解决方案
3.1 数据缓存一致性问题
在SEGGER调试过程中遇到的典型问题:
现象:全局变量在watch窗口不能实时刷新,只有断点后会更新
原因分析:HPM6E80的三级存储架构导致:
- ILM(指令本地内存)
- DLM(数据本地内存)
- 主SRAM
CPU实际访问的是DLM中的数据,而调试器读取的是SRAM中的副本,两者不同步。
解决方案:使用ATTR_PLACE_AT_FAST_RAM宏强制变量存储在DLM:
c复制ATTR_PLACE_AT_FAST_RAM int Pulse; // 确保变量位于CPU本地内存
3.2 低速测速失效问题
现象:编码器转速低于90°/s时,快照寄存器不更新
根本原因:QEIV2的快照触发条件需要在一个测量周期内检测到至少两个脉冲边沿。对于10000线编码器:
- 400us周期时,最小可测速度≈90°/s
- 4000us周期时,最小可测速度≈9°/s
临时解决方案:动态调整测量周期:
c复制if(转速 < 阈值) {
qeiv2_set_cycle0_num(HPM_QEI0, 更大值);
qeiv2_sw_restart_cycle0(HPM_QEI0);
}
优化建议:结合脉冲计数和周期测量两种方式,实现全速度范围内的精确测速。
4. 性能优化与实践经验
4.1 中断处理优化
在高速编码器应用中,中断处理效率至关重要。以下是几个优化点:
- 关键变量定位:将所有频繁访问的变量放在DLM
c复制ATTR_PLACE_AT_FAST_RAM uint32_t pulse_snap0, pulse_snap1;
ATTR_PLACE_AT_FAST_RAM uint32_t cycle_snap0, cycle_snap1;
- 中断精简:只处理必要的事件标志
c复制void isr_qei0(void) {
uint32_t status = qeiv2_get_status(HPM_QEI0);
qeiv2_clear_status(HPM_QEI0, status);
if(status & QEIV2_EVENT_CYCLE0_FLAG_MASK) {
// 仅处理测速中断
}
}
4.2 位置检测精度提升
对于高精度应用,需要注意:
- Z相处理:合理配置Z相触发模式,避免误触发
c复制mode_config.z_count_inc_mode = qeiv2_z_count_inc_on_phase_count_max;
- 抗抖动处理:在GPIO配置时添加去抖滤波
c复制HPM_IOC->PAD[IOC_PAD_PB05].FUNC_CTL = IOC_PB05_FUNC_CTL_QEI0_Z;
HPM_IOC->PAD[IOC_PAD_PB05].PAD_CTL = IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1); // 使能上拉
4.3 实测数据对比
在不同转速下的测速精度对比:
| 设定转速(°/s) | 脉冲数测量结果 | 周期测量结果 | 误差率 |
|---|---|---|---|
| 500 | 502.3 | 499.8 | 0.4% |
| 100 | 98.5 | 100.2 | 0.2% |
| 50 | 不可测 | 50.1 | 0.2% |
| 5 | 不可测 | 5.3 | 6% |
从数据可以看出,周期测量法在低速时优势明显,但极低速时误差会增大,这时需要考虑延长测量周期或采用其他补偿算法。
