STM32 外部中断详解(原理+配置代码)
本文介绍了STM32基于标准外设库的外部中断配置,以及基于参考手册如何更加寄存器配置外部中断
1 前言
打算写一下中断,又忍不住想说一下中断的概念,去书上翻一翻,或者自己在搜索引擎上搜一下,都可以找到一大堆,包括本文写的这个外部中断也不例外。如果要写光是中断就可以单独写一篇了,所以本文直入主题,对于STM32的外部中断进行详细的剖析。
2 STM32的外部中断
下图来自《STM32参考手册》,从整个架构图可以知道,外部中断的功能可以配置六个寄存器;
- 中断屏蔽寄存器(EXTI_IMR)
- 事件屏蔽寄存器(EXTI_EMR)
- 上升沿触发选择寄存器(EXTI_RTSR)
- 下降沿触发选择寄存器(EXTI_FTSR)
- 软件中断事件寄存器(EXTI_SWIER)
- 挂起寄存器(EXTI_PR)

EXTI支持配置20个中断和事件屏蔽位; - GPIO端口以下图的方式连接到16个外部中断/事件线上;
EXTI_Line0—EXTI_Line15; - EXTI_Line16 连接到PVD输出 ;
- EXTI_Line17连接到RTC闹钟事件;
- EXTI_Line18连接到USB唤醒事件;
- EXTI_Line19连接到以太网唤醒事件(只适用于互联型产品);
GPIO的映射关系图如下所示;

3 中断服务函数的映射关系
| GPIO | IRQn | IRQHandler |
|---|---|---|
| GPIO_Pin0 | EXTI0_IRQn | EXTI0_IRQHandler |
| GPIO_Pin1 | EXTI1_IRQn | EXTI1_IRQHandler |
| GPIO_Pin2 | EXTI2_IRQn | EXTI2_IRQHandler |
| GPIO_Pin3 | EXTI3_IRQn | EXTI3_IRQHandler |
| GPIO_Pin4 | EXTI4_IRQn | EXTI4_IRQHandler |
| GPIO_Pin5 — GPIO_Pin9 | EXTI9_5_IRQn | EXTI9_5_IRQHandler |
| GPIO_Pin10 — GPIO_Pin15 | EXTI15_10_IRQn | EXTI15_10_IRQHandler |
4 外部中断的配置
宏定义,抽象一下接口,方便后面修改;
#define Z_GPIO_PIN GPIO_Pin_5
#define Z_GPIO_PORT GPIOE
#define Z_PortSource GPIO_PortSourceGPIOE
#define Z_PinSource GPIO_PinSource5
#define Z_Line EXTI_Line5
#define Z_IRQ EXTI9_5_IRQn
GPIO的配置;这里GPIO的输入模式可以配置为浮空输入(GPIO_Mode_IN_FLOATING),上拉输入(GPIO_Mode_IPU)或者下拉输入(GPIO_Mode_IPD),具体如下图所示;
GPIO的配置代码如下;
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = Z_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(Z_GPIO_PORT, &GPIO_InitStructure);
不要忘记外设总线时钟的配置;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC |
RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOF |
RCC_APB2Periph_GPIOG, ENABLE);
EXTI的配置,EXTI_Trigger这里支持三种模式;
- EXTI_Trigger_Rising 上升沿触发;
- EXTI_Trigger_Falling 下降沿触发;
- EXTI_Trigger_Rising_Falling 上升沿和下降沿都可以触发;
GPIO_EXTILineConfig(Z_PortSource, Z_PinSource);
EXTI_InitStructure.EXTI_Line = Z_Line;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC的配置
NVIC_InitStructure.NVIC_IRQChannel = Z_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
中断服务函数
void EXTI9_5_IRQHandler(void)
{
//中断服务函数
}
以上就完成了检测下降沿信号的GPIOE5的外部中断;
也参考官方DEMO,
STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\EXTI\EXTI_Config。
5 寄存器的操作
以下摘自**《STM32参考手册》**
产生产生中断的步骤,必须先配置好并使能中断线。根据需要的边沿检测设置2个触发寄存器,同时在**中断屏蔽寄存器(EXTI_IMR)的相应位写1允许中断请求。当外部中断线上发生了期待的边沿时,将产生一个中断请求,对应的挂起位也随之被置1。在挂起寄存器(EXTI_PR)的对应位写1,将清除该中断请求。
产生事件的步骤:必须先配置好并使能事件线。根据需要的边沿检测通过设置2个触发寄存器,同时在中断屏蔽寄存器(EXTI_IMR)**的相应位写1允许事件请求。当事件线上发生了需要的边沿时,将产生一个事件请求脉冲,对应的挂起位不被置1。通过在软件中断/事件寄存器写1,也可以通过软件产生中断/事件请求。
- 中断屏蔽寄存器(EXTI_IMR)
- 事件屏蔽寄存器(EXTI_EMR)
- 上升沿触发选择寄存器(EXTI_RTSR)
- 下降沿触发选择寄存器(EXTI_FTSR)
- 软件中断事件寄存器(EXTI_SWIER)
- 挂起寄存器(EXTI_PR)
IMR如下图所示,其他几个类似;

5.1 硬件中断选择
通过下面的过程来配置20个线路做为中断源:
- 配置20个中断线的屏蔽位(EXTI_IMR)
- 配置所选中断线的触发选择位(EXTI_RTSR和EXTI_FTSR);
- 配置对应到外部中断控制器(EXTI)的NVIC中断通道的使能和屏蔽位,使得20个中断线中的请求可以被正确地响应。
5.2 硬件事件选择
通过下面的过程,可以配置20个线路为事件源
- 配置20个事件线的屏蔽位(EXTI_EMR)
- 配置事件线的触发选择位(EXTI_RTSR和EXTI_FTSR)
5.3 软件中断/事件的选择
20个线路可以被配置成软件中断/事件线。下面是产生软件中断的过程:
- 配置20个中断/事件线屏蔽位(EXTI_IMR, EXTI_EMR)
- 设置软件中断寄存器的请求位(EXTI_SWIER)
6 总结
本文参考stm32手册对于外部中断的概念以及配置进行了介绍,本人能力有限,难免存在错误和纰漏,请大佬不吝赐教。
STM32 外部中断详解(原理+配置代码)的更多相关文章
- STM8的中断系统以及外部中断详解
STM8具有最多32的中断系统,在中断的处理上类似于cortexm系列的芯片,首先是每个中断的向量都是固化在系统内部的,用户需要向相应的中断向量flash位置写入中断处理函数,其二,每个中断向量都具有 ...
- STM32固件库详解
STM32固件库详解 emouse原创文章,转载请注明出处http://www.cnblogs.com/emouse/ 应部分网友要求,最新加入固件库以及开发环境使用入门视频教程,同时提供例程模板 ...
- log4j.properties 详解与配置步骤(转)
找的文章,供参考使用 转自 log4j.properties 详解与配置步骤 一.log4j.properties 的使用详解 1.输出级别的种类 ERROR.WARN.INFO.DEBUGERROR ...
- 磁盘分区对齐详解与配置 – Linux篇
在之前一篇<磁盘分区对齐详解与配置 – Windows篇>中,我介绍了磁盘分区对齐的作用和适用于MBR和GPT的两种磁盘类型的配置,以及Windows平台设置磁盘分区对齐的方法. 本文作为 ...
- SpringBoot Profile使用详解及配置源码解析
在实践的过程中我们经常会遇到不同的环境需要不同配置文件的情况,如果每换一个环境重新修改配置文件或重新打包一次会比较麻烦,Spring Boot为此提供了Profile配置来解决此问题. Profile ...
- C3P0连接池详解及配置
C3P0连接池详解及配置 本人使用的C3P0的jar包是:c3p0-0.9.1.jar <bean id = "dataSource" class = "com.m ...
- SQL Server 表的管理_关于事务的处理的详解(案例代码)
SQL Server 表的管理_关于事务的处理的详解(案例代码) 一.SQL 事务 1.1SQL 事务 ●事务是在数据库上按照一定的逻辑顺序执行的任务序列,既可以由用户手动执行,也可以由某种数据库程序 ...
- SQL Server 表的管理_关于数据增删查改的操作的详解(案例代码)
SQL Server 表的管理_关于数据增删查改的操作的详解(案例代码)-DML 1.SQL INSERT INTO 语句(在表中插入) INSERT INTO 语句用于向表中插入新记录. SQL I ...
- SQL Server 表的管理_关于表的操作增删查改的操作的详解(案例代码)
SQL Server 表的管理_关于表的操作增删查改的操作的详解(案例代码) 概述: 表由行和列组成,每个表都必须有个表名. SQL CREATE TABLE 语法 CREATE TABLE tabl ...
随机推荐
- F - Robot Motion 栈加BFS
A robot has been programmed to follow the instructions in its path. Instructions for the next direct ...
- 腾讯云集群服务部署mysql并挂载到服务器
一.背景 由于现在大部分的应用都是运行在云服务器上的,而现在大多数文章都是主要写如何在服务器上使用docker去运行mysql,比较少有介绍云服务器上的.再加上现在k8s比较火爆,而云厂商大多数都提供 ...
- [整理]svn常见问题汇总
1.’.’ is not a working copy.Can’t open file‘.svn/entries’: 系统找不到指定的路径.解答:原因是输入的访问路径不正确,如svn://192.16 ...
- 图解AVL树
1:AVL树简介 二叉搜索树在一般情况下其搜索的时间复杂度为O(logn),但某些特殊情况下会退化为链表,导致树的高度变大且搜索的时间复杂度变为O(n),发挥不出树这种数据结构的优势,因此平衡二叉树便 ...
- ubuntu16.04-交叉编译-SeetaFaceEngine-master
0.前言 在要移植opecv和SeetaFaceEngine-master到ARM板子上运行的所有步骤之前,有几点需要注意的: 查看板子运行的Kernel版本 交叉编译工具链的gcc版本,关键就是工具 ...
- 推荐web前端框架bootstrap
bootstrap是基于Jquery而开发的一个前端框架. 全中文的学习网站:http://www.runoob.com/bootstrap/bootstrap-tutorial.html 实际上就是 ...
- 大数据hbase分布式安装及其部署。
大数据hbase分布式安装及其部署. 首先要启动Hadoop以及zookeeper,可以参考前面发布的文章. 将hbase的包上传至master节点 这里我使用的是1.3.6的版本,具体的根据自己的版 ...
- 0day堆(2)堆的调试实验
堆的调试实验 调试态堆管理策略和常态堆管理策略:前者只使用空表不用块表,不真实 使用调试器加载函数会触发前者 __asm int3 调试最真实的栈 未启用块表的堆区信息 堆区起始位置(假设为0x005 ...
- 前端js传值JSON.stringify(obj)
用bootstrap-talbe前端传值 首先直接传肯定是不行的; 其次做一个全局变量也不行,因为这里的问题的是用bootstrap-table进行生成的操作HTML,从这里datass = row ...
- php内置函数call_user_func()
<?php //call_user_func(callback,name,age) //第一个参数callback作为回掉函数使用,其余的参数是他的参数 function now($a,$b) ...