STM32入门学习之外部中断
1.STM32的IO口可以作为外部中断输入口。本文通过按键按下作为外部中断的输入,点亮LED灯。在STM32的19个外部中断中,0-15为外部IO口的中断输入口。STM32的引脚分别对应着0-15的外部中断线。比如,外部中断线0对应着GPIOA.0-GPIOG.0,以此类推就可以将所以的IO映射到0-15个外部中断线上。STM32的IO的外部中断映射图如下:

2.外部中断的配置步骤:
(1)将IO口映射到对应的外部中断线上,中断线河中断初始化。
(2)配置外部中断,即配置中断管理NVIC。
(3)重写中断服务函数,即中断回调函数。这些中断回调函数在startup_stm32f10x_xx.s中被规定好了名称,我们只需要重写对应的中断回调函数即可。
3.工程代码:
delay.h:
#ifndef __DELAY_H
#define __DELAY_H#include "stm32f10x.h"void delay_us(uint32_t us); //ÑÓʱ΢Ãë
void delay_ms(uint32_t ms); //ÑÓʱºÁÃë#endif
delay.c:
#include "delay.h"void delay_us(uint32_t us)
{uint32_t i;//1.Ñ¡ÔñHCLKʱÖÓ£¬²¢ÉèÖõδðʱÖÓ¼ÆÊýÖµSysTick_Config(72);for(i = 0;i < us;i++){while(!((SysTick->CTRL) & (1 << 16))); //µÈ´ý¼ÆÊýÍê³É}SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //Ñ¡ÔñSTCLKʱÖÓÔ´£¬²¢Ê§Äܶ¨Ê±Æ÷
}void delay_ms(uint32_t ms)
{uint32_t i;//1.Ñ¡ÔñHCLKʱÖÓÔ´£¬²¢ÉèÖõδðʱÖÓ¼ÆÊýÖµSysTick_Config(72000);for(i = 0;i < ms;i++){while(!((SysTick->CTRL) & (1 << 16))); //µÈ´ý¼ÆÊýÍê³É}SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //Ñ¡ÔñSTCLKʱÖÓÔ´£¬²¢Ê§Äܶ¨Ê±Æ÷
}
key.h:
#ifndef __KEY_H
#define __KEY_H#include "stm32f10x.h"#define KEY_0 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5) //¶ÁÈ¡°´¼üµÄ״̬
#define KEY_1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)
#define KEY_2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)void KEY_Init(void);
void KEY_Scan(void); //°´¼üɨÃ躯Êý#endif
key.c:
#include "key.h"
#include "delay.h"
#include "led.h"void KEY_Init(void)
{/*1.¶¨ÒåÒý½ÅµÄ½á¹¹Ìå¡£2.ʹÄÜÒý½Å¶ÔÓ¦µÄʱÖÓ¡£3.ÅäÖÃÒý½ÅÐÅÏ¢*///¶¨ÒåÒý½Å½á¹¹Ì壺GPIO_InitTypeDef GPIO_InitStruct;//ʹÄÜʱÖÓ£ºRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC,ENABLE);//ÅäÖÃÒý½ÅÐÅÏ¢(KEY0)£ºGPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOC,&GPIO_InitStruct);//ÅäÖÃKEY1£ºGPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; //ÉèÖóÉÉÏÀÊäÈëGPIO_Init(GPIOA,&GPIO_InitStruct);//ÅäÖð´¼üWK_UP:GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;GPIO_Init(GPIOA,&GPIO_InitStruct);LED_Init(); //³õʼ»¯LED
}void KEY_Scan(void)
{static u8 key_up = 1; //°´¼üËÉ¿ª±ê־λif(key_up && (KEY_0 == 0|| KEY_1 == 0|| KEY_1 == 1)){delay_ms(10); //È¥¶¶¶¯key_up = 0;if(KEY_0 == 0){GPIO_ResetBits(GPIOD ,GPIO_Pin_2);GPIO_SetBits(GPIOA,GPIO_Pin_8);//delay_ms(1000);}else if(KEY_1 == 0){GPIO_ResetBits(GPIOA ,GPIO_Pin_8);GPIO_SetBits(GPIOD,GPIO_Pin_2);//delay_ms(1000);}else if(KEY_2 == 1){GPIO_ResetBits(GPIOA ,GPIO_Pin_8);GPIO_ResetBits(GPIOD ,GPIO_Pin_2);}}else if(KEY_0==1&&KEY_1==1&&KEY_2==0){key_up = 1;}
}
exti.h:
#ifndef __EXTI_H
#define __EXTI_H#include "stm32f10x.h"void EXTIx_Init(void);#endif
exti.c:
#include "exti.h"
#include "key.h"
#include "delay.h"void EXTIx_Init(void)
{/*ÍⲿÖжϵÄÅäÖ÷½·¨£º1.½«IO¿ÚÓ³Éäµ½¶ÔÓ¦ÍⲿÖжÏÏßÉÏ2.ÅäÖÃÍⲿÖжÏ3.ÖØÐ´ÖжϷþÎñº¯Êý£¬¼´Öжϻص÷º¯Êý*///¶¨ÒåÍⲿÖжϺÍÖжϵĽṹÌ壺EXTI_InitTypeDef EXTI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;//ʹÄÜʱÖÓ£ºRCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//ÍⲿÖжÏÐèÒª¸´ÓÃʱÖÓKEY_Init(); //³õʼ»¯°´¼ü//GPIOC.5µÄÖжÏÏߺÍÖжϳõʼ»¯ÅäÖãºGPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5); //GPIOÓëÖжÏÏß½øÐÐÓ³ÉäEXTI_InitStructure.EXTI_Line = EXTI_Line5;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;EXTI_Init(&EXTI_InitStructure);//½«ÉÏÃæÅäÖõÄÐÅϢдÈëEXTI¼Ä´æÆ÷ÖÐ//GPIOA.0µÄÖжÏÏߺÍÖжϳõʼ»¯ÅäÖãºGPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0); //GPIOÓëÖжÏÏß½øÐÐÓ³ÉäEXTI_InitStructure.EXTI_Line = EXTI_Line0;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;EXTI_Init(&EXTI_InitStructure);//GPIOA.15µÄÖжÏÏߺÍÖжϳõʼ»¯ÅäÖãºGPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15); //GPIOÓëÖжÏÏß½øÐÐÓ³ÉäEXTI_InitStructure.EXTI_Line = EXTI_Line15;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;EXTI_Init(&EXTI_InitStructure);//ÖжϹÜÀíÅäÖãºNVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_Init(&NVIC_InitStructure);
}//ÖØÐ´ÖжϷþÎñº¯Êý.
void EXTI0_IRQHandlÕâЩÖжϻص÷º¯ÊýÔÚstartup_stm32f10x_xx.sÖб»¹æ¶¨ºÃÁËÃû³Æer(void)
{//¾²Ì¬±äÁ¿Ö»»áÔÚµÚÒ»´ÎÔËÐÐʱ±»³õʼ»¯¡£ËùÒÔ£¬¿ÉÒÔÀí½âΪÕâÌõÓï¾äÖ»Ö´ÐÐÒ»´Îstatic u8 flag1 = 1; delay_ms(10); //Ïû¶¶if(KEY_2 == 1){if(flag1){//GPIO_ResetBits(GPIOD ,GPIO_Pin_2);GPIO_SetBits(GPIOA,GPIO_Pin_8);flag1 = !flag1;}else{GPIO_ResetBits(GPIOA ,GPIO_Pin_8);//GPIO_SetBits(GPIOD,GPIO_Pin_2);flag1 = !flag1;}}EXTI_ClearITPendingBit(EXTI_Line0);
}void EXTI9_5_IRQHandler(void)
{static u8 flag2 = 1;delay_ms(10); //Ïû¶¶if(KEY_0 == 0){if(flag2){//GPIO_ResetBits(GPIOA,GPIO_Pin_8);GPIO_SetBits(GPIOD,GPIO_Pin_2);flag2 = !flag2;}else{//GPIO_ResetBits(GPIOA,GPIO_Pin_8);GPIO_ResetBits(GPIOD,GPIO_Pin_2);flag2 = !flag2;}}EXTI_ClearITPendingBit(EXTI_Line5);
}void EXTI15_10_IRQHandler(void)
{static u8 flag3 = 1;delay_ms(10); //Ïû¶¶if(KEY_1 == 0){if(flag3){GPIO_ResetBits(GPIOA,GPIO_Pin_8);GPIO_ResetBits(GPIOD,GPIO_Pin_2);flag3 = !flag3;}else{GPIO_SetBits(GPIOA,GPIO_Pin_8);GPIO_SetBits(GPIOD,GPIO_Pin_2);flag3 = !flag3;}}EXTI_ClearITPendingBit(EXTI_Line15);
}
main.c:
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "exti.h"int main(void)
{//LED_Init();NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// ÉèÖÃÖжÏÓÅÏȼ¶·Ö×é2KEY_Init();EXTIx_Init();while(1){
// GPIO_ResetBits(GPIOD ,GPIO_Pin_2);
// GPIO_SetBits(GPIOA,GPIO_Pin_8);
// delay_ms(1000);
// GPIO_ResetBits(GPIOA ,GPIO_Pin_8);
// GPIO_SetBits(GPIOD,GPIO_Pin_2);
// delay_ms(1000);//KEY_Scan();}
}
4.运行结果:按下key0,LED1亮,再按一下熄灭。按下key1,LED0亮,再按一下熄灭。按下key3,两个LED亮,再按一下两个LED熄灭。




5.总结:本文是通过key的外部中断来控制led的亮灭。其原理是利用STM32的IO可作为外部中断的输入口。当按下key时,对应的IO空作为输入会触发外部中断,然后系统会去调用对应的外部中断服务函数。通过中断,可以不用阻塞程序,在中断未被触发时,程序可以去执行其他的工作,提高系统的效率。
在配置外部中断的相关信息时,主要是配置相关的结构体信息、将IO映射到对应的中断线、配置中断管理NVIC。
相关文章:
STM32入门学习之外部中断
1.STM32的IO口可以作为外部中断输入口。本文通过按键按下作为外部中断的输入,点亮LED灯。在STM32的19个外部中断中,0-15为外部IO口的中断输入口。STM32的引脚分别对应着0-15的外部中断线。比如,外部中断线0对应着GPIOA.0-GPIOG.0,…...
Jenkins 配置maven和jdk
前提:服务器已经安装maven和jdk 一、在Jenkins中添加全局变量 系统管理–>系统配置–>全局属性–>环境变量 添加三个全局变量 JAVA_HOME、MAVEN_HOME、PATH 二、配置maven 系统管理–>全局工具配置–>maven–>新增 新增配置 三、配置JDK 在系统管…...
Leetcode | Binary search | 22. 74. 162. 33. 34. 153.
22. Generate Parentheses 要意识到只要还有左括号,就可以放到path里。只要右括号数量小于左括号,也可以放进去。就是valid的组合。recurse两次 74. Search a 2D Matrix 看成sorted list就好。直接用m*n表示最后一位的index,并且每次只需要 …...
生命在于折腾——面试问题汇总
这里面的问题都是我参加面试时候遇到的问题,大家就这样看吧。 一、个人情况 1、自我介绍 2、为什么离开上一家公司 3、有没有参加过HVV 4、介绍一下上家公司的项目 5、小程序和公众号渗透测试做过么 6、实习工资多少 7、有挖过漏洞么 二、基础知识 1、信息收集的…...
<Java>Map<String,Object>中解析Object类型数据为数组格式
背景: 前端:入参为字符串和数组类型;通过json字符串传给后台, 后台:后台通过工具解析为Map<String,Object>,然后需要解析出Map里面的数组值做操作; 需求: 入参&…...
别再分库分表了,试试TiDB!
什么是NewSQL 传统SQL的问题 升级服务器硬件 数据分片 NoSQL 的问题 优点 缺点 NewSQL 特性 NewSQL 的主要特性 三种SQL的对比 TiDB怎么来的 TiDB社区版和企业版 TIDB核心特性 水平弹性扩展 分布式事务支持 金融级高可用 实时 HTAP 云原生的分布式数据库 高度兼…...
Java进阶之Dump文件初体验
视频地址:https://www.bilibili.com/video/BV1Ak4y137oh 学习文章:https://d9bp4nr5ye.feishu.cn/wiki/VQoAwlzrXiLFZekuLIyc1uK5nqc 最近线上频繁的内存告警,同事A通过分析dump文件解决了这个问题,我当然是不会放过这种学习的机…...
基于扩展(EKF)和无迹卡尔曼滤波(UKF)的电力系统动态状态估计(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
曲线拟合(MATLAB拟合工具箱)位置前馈量计算(压力闭环控制应用)
利用PLC进行压力闭环控制的项目背景介绍请查看下面文章链接,这里不再赘述。 信捷PLC压力闭环控制应用(C语言完整PD、PID源代码)_RXXW_Dor的博客-CSDN博客闭环控制的系列文章,可以查看PID专栏的的系列文章,链接如下:张力控制之速度闭环(速度前馈量计算)_RXXW_Dor的博客-CSD…...
小程序使用echarts
参考文档:echarts官网、echarts-for-weixin 第一步引入组件库,可直接从echarts-for-weixin下载,也可以从echarts官网自定义生成,这里我们就不贴了组件库引入好后,就是页面引用啦,废话不多说,直…...
面向对象——封装
C面向对象的三大特性为:封装、继承、多态 C认为万事万物都皆为对象,对象上有其属性和行为 例如: 人可以作为对象,属性有姓名、年龄、身高、体重…,行为有走、跑、跳、吃饭、唱歌… 车也可以作为对象…...
【LeetCode】160.相交链表
题目 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 图示两个链表在节点 c1 开始相交: 题目数据 保证 整个链式结构中不存在环。 注意,函数返回结…...
【JWT的使用】
文章目录 前言1、用户登录1.1 JWTThreadLocal 2.1 代码实现2.1.1 ThreadLocal工具类2.2.2 定义拦截器2.2.3 注册拦截器 前言 1、用户登录 1.1 JWT JSON Web Token简称JWT,用于对应用程序上用户进行身份验证的标记。使用 JWTS 之后不需要保存用户的 cookie 或其他…...
Python获取音视频时长
Python获取音视频时长 Python获取音视频时长1、安装插件2、获取音视频时长.py3、打包exe4、下载地址 Python获取音视频时长 1、安装插件 pip install moviepy -i https://pypi.tuna.tsinghua.edu.cn/simple2、获取音视频时长.py 上代码:获取音视频时长.py # -*-…...
TCP四次握手为什么客户端等待的时间是2MSL
目录 什么是MSL从第三次握手开始分析总结 什么是MSL MSL是Maximum Segment Lifetime英文的缩写,中文可以译为“报文最大生存时间”,他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。 从第三次握手开始分析 第三次握手服务端…...
Android Studio 启用设备远程调试配置完整步聚
启用手机设置->开发者选项-无线调试,然后选择允许 已启用后无线调试变成绿色 ,点击无线调试进入详情页面 点击Android Studio的Device Manager 下的WIFI图标 会弹出下图窗口 打开手机的开发者选项中的WIFI调试(无线调试)下的使用二维码配对设备进行扫描. 设备配对成功后手机…...
玩转LaTeX(三)【数学公式(基础)、矩阵、多行公式】
数学公式基础 导言区(引包) \usepackage{amsmath} %带星号的eqution 正文区 \begin{document}%数学公式初步 \section{简介} \LaTeX{}将排版内容分为文本模式和数学模式。文本模式用于普通文本排版,数学模式用于数学公式排版。 …...
jenkins 配置git
在linux 中输入 保证git 安装成功 git --version使用查看git 安装目录(非源码安装直接用yum 安装的) which gitjenkins 中到 系统管理–>全局工具配置–> Git installations 新建一个项目 选择自由风格 源码管理选择 git 如果使用的是码云&a…...
单机部署MinIo并设置开机自启
MinIO 是高性能的对象存储,是为海量数据存储、人工智能、大数据分析而设计的,它完全兼容Amazon S3接口,单个对象最大可达5TB,适合存储海量图片、视频、日志文件、备份数据和容器/虚拟机镜像等。MinIO主要采用Golang语言实现&#…...
Latex | 使用MATLAB生成.eps矢量图并导入Latex中的方法
一、问题描述 用Latex时写paper时,要导入MATLAB生成的图进去 二、解决思路 (1)在MATLAB生成图片的窗口中,导出.eps矢量图 (2)把图上传到overleaf的目录 (3)在文中添加相应代码 三…...
到底什么是 AI 测试?AI 测试与传统测试的区别?
过去两年,AI已经从"加分项"变成了"必选项"。 不只是大厂,二线公司、甚至传统行业的测试团队都在要求:"能熟练使用AI工具提效"。 更关键的是,面试的玩法也变了。现在的技术面试早就跳出了 “考 AI 零…...
Logback 日志框架使用与配置指南
1. Logback 核心概念与架构 Logback 是 Java 生态中最主流的日志框架之一,其配置体系主要围绕以下三个核心概念展开: Logger(日志记录器):负责捕获日志事件。它通过 name 属性(通常是包名或类名)…...
2026央国企求职哪家强?TOP机构帮你稳住铁饭碗!
引言综述随着 2026 届超 1200 万毕业生涌入就业市场,央国企岗位竞争愈发激烈,岗位竞争比持续攀升。在这样的大环境下,求职者的核心需求集中在系统备考规划、精准岗位匹配以及高保障面试辅导上。本次测评旨在为求职者提供客观、专业的机构对比…...
终极指南:Visual C++运行库合集AIO - 一站式解决Windows程序依赖问题
终极指南:Visual C运行库合集AIO - 一站式解决Windows程序依赖问题 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经在运行某些软件或游戏时…...
2026年阿里云OpenClaw/Hermes Agent配置Token Plan部署一文读懂
2026年阿里云OpenClaw/Hermes Agent配置Token Plan部署一文读懂。OpenClaw是开源的个人AI助手,Hermes Agent则是一个能自我进化的AI智能体框架。阿里云提供计算巢、轻量服务器及无影云电脑三种部署OpenClaw 与 Hermes Agent的方案、百炼Token Plan兼容主流 AI 工具&…...
从开发者视角感受Taotoken官方价折扣带来的实际成本节省
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 从开发者视角感受Taotoken官方价折扣带来的实际成本节省 对于独立开发者和小型团队而言,在构建和迭代AI应用时…...
软件测试职业天花板真相:不是岗位不行,是你没找对方向
在软件行业高速发展的今天,打开任何一个技术论坛,总能刷到软件测试从业者的焦虑:“干了5年功能测试,薪资卡在15k再也上不去”“35岁还在写测试用例,是不是要被淘汰了”“AI都能自动生成测试脚本了,我们还有…...
3个步骤让你的Switch Joy-Con在Windows上焕发新生:JoyCon-Driver完全指南
3个步骤让你的Switch Joy-Con在Windows上焕发新生:JoyCon-Driver完全指南 【免费下载链接】JoyCon-Driver A vJoy feeder for the Nintendo Switch JoyCons and Pro Controller 项目地址: https://gitcode.com/gh_mirrors/jo/JoyCon-Driver 你是否曾想过让闲…...
机器学习博士生存指南:问题定义、三维技术栈与认知带宽管理
1. 这不是“读博指南”,而是一份机器学习方向博士生的生存手记 我带过7届硕士、指导过4位博士,自己也从MIT CSAIL实验室的PhD candidate一路走到现在,在工业界和学术界都完整跑过ML方向的闭环——从ICML投稿被拒5次到最终以共同作者身份参与N…...
Monk AI小样本分类实战:用几十张图快速构建可用AI模型
1. 项目概述:用 Monk AI 做分类,但只喂它一小块数据——这到底在解决什么问题?“Classification Using Monk AI by Using a Slice of the Dataset”这个标题乍看平平无奇,甚至有点拗口,但如果你在工业质检、医疗影像初…...
