1.6. ADC 与 eCAP/eQEP
1.6.1. ADC 模块
F28335 的 ADC 模块:12 位精度、16 通道、80 ns 转换时间。
ADC 模块结构:
┌────────────┐
ADCINA0 ──────────→ │ │
ADCINA1 ──────────→ │ 8 选 1 │
... │ MUX │──→ S/H ─→ 12-bit ADC ─→ RESULT0
ADCINA7 ──────────→ │ │
└────────────┘
┌────────────┐
ADCINB0 ──────────→ │ │
... │ 8 选 1 │──→ S/H ─→ 12-bit ADC ─→ RESULT1
ADCINB7 ──────────→ │ │
└────────────┘
1.6.1.1. ADC 初始化
void InitAdc(void)
{
// 1. 使能 ADC 时钟
SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1;
// 2. 上电校准
AdcRegs.ADCTRL3.all = 0x00E0; // ADC 上电,带隙参考使能
DELAY_US(1000); // 等待稳定
// 3. 设置采样窗口
AdcRegs.ADCTRL1.bit.ACQ_PS = 15; // 采样窗口 = 16 个 ADCCLK
// ADC 时钟 = HSPCLK / (ADCTRL3.ADCCLKPS + 1)
// 典型值:150 MHz / (6+1) ≈ 21.4 MHz → 46.7 ns
// 4. 设置转换模式
AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // 级联模式(16 通道排序器)
AdcRegs.ADCTRL1.bit.CONT_RUN = 0; // 启动-停止模式
AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1; // ePWM SOCA 触发
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // 使能 SEQ1 中断
}
1.6.1.2. 排序器配置
// 自动顺序转换 4 个通道
void Adc_ConfigChannels(void)
{
// 设置采样通道顺序
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0; // ADCINA0
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 1; // ADCINA1
AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 2; // ADCINA2
AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 3; // ADCINA3
// 设置转换次数
AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 3; // 4 次转换 (0~3)
}
1.6.1.3. 读取结果
interrupt void adc_isr(void)
{
uint16_t sample[4];
// 读取结果(结果寄存器自动递增)
sample[0] = AdcRegs.ADCRESULT0 >> 4; // 右对齐→右移4位
sample[1] = AdcRegs.ADCRESULT1 >> 4;
sample[2] = AdcRegs.ADCRESULT2 >> 4;
sample[3] = AdcRegs.ADCRESULT3 >> 4;
// 转换为电压(0~4095 → 0~3.3V)
float voltage = (sample[0] * 3.3) / 4095.0;
// 清除标志
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
1.6.2. eCAP 捕获模块
eCAP 用于测量 PWM 信号的频率、占空比和相位差。
eCAP 工作模式(4 种):
模式 1:捕获模式
捕获输入信号的边沿,记录时间戳
用于测量频率/占空比
模式 2:APWM 模式
作为简易 PWM 发生器使用
1.6.2.1. eCAP 捕获测量频率
void ECap1_Init(void)
{
// 捕获模式配置
ECap1Regs.ECEINT.all = 0x0000; // 先关闭中断
ECap1Regs.ECCLR.all = 0xFFFF; // 清除标志
ECap1Regs.ECCTL1.bit.CAPLDEN = 1; // 使能捕获加载
ECap1Regs.ECCTL1.bit.PRESCALE = 0; // 预分频系数 ÷1
ECap1Regs.ECCTL1.bit.CAP1POL = 0; // 上升沿触发
ECap1Regs.ECCTL1.bit.CAP2POL = 1; // 下降沿触发
ECap1Regs.ECCTL1.bit.CAP3POL = 1; // 下降沿
ECap1Regs.ECCTL1.bit.CAP4POL = 0; // 上升沿
ECap1Regs.ECCTL2.bit.CONT_ONESHT = 1; // 单次触发
ECap1Regs.ECCTL2.bit.STOP_WRAP = 3; // 4 个事件后停止
ECap1Regs.ECCTL2.bit.REARM = 1; // 强制重新触发
ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1; // 启动计数器
// 中断配置
ECap1Regs.ECEINT.bit.CEVT4 = 1; // 第 4 个捕获事件触发中断
}
// 计算频率
float ECap1_GetFrequency(void)
{
uint32_t period = ECap1Regs.CAP1; // 周期计数值
float freq = 150e6 / (float)period; // 频率 = SYSCLKOUT / period
return freq;
}
1.6.3. eQEP 正交编码器接口
eQEP 连接电机编码器,获取位置和速度信息。
QEP 信号:
QEPA ──┤ ├────┤ ├────┤ ├──── (A 相)
QEPB ──┤ ├──┤ ├────┤ ├──┤ ├─ (B 相,相位差 90°)
QEPI ──┤ ├─────────────────── (Z 相索引/零位)
void EQep1_Init(void)
{
// 正交计数模式
EQep1Regs.QUPRD = 1500; // 速度计算周期(单位:CPU 时钟)
EQep1Regs.QDECCTL.bit.QSRC = 0; // 正交模式(QA+QB 输入)
EQep1Regs.QDECCTL.bit.XCR = 0; // 2x 分辨率(提升 2 倍)
EQep1Regs.QDECCTL.bit.SWAP = 0; // 不交换 QA/QB
// 位置计数器
EQep1Regs.QPOSINIT = 0; // 初始位置
EQep1Regs.QPOSMAX = 0xFFFFFFFF; // 最大位置
// 使能中断(位置到达或速度计算完成)
EQep1Regs.QEINT.bit.QDC = 1; // 方向变化中断
EQep1Regs.QEINT.bit.QFLG = 1;
EQep1Regs.QCAPCTL.bit.UPPS = 5; // 单位位置事件预分频
EQep1Regs.QCAPCTL.bit.CCPPS = 7; // 捕获时钟预分频
EQep1Regs.QCAPCTL.bit.CEN = 1; // 使能位置捕获
}
// 读取位置
int32_t EQep1_GetPosition(void)
{
return EQep1Regs.QPOSCNT; // 当前计数值
}
// 读取速度 (rpm)
float EQep1_GetSpeed(void)
{
uint32_t pulse = EQep1Regs.QPOSLAT; // 最后捕获的位置差
// speed_rpm = pulse × 60 / (encoder_ppr × QUPRD × 150e6)
return pulse * 60.0 / (4000.0 * 1500 * 150e-6);
}