STM32F401的外部中断EXTI
stm32f401 EXTI
EXTI就是External interrupt/event controller, 外部事件和中断控制器, 包含21条边沿检测线. 每条线可以独立设置触发事件(上升沿, 下降沿或两者同时). 一个等待寄存器维护中断请求的状态.
当动作发生(例如按键按下)时, 如果电平状态由低变高, 会在输入线产生一个上升沿信号, 这个信号到达边沿检测电路后, 会被上升沿触发选择寄存器(EXTI_RTSR)检测并触发, 输出有效信号, 否则输出无效信号0. 反之如果电平由高变低, 则会被下降沿触发选择寄存器(EXTI_FTSR)检测触发.
EXTI可以在外部连线上检测到比内部APB2时钟周期更短的脉冲. stm32f4系列最多有81个GPIO可以连接到16个外部中断线. IO口和中断线的映射是多对一的, 例如EXTI0, 可以对应PA0, PB0, PC0等, 实际用到某个I/O引脚时, 通过配置决定具体哪个引脚对应EXTI0.
在stm32f4xx_exti.h中定义了0 - 23的中断线
#define EXTI_Line0 ((uint32_t)0x00001) /*!< External interrupt line 0 */
#define EXTI_Line1 ((uint32_t)0x00002) /*!< External interrupt line 1 */
#define EXTI_Line2 ((uint32_t)0x00004) /*!< External interrupt line 2 */
#define EXTI_Line3 ((uint32_t)0x00008) /*!< External interrupt line 3 */
#define EXTI_Line4 ((uint32_t)0x00010) /*!< External interrupt line 4 */
#define EXTI_Line5 ((uint32_t)0x00020) /*!< External interrupt line 5 */
#define EXTI_Line6 ((uint32_t)0x00040) /*!< External interrupt line 6 */
#define EXTI_Line7 ((uint32_t)0x00080) /*!< External interrupt line 7 */
#define EXTI_Line8 ((uint32_t)0x00100) /*!< External interrupt line 8 */
#define EXTI_Line9 ((uint32_t)0x00200) /*!< External interrupt line 9 */
#define EXTI_Line10 ((uint32_t)0x00400) /*!< External interrupt line 10 */
#define EXTI_Line11 ((uint32_t)0x00800) /*!< External interrupt line 11 */
#define EXTI_Line12 ((uint32_t)0x01000) /*!< External interrupt line 12 */
#define EXTI_Line13 ((uint32_t)0x02000) /*!< External interrupt line 13 */
#define EXTI_Line14 ((uint32_t)0x04000) /*!< External interrupt line 14 */
#define EXTI_Line15 ((uint32_t)0x08000) /*!< External interrupt line 15 */
#define EXTI_Line16 ((uint32_t)0x10000) /*!< External interrupt line 16 Connected to the PVD Output */
#define EXTI_Line17 ((uint32_t)0x20000) /*!< External interrupt line 17 Connected to the RTC Alarm event */
#define EXTI_Line18 ((uint32_t)0x40000) /*!< External interrupt line 18 Connected to the USB OTG FS Wakeup from suspend event */
#define EXTI_Line19 ((uint32_t)0x80000) /*!< External interrupt line 19 Connected to the Ethernet Wakeup event */
#define EXTI_Line20 ((uint32_t)0x00100000) /*!< External interrupt line 20 Connected to the USB OTG HS (configured in FS) Wakeup event */
#define EXTI_Line21 ((uint32_t)0x00200000) /*!< External interrupt line 21 Connected to the RTC Tamper and Time Stamp events */
#define EXTI_Line22 ((uint32_t)0x00400000) /*!< External interrupt line 22 Connected to the RTC Wakeup event */
#define EXTI_Line23 ((uint32_t)0x00800000) /*!< External interrupt line 23 Connected to the LPTIM Wakeup event */
在stm32f4xx.h中, 有这些中断的常量, 注意: Line虽然是各自独立的, 但是IRQn不是, Handler也不是
EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */
EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */
EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */
EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */
EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */
EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */
EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */
可以看到, 对于EXTI0到EXTI4(Line0到Line4), 都是单独的常量, 而Line5到Line9, Line10到Line15都是合用的.
对应的, 有以下的中断处理方法, 通过这些方法将自己的中断逻辑关联到对应的中断事件上去
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
EXTI9_5_IRQHandler
EXTI15_10_IRQHandler
初始化的步骤
##### How to use this driver #####
==================================================
[..] In order to use an I/O pin as an external interrupt source, follow steps
below:
(#) Configure the I/O in input mode using GPIO_Init()
(#) Select the input source pin for the EXTI line using SYSCFG_EXTILineConfig()
(#) Select the mode(interrupt, event) and configure the trigger
selection (Rising, falling or both) using EXTI_Init()
(#) Configure NVIC IRQ channel mapped to the EXTI line using NVIC_Init()
[..]
(@) SYSCFG APB clock must be enabled to get write access to SYSCFG_EXTICRx
registers using RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
- 使能I/O口时钟, 初始化I/O口为输入
- 使能SYSCFG时钟, 设置I/O口与中断线的映射关系
- 初始化中断线(EXTI线编号, 中断模式是中断还是事件, 触发方式是下降沿触发、上升沿触发还是任意电平触发, 是否使能中断线)
- 配置嵌套中断向量控制器NVIC
- 编写中断服务函数 对应各个中断线分别有EXTI0_IRQHandler(), EXTI1_IRQHandler(), ... EXTI9_5_IRQHandler(), EXTI15_10_IRQHandler().
官方的代码例子
- This example shows how to configure external interrupt lines.
- In this example, 2 EXTI lines (EXTI Line0 and Line15) are configured to generate an interrupt on each rising and falling edge, respectively.
- In the interrupt routine a LED connected to a specific GPIO pin is toggled.
static void EXTILine0_Config(void);
static void EXTILine13_15_Config(void);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program
* @param None
* @retval None
*/
int main(void)
{
/* Initialize LEDs mounted on EVAL board */
STM_EVAL_LEDInit(LED1);
STM_EVAL_LEDInit(LED2);
/* Configure EXTI Line0 (connected to PA0 pin) in interrupt mode */
EXTILine0_Config();
/* Configure EXTI Line13/15 (connected to PG13/15 pin) in interrupt mode
according to EVAL used */
EXTILine13_15_Config();
/* Generate software interrupt: simulate a falling edge applied on EXTI0 line */
EXTI_GenerateSWInterrupt(EXTI_Line0);
while (1)
{
}
}
/**
* @brief Configures EXTI Line0 (connected to PA0 pin) in interrupt mode
* @param None
* @retval None
*/
static void EXTILine0_Config(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable GPIOA clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* Enable SYSCFG clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* Configure PA0 pin as input floating */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Connect EXTI Line0 to PA0 pin */
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
/* Configure EXTI Line0 */
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/* Enable and set EXTI Line0 Interrupt to the lowest priority */
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**
* @brief Configures EXTI Line15 (connected to PG15 pin) in interrupt mode
* @param None
* @retval None
*/
static void EXTILine13_15_Config(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef USE_STM324x9I_EVAL
/* Enable GPIOC clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
#else
/* Enable GPIOG clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
#endif /* USE_STM324x9I_EVAL */
/* Enable SYSCFG clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* Configure PG15 pin as input floating */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
#ifdef USE_STM324x9I_EVAL
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_Init(GPIOC, &GPIO_InitStructure);
#else
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_Init(GPIOG, &GPIO_InitStructure);
#endif /* USE_STM324x9I_EVAL */
/* Connect EXTI Line15 to PG15 pin */
#ifdef USE_STM324x9I_EVAL
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource13);
#else
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOG, EXTI_PinSource15);
#endif /* USE_STM324x9I_EVAL */
/* Configure EXTI Line15 */
#ifdef USE_STM324x9I_EVAL
EXTI_InitStructure.EXTI_Line = EXTI_Line13;
#else
EXTI_InitStructure.EXTI_Line = EXTI_Line15;
#endif /* USE_STM324x9I_EVAL */
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/* Enable and set EXTI15_10 Interrupt to the lowest priority */
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
处理中断的例子
中断处理, 涉及的就是三步: 1)消抖(如果是按键触发), 2)确认中断源, 3)清除中断标志位
// 1
void EXTI4_IRQHandler( void )
{
delay_ms( 10 ); /* 消抖 */
if ( GPIO_ReadInputDataBit( GPIOE, GPIO_Pin_4 ) == 0 ) {
GPIO_ResetBits(GPIOF,GPIO_Pin_9);//输出低电平,灯亮
}
/* 清除LINE4上的中断标志位 */
EXTI_ClearITPendingBit( EXTI_Line4 );
}
// 2
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET) {} // 确保产生了EXTI0线中断
LED_TOGGLE; // LED灯状态切换
EXTI_ClearITPendingBit(EXTI_Line0);// 清除中断标志位
}
}
// 3
/* Set interrupt handlers */
/* Handle PB12 interrupt */
void EXTI15_10_IRQHandler(void) {
/* Make sure that interrupt flag is set */
if (EXTI_GetITStatus(EXTI_Line12) != RESET) {
/* Do your stuff when PB12 is changed */
/* Clear interrupt flag */
EXTI_ClearITPendingBit(EXTI_Line12);
}
}
参考
STM32F401的外部中断EXTI的更多相关文章
- STM32外部中断(EXTI)控制LED亮灭的代码
led.c #include "led.h" void LED_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2P ...
- stm32 外部中断学习
今天我们看看STM32的外部中断实验. STM32 供 IO 口使用的中断线只有 16 个,但是 STM32 的 IO 口却远远不止 16 个,那么 STM32 是怎么把 16 个中断线和 IO 口一 ...
- STM32之EXTI——外部中断
互联网的广大网友,大家早上中午晚上好.EXTI...故名思义..EX表外,出..I表示Intrrupt..所以合起来就是外部中断...说到这..我觉得我最近的六级水平(背单词)又进了一步,稍微自夸了下 ...
- STM32本学习笔记EXTI(外部中断)
参考资料:STM32数据表.网络信息 =========================================切割线===================================== ...
- 第17章 EXTI—外部中断/事件控制器
第17章 EXTI—外部中断/事件控制器 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.co ...
- STM32学习笔记之EXTI(外部中断)
參考资料:STM32数据手冊.网络资料 =========================================切割线==================================== ...
- EXTI—外部中断/事件控制器
外部中断/事件控制器(EXTI)管理了控制器的 23 个中断/事件线.每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测. EXTI 可以实现对每个中断/事件线进行单独 ...
- 第17章 EXTI—外部中断/事件控制器—零死角玩转STM32-F429系列
第17章 EXTI—外部中断/事件控制器 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.co ...
- STM32 EXTI(外部中断)
一.EXTI 简介 EXTI(External interrupt/event controller)-外部中断/事件控制器,管理了控制器的 20个中断/事件线.每个中断/事件线都对应有一个边沿检测器 ...
- STM32f103之外部中断
一.背景 有个需求,IO口检测上升沿,然后做相应的动作.在此记录STM32F103的外部中断结构及配置方法, 以备下次快速上手使用. 有许多不太明白,又是老司机(:-D)帮忙,真的是站在别人的肩膀上会 ...
随机推荐
- java - 标准类的定义
一个标准的类需要拥有下面 4个 组成部分: 1. 所有的成员变量都要使用 private 关键字进行修饰 2. 为每一个成员变量编写 set.get 方法 3. 创建一个无参数的构造方法 4. 创建一 ...
- 类外static函数定义要不要加static关键字?
类外static函数定义要不要加static关键字? 先说答案:不需要. 错误代码: #include<iostream> #include<memory> using nam ...
- Oceanbase部分参数学习与验证
Oceanbase部分参数学习与验证 字符集等参数查看 yum install obclient -y 然后使用客户端连接: obclient -h172.24.110.175 -P2881 -uro ...
- [转帖]Docker与k8s的恩怨情仇(四):云原生时代的闭源落幕
https://zhuanlan.zhihu.com/p/388840887 在本系列前几篇文章中,我们介绍了从Cloud Foundry到Docker等PaaS平台的发展迭代过程.今天我们继续来为大 ...
- goofys 鲲鹏上面编译挂载与性能测试
goofys 鲲鹏上面编译挂载与性能测试 介质 使用go进行编译. 官网上面有 amd64的介质,但是没有aarch64的介质 需要自行编译 前几天一直编译失败. 周天在家自己测试了一把,根据gith ...
- [转帖][大数据]ETL之增量数据抽取(CDC)
https://www.cnblogs.com/johnnyzen/p/12781942.html 目录 1 CDC 概念 1.1 定义 1.2 需求背景 1.3 考察指标 2 CDC 常见解决方案 ...
- [转帖]Redhat 8 磁盘调度策略变化:NOOP改为NONE
说明 在 redhat 4/5/6/7版本中的NOOP调度策略,从8开始修改为NONE,官方解释: none Implements a first-in first-out (FIFO) schedu ...
- [转帖]Linux中./configure、make、make install命令详解
简单来说,make 是编译,make install 是安装. 总结:linux编译安装中configure.make和make install各自的作用 • ./configure是用来检测你 ...
- [转帖]sudo 命令_su、sudo、sudo su、sudo -i的用法和区别
sudo 命令 1.sudo 简介 sudo是linux系统管理指令,是允许系统管理员让普通用户执行一些或者全部的root命令的一个工具,如halt,reboot,su等等.这样不仅减少了root用户 ...
- Mysql 查看varchar和char类型表的列长度
SELECT table_name, SUM(character_maximum_length) AS sum_length FROM information_schema.columns WHERE ...