STM32F103外部中断配置

一、外部中断

在上一节我们介绍了STM32f103的嵌套向量中断控制器,其中包括中断的使能、失能、中断优先级分组以及中断优先级配置等内容。

1.1 外部中断/事件控制器

STM32f103支持的60个可屏蔽中断中,有一些比较特殊的中断:

  • 中断编号13 EXTI0EXTI线0中断;

  • 中断编号14 EXTI1EXTI线1中断;

  • 中断编号15 EXTI2EXTI线2中断;

  • 中断编号16 EXTI3EXTI线3中断;

  • 中断编号17 EXTI4EXTI线4中断;

  • 中断编号30 EXTI9_5EXTI线[9:5]中断;

  • 中断编号47 EXTI15_10EXTI线[15:10]中断;

  • 中断编号8 PVD:连到EXTI的电源电压检测(PVD)中断;

  • 中断编号48 RTCAlarm:连到EXTI线16RTC闹钟时间;

  • 中断编号49 USB唤醒:连到EXTI的线17USB待机唤醒事件;

  • 对于STM32F107来说,还有一个连到EXTI线18的以太网唤醒事件;

对于STM32f103来说,有19个能产生事件/中断请求的边沿检测器。每个输入线可以独立地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿或下降沿或者双边沿都触发)。每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求。

1.1.1 EXTI线与IO映射关系4

EXTI线0~15:对应外部IO口的输入中断。STM32F103供给IO口使用的中断线只有16个,但是 STM32F103IO口 却远远不止16 个,所以STM32GPIO管脚GPIOx.0~GPIOx.15(x=A,B,C,D,E,F,G)分别对应中断线0~15

这样子每个中断线对应了最多9个IO口,以线0为例:它对应了GPIOA0GPIOB0GPIOC0GPIOD0GPIOE0GPIOF0GPIOG0。而中断线每次只能连接到1个IO口上, 这样就需要通过配置决定对应的中断线配置到哪个GPIO上了。

GPIO和中断线映射关系是在寄存器AFIO_EXTICR1 ~ AFIO_EXTICR4中配置的。

1.1.2 框图

其中按照控制功能划分,共分为4个部分,有两条主线:

  • 一条是由输入线到NVIC中断控制器;
  • 一条是由输入线到脉冲发生器。

其中:

  • 输入线:是线路的信息输入端,它可以通过配置寄存器设置为任何一个GPIO口,或者是一些外设的事件。输入线一般都是存在电平变化的信号;
  • 边沿检测电路(标号1):上升沿触发选择寄存器和下降沿触发选择寄存器。边沿检测电路以输入线作为信号输入端,如果检测到有边沿跳变就输出有效信号1,就输出有效信号1到标号2部分电路,否则输入无效信号0。边沿跳变的标准在于对两个触发选择寄存器的设置;
  • 或门电路(标号2):它的两个信号输入端分别是软件中断事件寄存器和边沿检测电路的输入信号。或门电路只要输入端有信号1,就会输出1,所以就会输出信号1到标号3电路和标号4电路;
  • 与门电路(标号3):两个信号输入端分别是中断屏蔽寄存器和标号2电路信号;-
    • 如果中断屏蔽寄存器设置为0时,不管从标号2电路输出的信号特性如何,最终标号3电路输出的信号都是0;
    • 如果中断屏蔽寄存器设置为1时,最终标号3电路输出的信号才由标号2电路输出信号决定;
  • 与门电路(标号4):输入端来自标号2电路以及来自于事件屏蔽寄存器。可以简单的控制事件屏蔽寄存器来实现是否产生事件的目的。标号4电路输出有效信号1就会使脉冲发生器电路产生一个脉冲,而无效信号就不会使其产生脉冲信号。脉冲信号产生可以给其他外设电路使用,例如定时器,模拟数字转换器等,这样的脉冲信号一般用来触发TIM或者ADC开始转换。
1.2 功能说明
1.2.1 硬件中断选择

要产生中断,必须先配置好并使能中断线;

  • 根据需要的边沿检测设置2个触发寄存器(EXTI_RTSREXTI_FTSR),同时在中断屏蔽寄存器(EXTI_IMR)的相应位写1允许中断请求;
  • 配置对应到外部中断控制器(EXTI)的NVIC中断通道的使能和屏蔽位,使得20个中断线中的请求可以被正确地响应;
  • 当外部中断线上发生了期待的边沿时,将产生一个中断请求,对应的挂起位(EXTI_PR)也随之被置1;
  • 在挂起寄存器(EXTI_PR)的对应位写1,将清除该中断请求。
1.2.2 硬件事件选择

如果需要产生事件,必须先配置好并使能事件线;

  • 根据需要的边沿检测通过设置2个触发寄存器(EXTI_RTSREXTI_FTSR),同时在事件屏蔽寄存器(EXTI_EMR)的相应位写1允许事件请求;

  • 当事件线上发生了需要的边沿时,将产生一个事件请求脉冲,对应的挂起位(EXTI_PR)不被置1。

1.2.3 软件中断/事件的选择

通过在软件中断/事件寄存器写1,也可以通过软件产生中断/事件请求;

  • 配置20个中断/事件线屏蔽位(EXTI_IMREXTI_EMR);
  • 设置软件中断寄存器的请求位(EXTI_SWIER)。

二、EXTI相关寄存器

在前面的介绍中,所涉及的寄存器共有7个:

  • 上升沿触发选择寄存器(EXTI_RTSR);
  • 下降沿触发选择寄存器(EXTI_FTSR);
  • 挂起寄存器(EXTI_PR);
  • 软件中断事件寄存器(EXTI_SWIER);
  • 中断屏蔽寄存器(EXTI_IMR);
  • 事件屏蔽寄存器(EXTI_EMR);
  • 外部中断配置寄存器 (AFIO_EXTICRx)。
2.1 上升沿触发选择寄存器(EXTI_RTSR)

该寄存器主要用于控制输入线进来的输入信号,上升沿时是否在边沿检测电路被检测出,20位共控制20EXTI线;

2.2 下降沿触发选择寄存器(EXTI_FTSR)

该寄存器主要用于控制输入线进来的输入信号,下升沿时是否在边沿检测电路被检测出,20位共控制20EXTI线;

2.3 挂起寄存器(EXTI_PR)

该寄存器的作用主要有两个:

  • 检测外部中断线上是否发生了选择的边沿事件,如果发生了该位置1,并将信号传递给与门电路,进而进入NVIC中;
  • 在该位手动(软件)写入1,可以清除之前中断信号的1,主要作用是进入中断后,清除中断位,防止多次进入中断。
2.4 软件中断事件寄存器(EXTI_SWIER)
2.5 中断屏蔽寄存器(EXTI_IMR)

该寄存器的主要作用只有一个,就是是否允许来自输入线上的中断信号进入NVIC中断控制器。

2.6 事件屏蔽寄存器(EXTI_EMR)

该寄存器的主要作用只有一个,就是是否允许来自输入线线上的事件进入脉冲发生器。

2.7 外部中断配置寄存器 (AFIO_EXTICRx)

AFIO_EXTICR1寄存器配置EXTI0EXTI3线,包含的外部中断的引脚包括PAxPGxx=03

AFIO_EXTICR2寄存器配置EXTI4EXTI7线;

AFIO_EXTICR3寄存器配置EXTI8EXTI11线;

AFIO_EXTICR4寄存器配置EXTI12EXTI15线;

特别注意:配置AFIO寄存器之前需要使能AFIO的时钟。

2.7.1 AFIO_EXTICR1
2.7.2 AFIO_EXTICR2
2.7.3 AFIO_EXTICR3
2.7.4 AFIO_EXTICR4

三、外部中断源码

3.1 外部中断的初始化步骤

EXTI中断配置流程如下:

(1) GPIO口初始化;

  • 外设时钟配置:通过配置RCC_APB2ENR寄存器使能GPIO时钟;
  • GPIO配置:设置GPIO工作模式为上拉/下拉输入模式、浮空输入模式,即配置GPIOx_CRLGPIOx_CRH寄存器;

(2) EXTI外部中断配置;

  • AFIO时钟配置:通过配置RCC_APB2ENR寄存器使能AFIO时钟;
  • 设置GPIOEXTI映射关系:通过AFIO_EXTICRx寄存器配置IO对应的EXTI输入线;
  • 设置EXTI屏蔽、上升沿、下降沿:即设置EXTI_EMREXTI_RTSREXTI_FTSR寄存器;

(3) 设置NVIC;

  • 参考《STM32F103嵌套向量中断控制器》:设置中断优先级分组、设置响应优先级和抢断优先级、使能相应中断位;

(34) 中断处理函数;

  • 设置中断服务函数(包括清除中断标志)。
3.2 源码实现
3.2.1 GPIO口初始化

首先调用gpio_init函数进行GPIO初始化,具体参考《STM32F103 GPIO和串口配置》。

比如配置GPIOC5为上拉输入:

gpio_init(PC5,GPI_UP,HIGH);	             // PC5接按键KEY0
3.2.2 外部中断配置函数
typedef enum	                    //外部中断触发方式
{FALLING = 0x01,RISING  = 0x02,LEVEL   = 0x03
}TRIGGER_MODE;/********************************************************************************************************* *		   Description:外部中断配置函数*					   决定中断线配置到哪个GPIO口	  *                    AFIO->EXTICR[0~3] 每个寄存器的低16位每4位决定1路中断线  *					   0000:PAx    0001:PBx    0010:PCx0011:PDx    0100:PEx    0101:PFx*         Parameter:portx_pinx形如PA0,PA1................TRIGGER_Mode:  0x01 下降沿触发    0x02 上升沿触发0x03 任意电平触发*			Example   : Ex_NVIC_Congig(PA8,0x01);       PA8下降沿触发	*********************************************************************************************************/void Ex_NVIC_Congig(PORTx_PINx portx_pinx,TRIGGER_MODE  trigger_mode){u8 address;			        //外部中断触发寄存器编号选择u8 offset;                  //外部中断触发寄存器偏移位选择u8 portx=portx_pinx/16;     //端口号u8 pinx=portx_pinx%16;      //引脚号 address = pinx/4;offset  = (pinx%4)*4;RCC->APB2ENR |= 1<<0;                     //使能I/O复用时钟AFIO->EXTICR[address]|=portx<<offset;     //EXTI.BITx映射到GPIOx.BITx
//		EXTI->PR  |= 1<<pinx;                     //清除线x上的中断标志位 EXTI->IMR |= 1<<pinx;                     //开放来自线x上的中断请求EXTI->EMR |= 1<<pinx;                     //开放来自线x上的事件请求if(trigger_mode==0x01)EXTI->FTSR |= 1<<pinx;   			  //设置线x上下降沿触发if(trigger_mode==0x02)EXTI->RTSR |= 1<<pinx;   			  //设置线x上上降沿触发}

比如配置GPIOC5为下降沿触发:

Ex_NVIC_Congig(PC5,FALLING);             // 按键KEY0按下触发 高电平->低电平
3.2.3 NVIC中断优先级初始化

调用STM32_NVIC_Init函数初始化PC5中断优先级,具体参考《STM32F103嵌套向量中断控制器》;

GPIOC5对应的EXTI线[9:5],这里设置EXTI9_5_IRQn中断优先级分组2,抢占优先级为2,响应优先级为2;

STM32_NVIC_Init(2,EXTI9_5_IRQn,2,2);
3.2.4 中断处理函数

这里依然以EXTI9_5_IRQn中断为例,对应的中断处理函数为EXTI9_5_IRQHandler

/*********************************************************************************************************************
* Function Name  : EXTI9_5_IRQHandler
* Description    : This function handles External lines 9 to 5 interrupt request.
* Input          : None
* Output         : None
* Return         : None
*************************************************************************************************************************/
void EXTI9_5_IRQHandler(void)
{if(	EXTI->PR & 1<<5 )               //来自中断线5上的中断{//**********************自定义用户任务****************************////*****************************************************************//EXTI->PR = 1<<5;				   //清中断线5上的中断标志}   if(	EXTI->PR & 1<<6 )               //来自中断线6上的中断{//**********************自定义用户任务****************************////*****************************************************************//EXTI->PR = 1<<6;	                //清中断线6上的中断标志}if(	EXTI->PR & 1<<7 )               //来自中断线7上的中断{//**********************自定义用户任务****************************////*****************************************************************//EXTI->PR = 1<<7;	                        //清中断线7上的中断标志 }if(	EXTI->PR & 1<<8 )                  //来自中断线8上的中断{//**********************自定义用户任务****************************//usart_sendStr(USART_1, "坏人");//*****************************************************************//EXTI->PR = 1<<8;	                  //清中断线8上的中断标志 }if(	EXTI->PR & 1<<9 )                 //来自中断线9上的中断{//**********************自定义用户任务****************************////*****************************************************************//EXTI->PR = 1<<9;	                 //清中断线9上的中断标志 }
}
3.3 实现功能

这里我们就利用手头开发板的独立按键kKEY0来控制LED1灯的亮灭;

其中:

  • KEY0连接STM32f103GPIOC5,按键无上拉电阻,需要在GPIOC5上设为上拉状态,提供一个确定电平;
    • 按键按下时,GPIOC5输出低电平;
    • 当按键未按下时,GPIOC5应为高电平;
  • LED1连接STM32f103GPIOA8引脚,低电平点亮;

我们要实现的功能也很简单:即按下KEY0点亮LED1,源码实现包括以下两个步骤;

  • 配置GPIOA8通用推挽输出,最大速度50MHz
  • 配置GPIOC对应的EXTI线[9:5]外部中断,下降沿触发;
3.3.1 main函数实现
int main()
{ u32 i=0;STM32_Clock_Init(9);         	          //系统时钟初始化                         	while(RTC_Init());                       //RTC初始化 STM32_NVIC_Init(2,USART1_IRQn,0,1);		  //串口中断优先级初始化,其中包括中断使能usart_init(USART_1,115200);				  //串口1初始化,波特率115200 映射到PA9 PA10// LED1初始化gpio_init(PA8,GPO_SpeedMax_50,HIGH);              //PA8接入LED1  // 按键KEY0初始化  gpio_init(PC5,GPI_UP,HIGH);	             //PC5接按键KEY0Ex_NVIC_Congig(PC5,FALLING);                //按键KEY0按下触发 高电平->低电平STM32_NVIC_Init(2,EXTI9_5_IRQn,2,2);	     //EXTI线[9:5]中断优先级初始化,其中包括中断使能while(1){	    delay_ms(100);PAout(8) = 1;   // 熄灭LED1}		 
}
3.3.2 EXTI9_5_IRQHandler函数实现
/*********************************************************************************************************************
* Function Name  : EXTI9_5_IRQHandler
* Description    : This function handles External lines 9 to 5 interrupt request.
* Input          : None
* Output         : None
* Return         : None
*************************************************************************************************************************/
void EXTI9_5_IRQHandler(void)		
{if(	EXTI->PR & 1<<5 )               //来自中断线5上的中断{//**********************自定义用户任务****************************//PAout(8) = 0;   // 点亮LED1//*****************************************************************//EXTI->PR = 1<<5;				   //清中断线5上的中断标志}   if(	EXTI->PR & 1<<6 )               //来自中断线6上的中断{//**********************自定义用户任务****************************////*****************************************************************//EXTI->PR = 1<<6;	                //清中断线6上的中断标志}if(	EXTI->PR & 1<<7 )               //来自中断线7上的中断{//**********************自定义用户任务****************************////*****************************************************************//EXTI->PR = 1<<7;	                        //清中断线7上的中断标志 }if(	EXTI->PR & 1<<8 )                  //来自中断线8上的中断{//**********************自定义用户任务****************************////*****************************************************************//EXTI->PR = 1<<8;	                  //清中断线8上的中断标志 }if(	EXTI->PR & 1<<9 )                 //来自中断线9上的中断{//**********************自定义用户任务****************************////*****************************************************************//EXTI->PR = 1<<9;	                 //清中断线9上的中断标志 }}

四、源码下载

源码下载路径:stm32f103

参考文章

[1] Mini2440裸机开发之中断控制器

[2] STM32--中断使用

[3] 《STM32F10xxx Cortex-M3编程手册》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/61947.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C嘎嘎探索篇:栈与队列的交响:C++中的结构艺术

C嘎嘎探索篇&#xff1a;栈与队列的交响&#xff1a;C中的结构艺术 前言&#xff1a; 小编在之前刚完成了C中栈和队列&#xff08;stack和queue&#xff09;的讲解&#xff0c;忘记的小伙伴可以去我上一篇文章看一眼的&#xff0c;今天小编将会带领大家吹奏栈和队列的交响&am…

【c语言】文件操作详解 - 从打开到关闭

文章目录 1. 为什么使用文件&#xff1f;2. 什么是文件&#xff1f;3. 如何标识文件&#xff1f;4. 二进制文件和文本文件&#xff1f;5. 文件的打开和关闭5.1 流和标准流5.1.1 流5.1.2 标准流 5.2 文件指针5.3 文件的打开和关闭 6. 文件的读写顺序6.1 顺序读写函数6.2 对比一组…

从 0 到 1 掌握部署第一个 Web 应用到 Kubernetes 中

文章目录 前言构建一个 hello world web 应用项目结构项目核心文件启动项目 检查项目是否构建成功 容器化我们的应用编写 Dockerfile构建 docker 镜像推送 docker 镜像仓库 使用 labs.play-with-k8s.com 构建 Kubernetes 集群并部署应用构建 Kubernetes 集群环境编写部署文件 总…

Matlab以一个图像分类例子总结分类学习的使用方法

目录 前言 导入数据 训练学习 导出训练模型 仿真测试 总结 前言 最近在尝试一些基于Simulink的边沿AI部署,通过这个案例总结Matlab 分类学习功能的使用。本案例通过输入3000张28*28的灰度图像,训练分类学习模型。并验证训练好的模型最后部署到MCU。 导入数据 如下图是…

2025蓝桥杯(单片机)备赛--扩展外设之UART1的原理与应用(十二)

一、串口1的实现原理 a.查看STC15F2K60S2数据手册: 串口一在590页&#xff0c;此款单片机有两个串口。 串口1相关寄存器&#xff1a; SCON:串行控制寄存器&#xff08;可位寻址&#xff09; SCON寄存器说明&#xff1a; 需要PCON寄存器的SMOD0/PCON.6为0&#xff0c;使SM0和SM…

Reactor 模式的理论与实践

1. 引言 1.1 什么是 Reactor 模式&#xff1f; Reactor 模式是一种用于处理高性能 I/O 的设计模式&#xff0c;专注于通过非阻塞 I/O 和事件驱动机制实现高并发性能。它的核心思想是将 I/O 操作的事件分离出来&#xff0c;通过事件分发器&#xff08;Reactor&#xff09;将事…

【Android+多线程】IntentService 知识总结:应用场景 / 使用步骤 / 源码分析

定义 IntentService 是 Android中的一个封装类&#xff0c;继承自四大组件之一的Service 功能 处理异步请求 & 实现多线程 应用场景 线程任务 需 按顺序、在后台执行 最常见的场景&#xff1a;离线下载不符合多个数据同时请求的场景&#xff1a;所有的任务都在同一个T…

Easy Excel 通过【自定义批注拦截器】实现导出的【批注】功能

目录 Easy Excel 通过 【自定义批注拦截器】实现导出的【批注】功能需求原型&#xff1a;相关数据&#xff1a;要导出的对象字段postman 格式导出对象VO 自定义批注拦截器业务代码&#xff1a; 拦截器代码解释&#xff1a;详细解释&#xff1a;格式优化&#xff1a; Easy Excel…

Spring Boot 的 WebClient 实践教程

什么是 WebClient&#xff1f; 在 Spring Boot 中&#xff0c;WebClient 是 Spring WebFlux 提供的一个非阻塞、响应式的 HTTP 客户端&#xff0c;用于与 RESTful 服务或其他 HTTP 服务交互。相比于传统的 RestTemplate&#xff0c;WebClient 更加现代化&#xff0c;具有异步和…

QML学习 —— 29、3种不同使用动画的方式(附源码)

效果 说明 第一种:属性动画 - 当启动软件时候自动执行动画。      第二种:行为动画 - 当属性发生变化则自动执行动画。      第三种:目标动画 - 将动画变为对象,指定对象的目标进行执行动画。 代码 import QtQuick 2.12 import QtQuick.Window 2.12 import QtQu…

Redis缓存穿透及常见的解决方案

一.什么是缓存穿透&#xff1f; 缓存穿透是指当客户端请求的数据在缓存&#xff08;如 Redis&#xff09;中不存在&#xff0c;并且在数据库中也不存在时&#xff0c;直接绕过缓存去请求数据库。这种情况会导致&#xff1a; 缓存系统无法发挥作用&#xff0c;数据每次都会直接…

(原创)Android Studio新老界面UI切换及老版本下载地址

前言 这两天下载了一个新版的Android Studio&#xff0c;发现整个界面都发生了很大改动&#xff1a; 新的界面的一些设置可参考一些博客&#xff1a; Android Studio新版UI常用设置 但是对于一些急着开发的小伙伴来说&#xff0c;没有时间去适应&#xff0c;那么怎么办呢&am…

windows下安装wsl的ubuntu,同时配置深度学习环境

写在前面&#xff0c;本次文章只是个人学习记录&#xff0c;不具备教程的作用。个别信息是网上的&#xff0c;我会标注&#xff0c;个人是gpt生成的 安装wsl 直接看这个就行&#xff1b;可以不用备份软件源。 https://blog.csdn.net/weixin_44301630/article/details/1223900…

Node.js的http模块:创建HTTP服务器、客户端示例

新书速览|Vue.jsNode.js全栈开发实战-CSDN博客 《Vue.jsNode.js全栈开发实战&#xff08;第2版&#xff09;&#xff08;Web前端技术丛书&#xff09;》(王金柱)【摘要 书评 试读】- 京东图书 (jd.com) 要使用http模块&#xff0c;只需要在文件中通过require(http)引入即可。…

AI赋能电商:构建高效、智能化的新零售生态

随着人工智能&#xff08;AI&#xff09;技术的不断进步&#xff0c;其在电商领域的应用日益广泛&#xff0c;从购物推荐到供应链管理&#xff0c;再到商品定价&#xff0c;AI正在全面改变传统电商的运营模式&#xff0c;并推动行业向智能化和精细化方向发展。本文将探讨如何利…

算法之区间和题目讲解

题干 难度&#xff1a;简单 题目分析 题目要求算出每个指定区间内元素的总和。 然而&#xff0c;区间在输入的最下面&#xff0c;所以按照暴力破解的思路&#xff0c;我们首先要遍历数组&#xff0c;把它的值都存进去。 然后&#xff0c;遍历下面的区间&#xff0c;从索引a…

openssl颁发包含主题替代名的证书–SAN

原文地址&#xff1a;openssl颁发包含主题替代名的证书–SAN – 无敌牛 欢迎参观我的个人博客&#xff1a;无敌牛 – 技术/著作/典籍/分享等 在 X.509 证书中&#xff0c;commonName&#xff08;CN&#xff09;字段只能有一个值。如果让证书支持多个域名和IP地址&#xff0c;…

从尾到头打印链表 剑指offer

题目描述 输入一个链表的头节点&#xff0c;从尾到头反过来打印出每个节点的值。 链表节点定义如下&#xff1a; struct ListNode {int m_nKey;ListNode*m_pNext; }; 代码实现 栈实现&#xff1a; 递归实现&#xff1a; 但是用递归实现可能存在的问题&#xff1a;

ajax基础

一&#xff1a;express框架 在终端输入nodejs文件名 // 引入express const express require(express); //创建应用对象 const app express(); //创建路由规则 app.get(/,(request,response) > {//设置响应response.send(Hello Express); }); // 监听3000端口 app.lis…

免费实用在线AI工具集合 - 加菲工具

免费在线工具-加菲工具 https://orcc.online/ 在线录屏 https://orcc.online/recorder 时间戳转换 https://orcc.online/timestamp Base64 编码解码 https://orcc.online/base64 URL 编码解码 https://orcc.online/url Hash(MD5/SHA1/SHA256…) 计算 https://orcc.online/h…