4. 外部中断控制LED
任务说明
本案例使用NXP S32K144开发板,通过按键触发外部中断,在中断服务函数中翻转LED的亮灭状态。需要完成以下目标:配置按键引脚为外部中断输入、编写中断服务函数实现LED翻转、设置中断优先级并验证中断响应。
硬件连接
- 按键K1连接PTA0引脚(低电平有效,按下为低电平)
- LED0连接PTD15引脚(高电平点亮)
- LED1连接PTD16引脚(高电平点亮)
代码实现
本案例使用S32K144的GPIO外部中断功能。PTA0配置为下降沿触发的外部中断输入,PTD15和PTD16配置为GPIO输出控制LED。中断服务函数中翻转两个LED的状态,实现按键按下时LED交替亮灭。
/* external_interrupt_led.c */
#include "S32K144.h"
/* LED引脚定义 */
#define LED0_PIN 15u /* PTD15 */
#define LED1_PIN 16u /* PTD16 */
#define KEY_PIN 0u /* PTA0 */
/* 中断优先级定义 */
#define KEY_ISR_PRIORITY 5u
/* 函数声明 */
void PORT_IRQHandler(void);
void delay_cycles(volatile unsigned int count);
/* 初始化LED引脚 */
void LED_Init(void)
{
/* 使能PORTD时钟 */
PCC->PCCn[PCC_PORTD_INDEX] = PCC_PCCn_CGC_MASK;
/* 配置PTD15和PTD16为GPIO输出 */
PORTD->PCR[LED0_PIN] = PORT_PCR_MUX(1u); /* 复用为GPIO */
PORTD->PCR[LED1_PIN] = PORT_PCR_MUX(1u);
PTD->PDDR |= (1u << LED0_PIN) | (1u << LED1_PIN); /* 设为输出 */
PTD->PDOR |= (1u << LED0_PIN) | (1u << LED1_PIN); /* 初始熄灭 */
}
/* 初始化按键外部中断 */
void KEY_EXTI_Init(void)
{
/* 使能PORTA时钟 */
PCC->PCCn[PCC_PORTA_INDEX] = PCC_PCCn_CGC_MASK;
/* 配置PTA0为GPIO输入,使能内部上拉 */
PORTA->PCR[KEY_PIN] = PORT_PCR_MUX(1u) | /* 复用为GPIO */
PORT_PCR_PE_MASK | /* 使能上拉/下拉 */
PORT_PCR_PS_MASK | /* 选择上拉 */
PORT_PCR_IRQC(0xAu); /* 下降沿触发中断 */
PTA->PDDR &= ~(1u << KEY_PIN); /* 设为输入 */
/* 设置中断优先级 */
NVIC_SetPriority(PORTA_IRQn, KEY_ISR_PRIORITY);
/* 使能PORTA中断 */
NVIC_EnableIRQ(PORTA_IRQn);
}
/* PORTA中断服务函数 */
void PORTA_IRQHandler(void)
{
/* 检查PTA0是否触发中断 */
if (PORTA->ISFR & (1u << KEY_PIN))
{
/* 翻转LED0和LED1状态 */
PTD->PTOR = (1u << LED0_PIN) | (1u << LED1_PIN);
/* 清除中断标志 */
PORTA->ISFR = (1u << KEY_PIN);
}
}
/* 简单延时函数 */
void delay_cycles(volatile unsigned int count)
{
while (count--)
{
__NOP();
}
}
/* 主函数 */
int main(void)
{
/* 初始化系统时钟 */
WDOG->CNT = 0xD928C520u; /* 解锁看门狗 */
WDOG->TOVAL = 0x0000FFFFu;
WDOG->CS = 0x00002100u; /* 禁用看门狗 */
/* 初始化外设 */
LED_Init();
KEY_EXTI_Init();
while (1)
{
/* 主循环空操作,等待中断 */
__WFI();
}
}
代码说明
- LED_Init():使能PORTD时钟,配置PTD15和PTD16为GPIO输出模式,初始状态为高电平(LED熄灭)
- KEY_EXTI_Init():使能PORTA时钟,配置PTA0为GPIO输入并启用内部上拉电阻,设置下降沿触发外部中断,配置中断优先级为5
- PORTA_IRQHandler():中断服务函数,检测到PTA0中断标志后,通过PTOR寄存器翻转两个LED的输出状态,然后清除中断标志
- NVIC_SetPriority():设置PORTA中断优先级为5(数值越小优先级越高,S32K144支持0-15级)
编译与烧录
- 在S32 Design Studio中创建新工程,选择S32K144芯片型号
- 将上述代码复制到main.c文件中
- 编译工程生成.elf或.hex文件
- 使用S32K144EVB-Q100开发板,通过OpenSDA调试器连接USB口
- 将生成的elf文件烧录到开发板
验证方法
完成烧录后,按下按键K1,观察LED0和LED1的状态变化:
- 初始状态:LED0和LED1均熄灭
- 第一次按下按键:LED0和LED1同时点亮
- 第二次按下按键:LED0和LED1同时熄灭
- 后续每次按下按键,LED状态都会翻转
判定标准:每次按下按键,两个LED的状态同步翻转,说明外部中断触发正常,中断服务函数正确执行了LED翻转操作。若LED状态不变化,检查按键连接和引脚配置是否正确。
中断优先级说明
本案例将PORTA中断优先级设置为5。S32K144的NVIC支持0~15级优先级,数值越小优先级越高。若系统中存在多个中断源,可通过修改KEY_ISR_PRIORITY宏定义的值来调整按键中断的抢占优先级。例如设置为0则按键中断具有最高优先级,可以抢占其他低优先级中断。