文章目录

  • 外部中断
    • 什么是外部中断
    • 外部中断的触发
      • 上升沿触发
      • 下降沿触发
      • 上升下降沿触发
    • 外部中断初始化
      • 初始化思路
        • 1.初始化GPIO
        • 2. 打开时钟
        • 3.GPIO和外部中断的连接
        • 4.外部中断初始化结构体
        • 5.初始化外部中断
        • 6.配置NVIC
        • 7.中断服务函数
    • 外部中断的使用

文章基于适用于STM32F4系列,作者使用STM32F401CCU6开发板。
本文章基于此系列和开发板展开讨论。

外部中断

什么是外部中断

广义上是指外设所产生的中断。
一般在实践中习惯将外部引脚的电平变化所引发的中断叫外部中断。
在标准库中将GPIO所产生的中断,PVD(电压检测),RTC(实时时钟),USB等等,合在一切叫做外部中断。

注意:STM32的所有GPIO均可作为外部中断使用,这和51单片机不一样
外部中断只有24个,0-15是GPIO的外部中断,剩下的中断号的对应关系请看标准库的定义*
本文是关于GPIO所产生的外部中断的。

外部中断的触发

GPIO的外部中断是由于电平变化所引起的,为了避免误触和重复中断,STM32使用边沿触发模式来触发中断。

上升沿触发

当GPIO的电平由低电平到高电平时会触发一次中断
就像这样

下降沿触发

当GPIO的电平由高电平到低电平时会触发一次中断
就像这样

上升下降沿触发

当GPIO的电平由低电平到高电平或者从高到低时会触发一次中断
就像这样

外部中断初始化

初始化思路

  1. 初始化GPIO为输入模式(上下拉和浮空都可,不能模拟输入)
  2. 打开时钟
  3. 将GPIO和中断连接起来
  4. 配置外部中断初始化结构体
  5. 用函数初始化外部中断
  6. 配置NVIC
  7. 编写中断服务函数

1.初始化GPIO

详情见之前关于GPIO的文章
GPIO
这里只放个例子

GPIO_InitTypeDef GPIO_Initstruct;                        //声明GPIO初始化结构体
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);    //打开GPIOB的时钟
GPIO_Initstruct.GPIO_Mode=GPIO_Mode_IN;                    //设置为输入模式
GPIO_Initstruct.GPIO_OType=GPIO_OType_OD;              //设置为开漏模式
GPIO_Initstruct.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;            //引脚选择0和1
GPIO_Initstruct.GPIO_PuPd=GPIO_PuPd_UP;                    //上拉模式
GPIO_Initstruct.GPIO_Speed=GPIO_High_Speed;                //高速模式
GPIO_Init(GPIOB,&GPIO_Initstruct);                      //初始化GPIO

2. 打开时钟

这个不用解释了吧,只需要知道外部中断的控制器的时钟挂载在APB2时钟组下
因此使用这个函数配置时钟

void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)

这个外设的打开时钟命令基本上是固定的,也就是这句

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);

3.GPIO和外部中断的连接

上文提到过,STM32的GPIO都可以当作外部中断使用,但GPIO外部中断只有16个
因此我们需要一个对应关系,让GPIO和外部中断对应起来。
STM32的GPIO端口号对应着外部中断号
例如:所有GPIO组的0管脚对应外部中断0,所有GPIO组的1管脚对应外部中断1
因此不能同时使用2个组的同一管脚号来触发中断。
例如:能用A组的0引脚触发外部中断0,B组的1引脚触发外部中断1.
但不可以使用A组的0引脚和B组的0引脚同时触发外部中断0

我们使用这个函数来配置连接关系

void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex)

第一个参数是有关GPIO的信息
取值可以是

EXTI_PortSourceGPIOA 到 EXTI_PortSourceGPIOK

第二个参数是选择哪个外部中断的
取值可以是

EXTI_PinSource0 到 EXTI_PinSource15

例子

SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB,EXTI_PinSource1);

第一句是指将GPIOA组的引脚0设置为外部中断0
第二句是指将GPIOB组的引脚1设置为外部中断1

4.外部中断初始化结构体

结构体的定义是这个

typedef struct
{uint32_t EXTI_Line;                            //选择需要配置的中断EXTIMode_TypeDef EXTI_Mode;                  //选择模式EXTITrigger_TypeDef EXTI_Trigger;             //选择触发模式FunctionalState EXTI_LineCmd;               //打开或者关闭
}EXTI_InitTypeDef;

EXTI_Line
是需要配置的中断

可以使用或命令( | )同时初始化多个值
取值可以是

EXTI_Line0 到 EXTI_Line23
其中EXTI_Line0 到 EXTI_Line15是关于GPIO的外部中断

EXTI_Mode
是选择模式

取值可以是

EXTI_Mode_Interrupt              //中断模式
EXTI_Mode_Event                 //事件模式

中断模式就是我们在这里配置需要用的
事件模式是不产生中断的,可以用这个模式产生一个信号来驱动某些外设,以此来做到不占用CPU的算力,之后使用时会提到
另外中断本身也是事件的一种,其实就是将某些需要CPU响应的事件叫做中断,并进入某个函数。


EXTI_Trigger
是选择中断触发方式的

取值可以是

EXTI_Trigger_Rising                  //上升沿触发
EXTI_Trigger_Falling                //下降沿触发
EXTI_Trigger_Rising_Falling         //上升沿和下降沿触发

具体上升沿和下降沿是什么请看上文的解释。


EXTI_LineCmd
使能开关

取值可以是

DISABLE              //关闭(失能)
ENABLE              //打开(使能)

5.初始化外部中断

就是使用这个函数进行初始化

void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)

需要传入的是配置外部中断的结构体的地址
请使用取址符(&)
例子

EXTI_Init(&EXTI_Initstruct);

6.配置NVIC

这部分在之前的文章中介绍过了
中断和NVIC
关于NVIC配置结构体的外部中断中断名称(NVIC_IRQChannel)
可以取值为

EXTI0_IRQn               //外部中断0
EXTI1_IRQn              //外部中断1
EXTI2_IRQn              //外部中断2
EXTI3_IRQn              //外部中断3
EXTI4_IRQn              //外部中断4
EXTI9_5_IRQn            //外部中断5-9
EXTI15_10_IRQn          //外部中断10-15

注意外部中断0 到 外部中断4有独立的中断优先级和中断服务函数,而外部中断5-9共用一个中断优先级和中断服务函数,外部中断10-15同理,
可以在外部中断5-9中使用检测中断标志位的方式来区分是哪个中断触发

7.中断服务函数

因为所以的中断服务函数都在启动的汇编文件中定义过了,因此名字不能错误
注意:区分大小写
中断服务函数的定义时应该这样写

void EXTI0_IRQHandler(void){/*这里写函数内容*/}
void EXTI1_IRQHandler(void){/*这里写函数内容*/}
void EXTI2_IRQHandler(void){/*这里写函数内容*/}
void EXTI3_IRQHandler(void){/*这里写函数内容*/}
void EXTI4_IRQHandler(void){/*这里写函数内容*/}
void EXTI9_5_IRQHandler(void){/*这里写函数内容*/}
void EXTI15_10_IRQHandler(void){/*这里写函数内容*/}

外部中断的使用

当外部中断触发时,就会在一个叫做外部中断挂起寄存器的特点位置写入数据
也就是一个标志位,可以使用标准库函数读取和更改标准位
每当这个标志位置为设置状态时()就会自动跳转到对应的中断服务函数

为了避免出现异常调用,一般在中断服务函数里做一个验证,读取这个标志位是否为置位状态
而且每当中断服务函数结束并且需要下次中断执行中断服务函数,
则需要在函数的最后清除中断标志位

用这个函数读取中断标志位

ITStatus EXTI_GetITStatus(uint32_t EXTI_Line)

返回值是

RESET            //没触发中断
SET             //触发了中断

这是清除外部中断的标志位的函数

void EXTI_ClearITPendingBit(uint32_t EXTI_Line)

这两个函数的输入值可以是

EXTI_Line0 到 EXTI_Line23
其中EXTI_Line0 到 EXTI_Line15是关于GPIO的外部中断

这是一个使用外部中断的模板

//GPIO初始化
void GPIO(void)
{GPIO_InitTypeDef GPIO_Initstruct;                      //声明GPIO初始化结构体RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);  //打开GPIO时钟GPIO_Initstruct.GPIO_Mode=GPIO_Mode_IN;                  //输入模式GPIO_Initstruct.GPIO_OType=GPIO_OType_OD;                //开漏输入模式GPIO_Initstruct.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;            //引脚0,1GPIO_Initstruct.GPIO_PuPd=GPIO_PuPd_UP;                  //上拉模式GPIO_Initstruct.GPIO_Speed=GPIO_High_Speed;              //高速模式GPIO_Init(GPIOB,&GPIO_Initstruct);                        //初始化GPIO
}
//外部中断初始化
void EXTI_init(void)
{EXTI_InitTypeDef EXTI_Initstruct;                              //创建外部中断初始化结构体RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);         //打开时钟SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB,EXTI_PinSource0);  //将GPIO与外部中断连接SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB,EXTI_PinSource1);  //同上EXTI_Initstruct.EXTI_Line=EXTI_Line0|EXTI_Line1;                           //配置的是外部中断0,1EXTI_Initstruct.EXTI_LineCmd=ENABLE;                           //使能EXTI_Initstruct.EXTI_Mode=EXTI_Mode_Interrupt;                 //选择中断模式EXTI_Initstruct.EXTI_Trigger=EXTI_Trigger_Falling;             //下降沿模式EXTI_Init(&EXTI_Initstruct);                                 //初始化外部中断0,1
}
//配置NVIC
void EXTI_NVIC(void)
{NVIC_InitTypeDef NVIC_Initstruct;                      //声明NVIC初始化结构体NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);           //选定NVIC分组NVIC_Initstruct.NVIC_IRQChannel=EXTI0_IRQn;              //配置的外部中断0NVIC_Initstruct.NVIC_IRQChannelCmd=ENABLE;               //使能NVIC_Initstruct.NVIC_IRQChannelPreemptionPriority=1;   //主优先级NVIC_Initstruct.NVIC_IRQChannelSubPriority=1;            //副优先级NVIC_Init(&NVIC_Initstruct);                          //初始化外部中断0的NVICNVIC_Initstruct.NVIC_IRQChannel=EXTI1_IRQn;             //配置的外部中断1NVIC_Initstruct.NVIC_IRQChannelCmd=ENABLE;               //同上NVIC_Initstruct.NVIC_IRQChannelPreemptionPriority=1;   //同上NVIC_Initstruct.NVIC_IRQChannelSubPriority=2;          //同上NVIC_Init(&NVIC_Initstruct);                            //初始化外部中断1的NVIC
}
//初始化函数
void Init(void)
{GPIO();EXTI_init();EXTI_NVIC();
}
//外部中断0的中断服务函数
void EXTI0_IRQHandler(void)
{if(EXTI_GetITStatus(EXTI_Line0)!=RESET)           //标志位被值位(产生中断){/*需要操作的内容*/EXTI_ClearITPendingBit(EXTI_Line0);         //清除中断标志位}
}
//外部中断1的中断服务函数
void EXTI1_IRQHandler(void)
{if(EXTI_GetITStatus(EXTI_Line1)!=RESET)           //标志位被值位(产生中断){/*需要操作的内容*/EXTI_ClearITPendingBit(EXTI_Line1);         //清除中断标志位}
}

【STM32标准库】【基础知识】外部中断相关推荐

  1. STM32F103标准库开发:外部中断(EXTI)实验

    STM32F103标准库开发----目录 STM32F103标准库开发----外部中断(EXTI)实验----程序源码 本文章技术信息均出自:STM32F103系列超详细参考手册-中文版 一.外部中断 ...

  2. STM32标准库、HAL库特点与应用

    新手在入门STM32的时候,一般大多数都会选用标准库和HAL库,而极少部分人会通过直接配置寄存器进行开发. 对于刚入门的朋友可能没法直观了解这些不同开发发方式彼此之间的区别,本文试图以一种非常直白的方 ...

  3. 【STM32】STM32标准库与HAL库对照学习教程特别篇--系统时钟RCC详讲

    [STM32]STM32标准库与HAL库对照学习教程特别篇--系统时钟RCC详讲 一.前言 二.时钟是什么 三.时钟树 1.时钟树图 2.时钟树讲解 左边部分 中间部分 右边部分 特殊部分 四.初始化 ...

  4. 了解库开发,我们从STM32标准库开发学起

    摘要:从STM32新建工程.编译下载程序出发,让新手由浅入深,尽享STM32标准库开发的乐趣. 自从CubeMX等图像配置软件的出现,同学们往往点几下鼠标就解决了单片机的配置问题.对于追求开发速度的业 ...

  5. 从代码层面分析STM32 标准库和HAL库的差异

      如果用过STM32系列单片机的朋友会比较清楚,一般在开发STM32单片机程序的时候首先要考虑选用那种方式来写代码.常见的有三种方式,寄存器版.标准库版.HAL库版.现在选用后两种的比较多,选择寄存 ...

  6. STM32标准库的引入视频课程-第3季第6部分-朱有鹏-专题视频课程

    STM32标准库的引入视频课程-第3季第6部分-1017人已学习 课程介绍         本课程是<朱有鹏老师单片机完全学习系列课程>第3季第6个课程,本课程详细讲解了STM32官方新标 ...

  7. 视频教程-STM32标准库的引入视频课程-第3季第6部分-单片机/工控

    STM32标准库的引入视频课程-第3季第6部分 互联网课程品牌<朱老师物联网大讲堂>创始人.精通U-Boot.Linux kernel移植及驱动程序开发;精通C.C++.Java.C#等语 ...

  8. IAR新建stm32工程,完美移植stm32标准库(附源码)

    开发环境:Window 10 64bit 开发工具:IAR Embedded Workbench 硬件:stm32f103c8t6 基于IAR 开发工具,新建立STM32F1系列的最小开发例程,并加入 ...

  9. STM32标准库工程中移植TencentOS-tiny

    一.移植前的准备 1. 引言 因为项目的原因需要将原有的标准库工程升级为基于TencentOS-tiny的RTOS工程,所以花费一点时间记录移植过程,提供一份向基于STM32标准库的老工程中移植Ten ...

  10. (一)使用TrueSTUDIO软件新建一个基于STM32标准库工程

    一.TrueSTUDIO说明 不管是还在学习的还是已经工作的应该都很熟悉Keil和IAR这两款用来开发嵌入式的软件,在国内普遍用的这两款编译软件都是破解版的,并没有经过正规渠道授权注册,这就导致了在开 ...

最新文章

  1. 高亮提示、聚焦控件并滚动到浏览器中干好可以查看到该控件的位置
  2. 根据空间线上的两点生成圆柱体 算法
  3. P4318 完全平方数
  4. 中小企业如何巧用大数据?
  5. Delphi动态事件
  6. boost::lambda::switch_statement用法的测试程序
  7. 计算机视觉实时目标检测 TensorFlow Object Detection API
  8. java分割字符串_Java中分割字符串
  9. mysql函数之SUBSTRING_INDEX(str,/,-1)
  10. 一步步编写操作系统 44 用c语言编写内核1
  11. 上班快1个月,老板也不签合同,也没交社保,该怎么办?
  12. 如果有5杯水却来了6个领导,你该怎么办?
  13. NVelocity介绍
  14. ai的预览模式切换_ai模式切换快捷键是什么啊?ai模式切换方法
  15. 泰勒展开-常用优化实例
  16. C++ class 和 struct 构造函数
  17. 手把手教你搭建一个属于自己的网站-适合零基础小白,文末附网站模板
  18. DRILLNET 2.0------第二十四章 井涌模拟分析模型
  19. 查询ip区间的ip地址的sql语句
  20. 《葬花吟》笛箫简谱-红楼梦主题曲

热门文章

  1. 乐视网2018年净亏损40.96亿元 净资产为-30.26亿元
  2. 每个人都应该知道网站建设的制作流程与方法!
  3. 在父亲节到来之际,强烈推荐德国幽默大师的连环漫画《父与子》,父子亲情跃然纸上(多图)...
  4. 她是徐小平前助理,从雷军、刘强东们的日程表看到了商机
  5. 前端笔记5 JQuery 语法及应用
  6. 东北大学校园网一键登录安卓实现
  7. python数据评估
  8. 利用麦咖啡(McAfee)打造超安全的Web站点目录
  9. 计算机考试屏蔽范围,哪些屏蔽设备可用于计算机机房的电磁屏蔽?
  10. Redis | 安装Redis和启动Redis服务