stm32之外部中断该如何使用

发布者:科技徜徉最新更新时间:2021-06-21 来源: eefocus关键字:STM32  外部中断 手机看文章 扫描二维码
随时随地手机看文章

  中断对于开发嵌入式系统来讲的地位绝对是毋庸置疑的,在C51单片机时代,一共只有5个中断,其中2个外部中断,2个定时/计数器中断和一个串口中断,但是在STM32中,中断数量大大增加,而且中断的设置也更加复杂。今天就将来探讨一下关于STM32中的中断系统


  1 基本概念


  ARM Coetex-M3内核共支持256个中断,其中16个内部中断,240个外部中断和可编程的256级中断优先级的设置。STM32目前支持的中断共84个(16个内部+68个外部),还有16级可编程的中断优先级的设置,仅使用中断优先级设置8bit中的高4位。


  STM32可支持68个中断通道,已经固定分配给相应的外部设备,每个中断通道都具备自己的中断优先级控制字节PRI_n(8位,但是STM32中只使用4位,高4位有效),每4个通道的8位中断优先级控制字构成一个32位的优先级寄存器。68个通道的优先级控制字至少构成17个32位的优先级寄存器。


  4bit的中断优先级可以分成2组,从高位看,前面定义的是抢占式优先级,后面是响应优先级。按照这种分组,4bit一共可以分成5组


  第0组:所有4bit用于指定响应优先级;


  第1组:最高1位用于指定抢占式优先级,后面3位用于指定响应优先级;


  第2组:最高2位用于指定抢占式优先级,后面2位用于指定响应优先级;


  第3组:最高3位用于指定抢占式优先级,后面1位用于指定响应优先级;


  第4组:所有4位用于指定抢占式优先级。


  所谓抢占式优先级和响应优先级,他们之间的关系是:具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套。


  当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。每一个中断源都必须定义2个优先级。


  有几点需要注意的是:


  1)如果指定的抢占式优先级别或响应优先级别超出了选定的优先级分组所限定的范围,将可能得到意想不到的结果;


  2)抢占式优先级别相同的中断源之间没有嵌套关系;


  3)如果某个中断源被指定为某个抢占式优先级别,又没有其它中断源处于同一个抢占式优先级别,则可以为这个中断源指定任意有效的响应优先级别。


  2 GPIO外部中断


  STM32中,每一个GPIO都可以触发一个外部中断,但是,GPIO的中断是以组位一个单位的,同组间的外部中断同一时间只能使用一个。比如说,PA0,PB0,PC0,PD0,PE0,PF0,PG0这些为1组,如果我们使用PA0作为外部中断源,那么别的就不能够再使用了,在此情况下,我们只能使用类似于PB1,PC2这种末端序号不同的外部中断源。每一组使用一个中断标志EXTIx。EXTI0 – EXTI4这5个外部中断有着自己的单独的中断响应函数,EXTI5-9共用一个中断响应函数,EXTI10-15共用一个中断响应函数。


  对于中断的控制,STM32有一个专用的管理机构:NVIC。对于NVIC的详细解释,可以参考《ARM Cortex-M3权威指南》,Joseph Yiu著,宋岩译,北京航空航天大学出版社出版,第8章NVIC与中断控制。中断的使能,挂起,优先级,活动等等部都是NVIC在管理的。因为我学习STM32重点在于如何开发程序,所以内部的一些东西,在此我就不详细说明了,有感兴趣的可以参看上面提到的那本数。


  3 程序开发


  其实上面那些基本概念和知识只是对STM32的中断系统有一个大概的认识,用程序说话将会更能够加深如何使用中断。使用外部中断的基本步骤如下:


  1. 设置好相应的时钟;


  2. 设置相应的中断;


  3. IO口初始化;


  4. 把相应的IO口设置为中断线路(要在设置外部中断之前)并初始化;


  5. 在选择的中断通道的响应函数中中断函数。


  由于我用的奋斗开发板没有引出相应的芯片引脚,所以只能用按键来触发相应的中断。根据原理图,K1/K2/K3连接的是PC5/PC2/PC3,因此我将用EXTI5/EXTI2/EXTI3三个外部中断。PB5/PD6/PD3分别连接了三个LED灯。中断的效果是按下按键,相应的LED灯将会被点亮。


  1. 设置相应的时钟


  首先需要打开GPIOB、GPIOC和GPIOE(因为按键另外一端连接的是PE口)。然后由于是要用于触发中断,所以还需要打开GPIO复用的时钟。相应的函数在GPIO的学习笔记中有了详细了解释。详细代码如下:



 void RCC_cfg()


  {


  //打开PE PD PC PB端口时钟,并且打开复用时钟


  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE| RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOB |RCC_APB2Periph_AFIO, ENABLE);


  }



  设置相应的时钟所需要的RCC函数在stm32f10x_rcc.c中,所以要在工程中添加此文件。


  2. 设置好相应的中断


  设置相应的中断实际上就是设置NVIC,在STM32的固件库中有一个结构体NVIC_InitTypeDef,里面有相应的标志位设置,然后再用NVIC_Init()函数进行初始化。详细代码如下:



 void NVIC_cfg()


  {


  NVIC_InitTypeDefNVIC_InitStructure;


  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //选择中断分组2


  NVIC_InitStructure.NVIC_IRQChannel= EXTI2_IRQChannel; //选择中断通道2


  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0; //抢占式中断优先级设置为0


  NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0; //响应式中断优先级设置为0


  NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //使能中断


  NVIC_Init(&NVIC_InitStructure);


  NVIC_InitStructure.NVIC_IRQChannel=EXTI3_IRQChannel; //选择中断通道3


  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 1; //抢占式中断优先级设置为1


  NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1; //响应式中断优先级设置为1


  NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //使能中断


  NVIC_Init(&NVIC_InitStructure);


  NVIC_InitStructure.NVIC_IRQChannel= EXTI9_5_IRQChannel; //选择中断通道5


  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 2; //抢占式中断优先级设置为2


  NVIC_InitStructure.NVIC_IRQChannelSubPriority= 2; //响应式中断优先级设置为2


  NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //使能中断


  NVIC_Init(&NVIC_InitStructure);


  }



  由于有3个中断,因此根据前文所述,需要有3个bit来指定抢占优先级,所以选择第2组。又由于EXTI5-9共用一个中断响应函数,所以EXTI5选择的中断通道是EXTI9_5_IRQChannel,详细信息可以在头文件中查询得到。用到的NVIC相关的库函数在stm32f10x_nivc.c中,需要将此文件复制并添加到工程中。具体位置可以查看关于GPIO的笔记。这段代码编译起来没有任何问题,但是在链接的时候就会报错,需要把STM32F10xR.LIB加入工程中,具体位置在…KeilARMRV31LIBSTSTM32F10xR.LIB。


  3. IO口初始化



void IO_cfg()


  {


  GPIO_InitTypeDefGPIO_InitStructure;


  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2; //选择引脚2


  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //输出频率最大50MHz


  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //带上拉电阻输出


  GPIO_Init(GPIOE,&GPIO_InitStructure);


  GPIO_ResetBits(GPIOE,GPIO_Pin_2); //将PE.2引脚设置为低电平输出


  GPIO_InitStructure.GPIO_Pin= GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5; //选择引脚2 3 5


  GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IN_FLOATING; //选择输入模式为浮空输入


  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //输出频率最大50MHz


  GPIO_Init(GPIOC,&GPIO_InitStructure); //设置PC.2/PC.3/PC.5


  GPIO_InitStructure.GPIO_Pin= GPIO_Pin_3 |GPIO_Pin_6; //选择引脚3 6


  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //输出频率最大50MHz


  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //带上拉电阻输出


  GPIO_Init(GPIOD,&GPIO_InitStructure);


  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5; //选择引脚5


  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //输出频率最大50MHz


  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //带上拉电阻输出


  GPIO_Init(GPIOB,&GPIO_InitStructure);


  }


  其中连接外部中断的引脚需要设置为输入状态,而连接LED的引脚需要设置为输出状态,初始化PE.2是为了使得按键的另外一端输出低电平。GPIO中的函数在stm32f10x_gpio.c中。


  4. 把相应的IO口设置为中断线路


  由于GPIO并不是专用的中断引脚,因此在用GPIO来触发外部中断的时候需要设置将GPIO相应的引脚和中断线连接起来,具体代码如下:



 void EXTI_cfg()


  {


  EXTI_InitTypeDefEXTI_InitStructure;


  //清空中断标志


  EXTI_ClearITPendingBit(EXTI_Line2);


  EXTI_ClearITPendingBit(EXTI_Line3);


  EXTI_ClearITPendingBit(EXTI_Line5);


  //选择中断管脚PC.2 PC.3 PC.5


  GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource2);


  GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource3);


  GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5);


  EXTI_InitStructure.EXTI_Line= EXTI_Line2 | EXTI_Line3 | EXTI_Line5; //选择中断线路2 3 5


  EXTI_InitStructure.EXTI_Mode= EXTI_Mode_Interrupt; //设置为中断请求,非事件请求


  EXTI_InitStructure.EXTI_Trigger= EXTI_Trigger_Rising_Falling; //设置中断触发方式为上下降沿触发


  EXTI_InitStructure.EXTI_LineCmd=ENABLE; //外部中断使能


  EXTI_Init(&EXTI_InitStructure);


  }


  EXTI_cfg中需要调用到的函数都在stm32f10x_exti.c。


  5. 写中断响应函数


  STM32不像C51单片机那样,可以用过interrupt关键字来定义中断响应函数,STM32的中断响应函数接口存在中断向量表中,是由启动代码给出的。默认的中断响应函数在stm32f10x_it.c中。因此我们需要把这个文件加入到工程中来。


  在这个文件中,我们发现,很多函数都是只有一个函数名,并没有函数体。我们找到EXTI2_IRQHandler()这个函数,这就是EXTI2中断响应的函数。我的目标是将LED灯点亮,所以函数体其实很简单:



 voidEXTI2_IRQHandler(void)


  {


  //点亮LED灯


  GPIO_SetBits(GPIOD,GPIO_Pin_6);


  //清空中断标志位,防止持续进入中断


  EXTI_ClearITPendingBit(EXTI_Line2);


  }


  voidEXTI3_IRQHandler(void)


  {


  GPIO_SetBits(GPIOD,GPIO_Pin_3);


  EXTI_ClearITPendingBit(EXTI_Line3);


  }


  voidEXTI9_5_IRQHandler(void)


  {


  GPIO_SetBits(GPIOB,GPIO_Pin_5);


  EXTI_ClearITPendingBit(EXTI_Line5);


  }



  由于EXTI5-9是共用一个中断响应函数,因此所有的EXTI5 – EXTI9的响应函数都写在这个里面。


  6. 写主函数



 #include"stm32f10x_lib.h"


  void RCC_cfg();


  void IO_cfg();


  void EXTI_cfg();


  void NVIC_cfg();


  int main()


  {


  RCC_cfg();


  IO_cfg();


  NVIC_cfg();


  EXTI_cfg();


  while(1);


  }



  main函数前是函数声明,main函数函数体中都是调用初始化配置函数,然后进入死循环,等待中断响应。


  由于文中牵涉到很多库函数,我们可以通过查找库函数说明文档来了解相应的函数有些什么作用,在《ARM®-based32-bit MCU STM32F101xx and STM32F103xx firmware library》中。网上也有中文版的说明文档可供参考。


关键字:STM32  外部中断 引用地址:stm32之外部中断该如何使用

上一篇:关于STM32F中按键中断分析
下一篇:单片机学习笔记之--SPI通信基础

推荐阅读最新更新时间:2024-11-08 13:20

工作问题笔记-----STM32休眠问题
STM32低功耗分三种: SLEEP: 电压调节器开启,Cortex-M3内核停止运行,外设保持运行态; STOP: 电压调节器可选择性开启,所有外设时钟、PLL、HSI和HSE被关闭,Cortex-M3内核和所有外设停止运行,保留SRAM和寄存器的内容; STANDBY: 待机模式Standby:电压调节器关闭、整个1.8v区域断电。除了备份区域和待机电路的寄存器以外,SRAM和寄存器的内容全部丢失。 在休眠状态下,MCU的代码并不会继续执行,而是进入休眠状态,等待唤醒,唤醒的过程会先执行IRQ中断服务函数,然后再执行WFI后的函数。 省电级别由低到高,standby休眠后会让我们的数据丢失,而SLEE
[单片机]
STM32处理器 RTC分析
前言: 1.博客基于ARM Cortex-M3内核的STM32F103ZET6和标准3.5.0库; 2.如有不足之处,还请多多指教 一 RTC是什么? 1. 从结构上讲就是一个独立的定时器; 2. 从功能上来说就是为系统提供系统掉电不复位的日历时间; RTC分为两个完全能独立的部分:1. APB1接口;2. RTC核心; 功能: (1)APB1总线连接APB1接口并负责驱动APB1接口,接口内部包含一组16位寄存器,可以通过APB1总线对其进行读写操作。 (2)RTC核心由RTC20位预分频模块和32位可编程计数器模块组成; Ⅰ RTC预分频模块包含一个20位的可编程分频器RTC_DIV。预分频模块为32位计数器模块提供时
[单片机]
<font color='red'>STM32</font>处理器 RTC分析
基于STM32设计的计算器(实现基本运算)
1. 项目介绍 计算器是最常见的工具了,现在不管是手机、电脑都带有计算器功能,支持强大的科学运算等。 当前文章介绍的是STM32+LCD触摸屏设计的一个触摸计算器功能,实现基本的加减乘除,二进制转换显示等功能。LCD屏使用的是3.5寸带触摸屏的显示屏,方便操作屏幕,MCU采用STM32F103ZET6。 设计的这个计算器用到的硬件不多,主要是LCD屏和触摸屏,用到了一个W25Q64存储芯片,保存触摸屏校准后的一些配置数据,这个可有可无,只是方便不需要每次断电后重新校准。 运行效果图如下: 完整项目源码下载地址: https://download.csdn.net/download/xiaolong112662
[单片机]
基于<font color='red'>STM32</font>设计的计算器(实现基本运算)
ARM、ST与MATHWORKS携手实现支持STM32 MCU代码生成等功能
ARM与意法半导体(STMicroelectronics)携手宣布首款配合MATLAB和 Simulink支持ARM® Cortex™-M系统的Embedded Coder已上市。 意法半导体与ARM的合作项目获得MathWorks的全面支持,使软件开发人员能够在MATLAB和Simulink环境中开发算法,然后在处理器在环(PIL)仿真中编译目标,集成、调试和测试这些模型。Embedded Coder生成的C代码运行于STM32评估板上,Keil™微控制器开发套件(MDK-ARM™)的调试器与Simulink直接交互,进一步简化了代码集成过程。 意法半导体微控制器产品部总经理Michel Buffa表示:“基于消费者对MATL
[单片机]
STM32低功耗停止模式 以及简述判断中断的两种方式
#include wkup.h #include led.h #include delay.h ////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK战舰STM32开发板 //待机唤醒 代码 //正点原子@ALIENTEK //技术论坛:www.openedv.com //修改日期:2012/9/7 //版本:V1.0 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019 /
[单片机]
stm32中printf要做哪些配置
在调试代码时,我们经常用printf函数来输出一些打印信息,那么你的UART串口不够用,还要用printf要怎么办? 其实很简单,就是:使用SWO/SWV。 SWO:Serial Wire Output,串行线输出 SWD:Serial Wire Viewer,串行线查看器 使用printf要做哪些配置? 一、对工程属性进行配置,详细步骤如下 1、首先要在你的main 文件中 包含“stdio.h” (标准输入输出头文件)。 2、在main文件中重定义《fputc》函数 3、在工程属性的 “Target“ -》 ”Code Generation“ 选项中勾选 ”Use MicroLIB“” MicroLIB 是缺省C的备份库,
[单片机]
keil环境下STM32使用printf
1、首先需要设置keil ! (https://img-blog.csdn.net/20180509170628341?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmd6aGltaW5fMDcwMg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) 2、添加头文件 3、在代码中增加两段代码 增加第一段代码: #ifdef __GNUC__ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PR
[单片机]
GD32单片机STM32远程下载手机程序升级固件下载局域网网页升级工具
GD32、STM32单片机,是我们最常见的一种MCU。通常我们在使用STM32单片机都会遇到程序在线升级下载的问题。 GD32/STM32单片机的在线下载通常需要以下几种方式完成: 1、使用ST/GD提供的串口下载工具,本地完成固件的升级下载。 2、自行完成系统BootLoader的编写,将系统程序分为BootLoader和APP两个部分,BootLoader完成固件升级。 3、使用STM32/GD固件服务器,完成固件的升级,固件服务器https://simplewifi.taobao.com/ 几种方式各有优缺点: 使用ST提供的方法进行固件升级,方法简单,不需要额外的开发。但是,只能本地完成STM32单片机的升级。
[单片机]
GD32单片机<font color='red'>STM32</font>远程下载手机程序升级固件下载局域网网页升级工具
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved