使用S™ 32设置GPIO中断
中断示例
设计一个按键中断的实例。设置两个中断:EXTI0、EXTI9,
在EXTI9的中断服务之程序中实现LED灯的控制
按键中断实例设计:EXTI0和EXTI9
根据提供的电路图,我将设计一个基于STM32的按键中断系统,其中两个按键分别连接到EXTI0和EXTI9引脚,并通过EXTI9的中断服务程序控制LED灯组。
硬件连接分析
从电路图可以看出:
- 两个按键
Key Button
和Wakeup Button
通过上拉/下拉电阻连接到微控制器 - EXTI0连接到第一个按键输入
- EXTI9连接到第二个按键输入
- 四个LED灯(带限流电阻)连接到微控制器的GPIO引脚
STM32代码实现
#include "stm32f10x.h" // 假设使用STM32F10x系列,可根据实际芯片修改
// LED相关定义
#define LED_PORT GPIOB
#define LED_PIN_ALL (GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11)
#define LED_ALL_ON() GPIO_SetBits(LED_PORT, LED_PIN_ALL)
#define LED_ALL_OFF() GPIO_ResetBits(LED_PORT, LED_PIN_ALL)
// 按键相关定义
#define KEY0_PORT GPIOA
#define KEY0_PIN GPIO_Pin_0 // EXTI0对应PA0
#define KEY1_PORT GPIOA
#define KEY1_PIN GPIO_Pin_9 // EXTI9对应PA9
// 中断标志位
volatile uint8_t Key0Pressed = 0;
volatile uint8_t Key1Pressed = 0;
// LED状态变量
volatile uint8_t ledState = 0; // 0:全灭, 1:交替闪烁, 2:全部点亮
/*
* 函数名:EXTI0_IRQHandler
* 描述:EXTI0中断服务程序
* 输入:无
* 输出:无
*/
外部中断函数EXTI0_IRQHandler
void EXTI0_IRQHandler(void)
{
// 检查是否是KEY0触发的中断
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{
// 清除中断标志位
EXTI_ClearITPendingBit(EXTI_Line0);
// 设置按键0被按下的标志
Key0Pressed = 1;
}
}
/*
* 函数名:EXTI9_5_IRQHandler
* 描述:EXTI9-5中断服务程序
* 输入:无
* 输出:无
*/
EXTI9-5中断服务程序
EXTI9中断服务程序中实现了三种LED控制模式
void EXTI9_5_IRQHandler(void)
{
// 检查是否是KEY1触发的中断
if(EXTI_GetITStatus(EXTI_Line9) != RESET)
{
// 清除中断标志位
EXTI_ClearITPendingBit(EXTI_Line9);
// 设置按键1被按下的标志
Key1Pressed = 1;
// 控制LED灯
switch(ledState)
{
case 0: // 全灭
LED_ALL_ON();
ledState = 1;
break;
case 1: // 全部点亮
LED_ALL_OFF();
ledState = 2;
break;
case 2: // 交替闪烁模式
GPIO_Write(LED_PORT, (GPIO_ReadOutputData(LED_PORT) ^ LED_PIN_ALL));
break;
}
}
}
/*
* 函数名:KEY_Init
* 描述:初始化按键GPIO和中断
* 输入:无
* 输出:无
*/
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 配置KEY0和KEY1为浮空输入
GPIO_InitStructure.GPIO_Pin = KEY0_PIN | KEY1_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY0_PORT, &GPIO_InitStructure);
// 使能AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
// 配置KEY0为EXTI0中断线
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
配置EXIT线
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
// 配置KEY1为EXTI9中断线
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource9);
EXTI_InitStructure.EXTI_Line = EXTI_Line9;
EXTI_Init(&EXTI_InitStructure);
// 配置NVIC中断优先级
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_Init(&NVIC_InitStructure);
}
/*
* 函数名:LED_Init
* 描述:初始化LED GPIO
* 输入:无
* 输出:无
*/
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 使能GPIOB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// 配置LED端口为推挽输出
GPIO_InitStructure.GPIO_Pin = LED_PIN_ALL;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LED_PORT, &GPIO_InitStructure);
// 初始状态:全灭
LED_ALL_OFF();
}
int main(void)
{
// 初始化按键和LED
KEY_Init();
LED_Init();
while(1)
{
// 检查KEY0是否被按下
if(Key0Pressed)
{
// 短暂延时,消除抖动
for(volatile uint32_t i = 0; i < 10000; i++);
// 处理按键事件
// 这里可以添加其他功能
// 清除标志位
Key0Pressed = 0;
}
// 检查KEY1是否被按下
if(Key1Pressed)
{
// 短暂延时,消除抖动
for(volatile uint32_t i = 0; i < 10000; i++);
// 清除标志位
Key1Pressed = 0;
}
// 可以在这里添加其他主循环逻辑
}
}
代码说明
硬件配置:
- EXTI0连接到PA0引脚
- EXTI9连接到PA9引脚
- 四个LED灯连接到PB8-PB11引脚
中断配置:
- EXTI0和EXTI9均配置为下降沿触发
- 为两个中断分配了相同的优先级
LED控制:
- EXTI9中断服务程序中实现了三种LED控制模式:
- 全灭 → 全部点亮 → 交替闪烁
- 使用ledState变量跟踪当前LED状态
- EXTI9中断服务程序中实现了三种LED控制模式:
按键消抖:
- 在主循环中通过延时实现简单的按键消抖
中断标志位:
- 使用Key0Pressed和Key1Pressed变量作为中断标志位
这个设计实现了按键检测和LED控制的基本功能,可以根据实际需求进一步扩展和优化。