DSP实战TMS320F28035:按键外部中断控制LED翻转
必备头文件,包含DSP28x的所有寄存器定义、专用数据类型(如Uint16、Uint32)、基础初始化函数,没有它,代码无法识别DSP的寄存器。宏定义:给引脚、电平起别名,比如用LED_PIN代替34,后续修改引脚时,只需改宏定义,无需全局修改代码。本文通过讲解了GPIO配置、外部中断(XINT1)、PIE中断控制器的用法,核心要点可总结为:1. GPIO配置:MUX(复用)、DIR(方向)、PU
资源链接:
1、tms320f28035中文数据手册.pdf
链接:https://pan.baidu.com/s/1trMohQQ9fIfC1h0yreU4Gg?pwd=1234 提取码: 1234
2、完整工程文件:Example_2803xGpioToggle (3).zip
链接:
https://pan.baidu.com/s/1-cyXah8psh8Q_r-Zt__PHA?pwd=1234 提取码: 1234
搭建环境:
1、硬件环境:DSP TMS320F28035 开发板

2、软件环境:基于CCS20.2.0开发
一、目标
硬件:按键(GPIO27)、LED(GPIO34),共地按键,共阴极LED。
功能:按下按键,触发外部中断XINT1,经过消抖处理后,翻转LED的亮灭状态;松开按键后,等待下一次触发,主循环不占用资源。
二、完整代码(可直接复制使用)
#include "DSP28x_Project.h" // 引用头文件
// 引脚定义
#define LED_PIN 34 // LED引脚(GPB组)
#define KEY_PIN 27 // 按键引脚(GPA组,GPIO12支持外部中断XINT1)
#define LED_ON 1 // 1=拉高点亮(根据LED类型调整)
#define KEY_PRESS 0 // 按键按下为低电平(共地按键)
// 全局变量:用于按键消抖
volatile Uint16 key_int_flag = 0; // 按键中断标志
volatile Uint32 key_debounce_cnt = 0; // 消抖计数器
// 函数前置声明
interrupt void xint1_isr(void); // 外部中断1服务函数
void LED_Init(void); // LED初始化
void KEY_Init(void); // 按键中断初始化
void DelayUs(Uint32 us); // 微秒级延时(消抖用)
// LED初始化函数
void LED_Init(void)
{
EALLOW;
// 配置GPIO34为普通GPIO输出
GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 0; // 普通GPIO模式
GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1; // 输出模式
GpioCtrlRegs.GPBPUD.bit.GPIO34 = 1; // 禁用上拉
EDIS;
// LED初始状态
if(LED_ON == 0){
GpioDataRegs.GPBCLEAR.bit.GPIO34 = 1;
}else{
GpioDataRegs.GPBSET.bit.GPIO34 = 1;
}
}
// 按键+外部中断初始化(核心:配置XINT1)
void KEY_Init(void)
{
EALLOW;
// 1. 配置GPIO12为普通GPIO输入
GpioCtrlRegs.GPAMUX2.bit.GPIO27 = 1; // 普通GPIO模式
GpioCtrlRegs.GPADIR.bit.GPIO27 = 0; // 输入模式
GpioCtrlRegs.GPAPUD.bit.GPIO27 = 0; // 使能内部上拉(按键松开为高电平)
// 2. 映射GPIO12到外部中断XINT1
GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL = KEY_PIN; // GPIO12关联XINT1
// 3. 配置XINT1中断触发方式(下降沿触发:按键按下)
XIntruptRegs.XINT1CR.bit.POLARITY = 0; // 0=下降沿触发,1=上升沿触发,2=双边沿
// 4. 配置PIE中断控制器
PieVectTable.XINT1 = &xint1_isr; // 映射XINT1中断服务函数
EDIS;
// 5. 使能各级中断
XIntruptRegs.XINT1CR.bit.ENABLE = 1; // 使能XINT1中断
PieCtrlRegs.PIEIER1.bit.INTx4 = 1; // 使能PIE组1的4号中断(XINT1)
IER |= M_INT1; // 使能CPU级的INT1中断
EINT; // 使能全局中断
ERTM; // 使能实时模式中断
}
// 微秒级延时(消抖用,60MHz主频)
void DelayUs(Uint32 us)
{
Uint32 i;
for(; us>0; us--)
{
for(i=0; i<60; i++); // 60个指令周期≈1us(60MHz主频)
}
}
// 外部中断1服务函数(按键中断处理)
interrupt void xint1_isr(void)
{
// 1. 清除中断标志(必须)
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // 清除PIE组1中断挂起标志
XIntruptRegs.XINT1CR.bit.ENABLE = 0; // 暂时关闭中断,防止重复触发
// 2. 按键消抖(延时10ms)
DelayUs(10000);
// 3. 确认按键确实按下
if(GpioDataRegs.GPADAT.bit.GPIO27 == KEY_PRESS)
{
GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1; // 翻转LED电平
}
// 4. 延时后重新使能中断(防止松手抖动触发)
DelayUs(10000);
XIntruptRegs.XINT1CR.bit.ENABLE = 1; // 重新使能XINT1中断
}
void main(void)
{
// 系统初始化
InitSysCtrl(); // 关闭看门狗+配置系统时钟(60MHz)
DINT; // 关闭全局中断
InitPieCtrl(); // 初始化PIE控制器
IER = 0x0000; // 清除CPU中断使能
IFR = 0x0000; // 清除CPU中断标志
InitPieVectTable(); // 初始化PIE中断向量表
// 外设初始化
LED_Init(); // LED初始化
KEY_Init(); // 按键+外部中断初始化
// 主循环
while(1)
{
}
}
三、核心模块拆解
1. 头文件与宏定义
#include "DSP28x_Project.h":必备头文件,包含DSP28x的所有寄存器定义、专用数据类型(如Uint16、Uint32)、基础初始化函数,没有它,代码无法识别DSP的寄存器。
宏定义:给引脚、电平起别名,比如用LED_PIN代替34,后续修改引脚时,只需改宏定义,无需全局修改代码。
2. 全局变量
重点关注 volatile 关键字——它告诉编译器“这个变量可能被中断修改”,禁止编译器优化,否则中断修改后主程序读不到最新值,会导致程序异常。
3. GPIO配置
DSP的GPIO配置有3个核心参数,无论配置输入还是输出,都要设置这3点:
-
MUX:复用模式,0=普通GPIO,非0=映射到外设(如中断、PWM); -
DIR:方向,1=输出(LED),0=输入(按键); -
PUD:上拉电阻,0=使能(输入引脚常用,保证电平稳定),1=禁用(输出引脚无需)。
另外,EALLOW/EDIS 是DSP的寄存器保护机制,配置关键寄存器(如GPIO、中断)时,必须先解锁(EALLOW),配置完成后加锁(EDIS),防止误操作。
4. 中断配置
DSP的外部中断(如XINT1)配置,必须遵循“3步走”:
-
GPIO映射:将按键引脚(GPIO27)绑定到外部中断XINT1(通过
GPIOXINT1SEL寄存器);
-
触发方式:设置中断触发边沿(下降沿、上升沿、双边沿),本文用下降沿(按键按下时触发);

-
三级使能:外设中断(XINT1)→ PIE中断(组1)→ CPU全局中断,只有三级都使能,中断才能正常触发。
5. 中断服务函数
中断服务函数有4个关键步骤:
-
清除中断标志:必须先清除,否则DSP会一直认为中断未处理,重复触发;
-
关闭中断+消抖:按键按下会有10ms左右的电平抖动,延时10ms后再读电平,避免误触发;
-
确认按键状态:消抖后再次读取按键电平,确认是真按下,再执行LED翻转操作;
-
重新使能中断:消抖完成后,重新开启中断,等待下一次按键触发。
四、总结
本文通过讲解了GPIO配置、外部中断(XINT1)、PIE中断控制器的用法,核心要点可总结为:
1. GPIO配置:MUX(复用)、DIR(方向)、PUD(上拉)是基础,EALLOW/EDIS是保护;
2. 中断配置:GPIO映射→触发方式→三级使能,三步缺一不可;
3. 中断服务:清标志→消抖→执行功能→重新使能,避免误触发。
如果遇到问题,欢迎在评论区留言,一起交流学习!
更多推荐



所有评论(0)