STM32——外部中断按键控制led

一、项目说明

本实验使用 STM32F103 外部中断(EXTI) 实现:按键 / 震动传感器触发外部中断 → 进入中断服务函数 → LED 亮 1 秒后自动熄灭

之前我写的按键控制led是轮询方式,相比轮询方式,中断方式不占用 CPU 资源、响应速度更快、程序效率更高,是 STM32 开发必备核心技能。

二、硬件连接

  • 按键PA0(外部中断输入引脚)
  • LEDPA1(推挽输出控制)
  • 共地 GND

三、完整代码

1. 整体工作流程

  1. 系统上电,初始化 LED、外部中断
  2. 主循环空跑,CPU 等待中断
  3. 按键 → PA0 从高电平变为低电平
  4. 产生下降沿信号 → 触发 EXTI0 外部中断
  5. CPU 暂停主程序,自动进入 EXTI0_IRQHandler
  6. LED 亮 1 秒 → 熄灭
  7. 清除中断标志,返回主循环继续等待

2.main.c 主程序文件

复制代码
// 包含STM32标准库底层驱动
#include "stm32f10x.h"
// 主头文件
#include "main.h"
// LED驱动头文件
#include "led.h"
// 震动/按键外部中断驱动头文件
#include "shake.h"

/**
  * @brief  毫秒级软件延时函数
  * @param  time: 延时时间,单位约1ms
  * @retval 无
  */
void delay(uint16_t time)
{
	uint16_t i = 0;
	while(time --)  // 循环time次
	{
		i = 12000;   // 内层循环,控制单次延时长度
		while(i --);
	}
}

/**
  * @brief  主函数
  * @retval int
  */
int main()
{
    // 【重要】设置中断分组:2位抢占优先级 + 2位子优先级
    // 整个工程只需要配置一次
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	LED_Init();        // 初始化LED引脚 PA1
	Shake_Init();      // 初始化外部中断引脚 PA0
	
	GPIO_SetBits( GPIOA,  GPIO_Pin_1);  // 默认LED熄灭(高电平)
	
	while(1)  // 主循环死循环
	{
		// 主循环空跑,所有逻辑交给中断处理
	}
}

/**
  * @brief  外部中断0服务函数
  * @note   函数名固定,不能修改
  * @retval 无
  */
void EXTI0_IRQHandler()
{
    // 判断:是否是EXTI_Line0触发的中断
	if(EXTI_GetITStatus(EXTI_Line0) != RESET )
	{
		GPIO_ResetBits(GPIOA,GPIO_Pin_1);  // 点亮LED(低电平有效)
		delay(1000);                       // 保持亮1秒
		GPIO_SetBits( GPIOA,  GPIO_Pin_1); // 熄灭LED
		
		EXTI_ClearITPendingBit(EXTI_Line0); // 【必须】清除中断标志位
	}
}

(1) 中断分组

复制代码
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  • 整个工程只配置一次
  • 决定中断优先级分配规则:2 位抢占、2 位子优先级

(2) 主循环空跑

复制代码
while(1){}
  • 不用轮询检测按键
  • 效率极高,CPU 资源完全释放

(3) 中断服务函数

复制代码
void EXTI0_IRQHandler()
  • 函数名固定,不能自定义
  • 中断触发后自动执行
  • 必须清除中断标志位,否则会反复进入中断

3.shake.c 外部中断初始化文件

复制代码
#include "shake.h"
// 包含STM32标准库
#include "stm32f10x.h"

/**
  * @brief  按键/震动传感器外部中断初始化
  * @param  无
  * @retval 无
  */
void Shake_Init(void)
{
    // 定义结构体变量
	GPIO_InitTypeDef GPIO_Initstruct;  	// GPIO配置结构体
	EXTI_InitTypeDef EXTIInitstruct;    // 外部中断配置结构体
	NVIC_InitTypeDef NVICInitstruct;    // 中断优先级配置结构体
	
	// 【重要】开启GPIOA时钟 + AFIO复用功能时钟
	// 使用外部中断必须开启AFIO
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
	
	// 配置PA0为上拉输入模式(按键/震动传感器输入)
	GPIO_Initstruct.GPIO_Pin = GPIO_Pin_0;
	GPIO_Initstruct.GPIO_Mode = GPIO_Mode_IPU;  // 上拉输入,默认高电平
	
	GPIO_Init(GPIOA, &GPIO_Initstruct);  // 初始化GPIO
	
	// 【重映射】将PA0映射到EXTI0中断线
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
	
	// 配置EXTI外部中断
	EXTIInitstruct.EXTI_Line = EXTI_Line0;                    // 中断线0
	EXTIInitstruct.EXTI_Mode = EXTI_Mode_Interrupt;           // 中断模式
	EXTIInitstruct.EXTI_Trigger = EXTI_Trigger_Falling;        // 下降沿触发
	EXTIInitstruct.EXTI_LineCmd = ENABLE;                     // 使能中断线
	
	EXTI_Init(&EXTIInitstruct);  // 应用配置
	
	// 配置NVIC中断控制器
	NVICInitstruct.NVIC_IRQChannel = EXTI0_IRQn;              // 选择EXTI0中断通道
	NVICInitstruct.NVIC_IRQChannelPreemptionPriority = 0;     // 抢占优先级0(最高)
	NVICInitstruct.NVIC_IRQChannelSubPriority = 0;            // 子优先级0
	NVICInitstruct.NVIC_IRQChannelCmd = ENABLE;               // 使能中断通道
	
	NVIC_Init(&NVICInitstruct);  // 应用配置
}

(1) 必须开启 AFIO 时钟

复制代码
RCC_APB2PeriphClockCmd(... | RCC_APB2Periph_AFIO, ENABLE);

使用外部中断,必须开启 AFIO,否则中断不生效!

(2) GPIO 上拉输入

复制代码
GPIO_Mode_IPU
  • 默认高电平
  • 按键按下 / 震动触发 → 变为低电平

(3) 中断线重映射

复制代码
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);

PA0EXTI0 绑定。

(4) 下降沿触发

复制代码
EXTI_Trigger_Falling

高电平 → 低电平瞬间触发中断。

(5) NVIC 开启中断通道

不配置 NVIC,中断永远无法响应。

四、必记的 3 个 "坑"

  1. 千万别忘开 AFIO 时钟!------ 这是最容易犯的错,没开这个,不管中断配置得多对,都不会触发(相当于门铃没装电池);
  2. 中断分组只配置一次!------ 咱们代码里放在 main 函数最开头,整个工程只写一次,多写会导致中断紊乱(相当于给门铃定了多个规则,单片机 confusion 了);
  3. 中断服务函数名不能乱改!------ EXTI0_IRQHandler() 是固定名字,改了单片机就找不到 "处理门铃的地方",中断触发了也没反应。
相关推荐
周洲08308 小时前
STM32 最简工程搭建|标准库/HAL库规范化模板,零冗余可直接落地
stm32·单片机·嵌入式硬件
ACP广源盛139246256739 小时前
M6/M5 Pro Mac mini 端侧 AI 落地@ACP#YLB3116 中端多盘存储扩展在 AI 服务中的机会与应用场景
大数据·网络·数据库·人工智能·嵌入式硬件·macos
ACP广源盛139246256739 小时前
M6/M5 Pro Mac mini 端侧 AI 新形态@ACP#GSV5800 Serdes 长距离视频传输在 AI 服务中的机会与落地场景
大数据·网络·数据库·人工智能·嵌入式硬件·macos·音视频
OIDCAT11 小时前
国产USB转千兆网卡芯片CH398-RTL8153国产替代实测与选型
网络·嵌入式硬件·智能硬件·国产芯片·usb转千兆网卡
HRTOS12 小时前
HRTOS 4.0 驱动库:06_Storage 存储设备驱动——24C02 EEPROM与I²C驱动开发
c语言·驱动开发·嵌入式硬件·51单片机
周洲083012 小时前
STM32 串口不定长接收|空闲中断 IDLE 方案,无固定帧长限制,项目实战
stm32·单片机·嵌入式硬件
我和头发拼了14 小时前
STM32--10硬件读写MPU6050
stm32·单片机·嵌入式硬件
糖糖单片机设计16 小时前
基于STM32的鱼缸水质检测系统
stm32·单片机·嵌入式硬件
HRTOS16 小时前
HRTOS 4.0 正式发布:Driver Library 基础外设驱动模块介绍
驱动开发·单片机·嵌入式硬件·51单片机
染予16 小时前
20个点位下发该如何正常操作?
单片机·嵌入式硬件