1.4. GPIO 与 PIE 中断系统
F28335 有 88 个 GPIO 引脚,每个引脚可配置为通用 I/O 或外设功能。
1.4.1. GPIO 配置
// GPIO 模式设置
// 每个 GPIO 有 4 种功能(通过 GPAMUX1/2 或 GPBMUX1/2 配置)
void Gpio_setup(void)
{
EALLOW;
// GPIO0:通用输出
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0; // 00 = GPIO 模式
GpioCtrlRegs.GPADIR.bit.GPIO0 = 1; // 输出
GpioCtrlRegs.GPAQSEL1.bit.GPIO0 = 0; // 同步采样(输入滤波)
// GPIO1:通用输入(上拉)
GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 0;
GpioCtrlRegs.GPADIR.bit.GPIO1 = 0; // 输入
GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0; // 使能上拉(0=启用)
// GPIO2:ePWM1A 外设功能
GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1; // 01 = ePWM1A
// GPIO3:SCI 接收
GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 1; // 01 = SCIRXDA
EDIS;
}
GPAMUX 值 |
功能 |
|---|---|
00 |
通用 GPIO |
01 |
外设功能 1 |
10 |
外设功能 2 |
11 |
外设功能 3 |
1.4.2. GPIO 读写
// 写输出
GpioDataRegs.GPADAT.bit.GPIO0 = 1; // 高电平
GpioDataRegs.GPADAT.bit.GPIO0 = 0; // 低电平
// 推荐:仅翻转指定位(不影响其他引脚)
GpioDataRegs.GPASET.bit.GPIO0 = 1; // 置位
GpioDataRegs.GPACLEAR.bit.GPIO0 = 1; // 清零
GpioDataRegs.GPATOGGLE.bit.GPIO0 = 1; // 翻转
// 读输入(不管 GPIO 方向,都能读取实际引脚电平)
uint16_t pin = GpioDataRegs.GPADAT.bit.GPIO1;
1.4.3. PIE 中断系统
F28335 的 PIE(外设中断扩展)模块将 96 个外设中断复用到 12 个 CPU 中断。
PIE 中断结构:
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 外设中断源 │────→│ PIE 分组 │────→│ CPU 中断 │
│ (96个) │ │ (12组×8路) │ │ INT1~INT12 │
└──────────────┘ └──────────────┘ └──────────────┘
PIE 分组示意:
INT1: TIMER0 | ADCINT | ...
INT2: EPWM1 | EPWM2 | ...
INT3: EPWM3 | EPWM4 | ...
INT4: ECAP1 | ECAP2 | ...
INT5: EQEP1 | ...
INT6: SPIRX | SPITX | ...
INT7: ...
INT8: I2C | ...
INT9: SCIRX | SCITX | ...
INT10: CAN | ...
INT11: CLA | ...
INT12: XINT1-3 | ...
1.4.3.1. 中断配置步骤
// 1. 中断服务函数声明
interrupt void adc_isr(void);
// 2. 初始化 PIE 并注册中断服务
void InitInterrupts(void)
{
// 初始化 PIE 控制寄存器
InitPieCtrl();
// 关闭所有 CPU 中断
IER = 0x0000;
IFR = 0x0000;
// 初始化中断向量表
InitPieVectTable();
// 注册中断服务函数
EALLOW;
PieVectTable.ADCINT1 = &adc_isr;
EDIS;
// 使能 PIE 分组中的具体中断
PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // PIE 组 1 的第 1 个中断 (ADC)
// 使能 CPU 中断
IER |= M_INT1; // CPU 中断 1
// 开启全局中断
EINT; // 相当于 asm(" CLRC INTM")
}
// 3. 实现中断服务函数
interrupt void adc_isr(void)
{
static uint16_t sample;
// 读取 ADC 结果
sample = AdcRegs.ADCRESULT0;
// 清除 ADC 中断标志
AdcRegs.ADCST.bit.INT_FLAG_CLR = 1;
// 应答 PIE 中断
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
// CPU 自动清除 INTM(中断返回时会自动恢复)
}
重要
中断服务函数必须:
清除外设中断标志 (每个外设不同)
应答 PIE 中断:
PieCtrlRegs.PIEACK.all = PIEACK_GROUPn使用
interrupt关键字声明代码尽量简短(避免长时间关中断)
函数名注册到
PieVectTable
1.4.4. 外部中断(XINT1~XINT3)
void InitExternalInterrupt(void)
{
// XINT1 连接到 GPIO0,下降沿触发
EALLOW;
GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL = 0; // GPIO0
EDIS;
XIntruptRegs.XINT1CR.bit.POLARITY = 1; // 下降沿
XIntruptRegs.XINT1CR.bit.ENABLE = 1; // 使能
// 注册中断
EALLOW;
PieVectTable.XINT1 = &xint1_isr;
EDIS;
PieCtrlRegs.PIEIER12.bit.INTx1 = 1;
IER |= M_INT12;
EINT;
}
interrupt void xint1_isr(void)
{
XIntruptRegs.XINT1CR.bit.ENABLE = 1; // 清除标志
PieCtrlRegs.PIEACK.all = PIEACK_GROUP12;
}
1.4.5. 中断优先级
优先级 |
CPU 中断 |
典型中断源 |
|---|---|---|
最高 |
INT1 |
PDPINTA, ADCINT, TINT0 |
↓ |
INT2~INT4 |
ePWM, eCAP |
↓ |
INT5~INT8 |
eQEP, SPI, I2C |
↓ |
INT9~INT11 |
SCI, CAN, CLA |
最低 |
INT12 |
XINT1~3, 保留 |
小技巧
电机控制中常见的中断优先级分配:
最高:故障捕获 (PDPINT) — 立即关 PWM
高:ePWM 中断 — 电流环 (10~20 kHz)
中:ADC 中断 — 采样完成
低:SCI/CAN 中断 — 通信
最低:CPU Timer — 后台任务