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)在文中添加相应代码 三…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...
数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !
我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...
