3. 正交编码器接口与转速计算
任务目标
本案例实现基于C2000系列DSP(以TMS320F280049C为例)的eQEP模块配置,完成对正交编码器信号的解码,并计算电机转子位置与转速。核心内容包括:eQEP引脚初始化、位置计数器配置、单位时间位置差计算转速,以及通过串口输出结果供验证。
硬件连接与依赖
- 编码器A/B信号分别连接至EQEP1A(GPIO24)和EQEP1B(GPIO25),索引信号Z(GPIO26)可选接入。
- 依赖
driverlib库(C2000Ware),需在工程中包含eqep.h、gpio.h、sysctl.h、uart.h头文件。 - 编码器线数(PPR)需根据实际硬件修改宏
ENCODER_PPR。
核心实现
#include "driverlib.h"
#include "device.h"
#define ENCODER_PPR 1000 // 编码器每圈脉冲数
#define SPEED_CALC_MS 100 // 转速计算周期(ms)
volatile uint32_t g_position = 0;
volatile int32_t g_speed_rpm = 0;
volatile uint32_t g_last_pos = 0;
// 初始化eQEP1为正交计数模式
void EQEP1_Init(void)
{
// 启用eQEP1时钟
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EQEP1);
// 配置GPIO24/25为EQEP1A/1B功能
GPIO_setPinConfig(GPIO_24_EQEP1A);
GPIO_setPinConfig(GPIO_25_EQEP1B);
GPIO_setDirectionMode(24, GPIO_DIR_MODE_IN);
GPIO_setDirectionMode(25, GPIO_DIR_MODE_IN);
GPIO_setQualificationMode(24, GPIO_QUAL_ASYNC);
GPIO_setQualificationMode(25, GPIO_QUAL_ASYNC);
// 配置eQEP模块
EQEP_setDecoderConfig(EQEP1_BASE,
EQEP_CONFIG_2X_RESOLUTION | // 2倍频(A/B边沿计数)
EQEP_CONFIG_QUADRATURE_MODE); // 正交计数模式
EQEP_setPositionCounterConfig(EQEP1_BASE,
EQEP_POSITION_RESET_IDX, // 索引信号复位
0xFFFFFFFF); // 最大计数
EQEP_setPositionCounter(EQEP1_BASE, 0);
EQEP_setLatchMode(EQEP1_BASE, EQEP_LATCH_WINDOW_ENABLE);
EQEP_setCaptureLatchMode(EQEP1_BASE, EQEP_CAPTURE_CLOCK_DIV_1);
}
// 读取当前位置(带方向)
uint32_t EQEP1_GetPosition(void)
{
return EQEP_getPositionCounter(EQEP1_BASE);
}
// 定时计算转速(在定时器中断中调用,周期100ms)
void Speed_Calculate(void)
{
uint32_t cur_pos = EQEP1_GetPosition();
int32_t delta = (int32_t)(cur_pos - g_last_pos);
g_last_pos = cur_pos;
g_position = cur_pos;
// 转速 = 脉冲差 / (PPR*2) / 时间(分钟)
// 时间 = SPEED_CALC_MS/1000/60 分钟
float rev = (float)delta / (ENCODER_PPR * 2);
float minutes = (float)SPEED_CALC_MS / 60000.0f;
g_speed_rpm = (int32_t)(rev / minutes);
}
void main(void)
{
Device_init();
EQEP1_Init();
// 配置定时器0,周期100ms触发中断
CPUTimer_setPeriod(CPUTIMER0_BASE, 100000);
CPUTimer_registerInterrupt(CPUTIMER0_BASE, &Speed_Calculate);
CPUTimer_enableInterrupt(CPUTIMER0_BASE);
CPUTimer_startTimer(CPUTIMER0_BASE);
// 串口初始化(用于输出结果)
UART_init(UART0_BASE, 9600);
while(1)
{
// 主循环中可通过调试器观察g_position和g_speed_rpm
DEVICE_DELAY_US(500000);
}
}
运行与验证
- 将代码烧录至F280049C LaunchPad,编码器A/B接入GPIO24/25。
- 在CCS调试模式下,将
g_position和g_speed_rpm添加至Expressions窗口。 - 手动旋转编码器轴:
g_position应随旋转方向递增或递减;g_speed_rpm应显示当前转速(正负代表方向)。 - 通过标准:以恒定速度旋转编码器,观察
g_speed_rpm数值稳定且与实测转速(如用手持转速表)误差在±5%以内;反向旋转时数值符号翻转。
关键说明
- 本代码使用2倍频模式,因此每圈计数值为
PPR×2。若编码器为1000线,则每圈2000个计数。 - 转速计算周期
SPEED_CALC_MS需与定时器中断周期一致(本例100ms),修改时需同步调整。 - 索引信号Z未强制使用,若需精确定位可接入GPIO26并配置
EQEP_POSITION_RESET_IDX为索引复位模式。 - 实际工程中建议增加速度低通滤波,但本案例为演示最小实现,未包含滤波逻辑。