STM32的中断介绍

这篇具有很好参考价值的文章主要介绍了STM32的中断介绍。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、STM32中断应用概览

(1)简介

(2)中断编程的顺序:

1.使能中断请求:

2.中断优先级分组:

3.配置NVIC寄存器,初始化NVIC_InitTypeDef;

4.编写中断服务函数

二、EXTI—外部中断/事件控制器

(1)简介

(2)EXTI结构图

(3)初始化结构体成员

(4)程序设计:

1.初始化要连接到EXTI的GPIO。

2.初始化EXTI用于产生中断/事件

3.初始化NVIC,用于处理中断

4.编写中断服务函数

5.main函数

一、STM32中断应用概览

(1)简介

STM32 中断非常强大,每个外设都可以产生中断,所以中断的讲解放在哪一个外设里面去讲都不合适,这里单独抽出一章来做一个总结性的介绍。

中断:把正常正在运行的程序打断,运行中断服务函数,运行完之后再回到主程序,与51大体相仿。

外部中断,体现在外设水平,系统异常,体现在内核水平。下面,中断就是异常,异常就是中断。

STM32的中断介绍

 STM32的中断介绍

STM32的中断介绍

 以上向量表中,灰色标住的是体现在内核水平的(异常),其余的是外设水平的(外部中断)。

中断由NVIC这个外设来控制。

NVIC:嵌套向量中断控制器,属于内核外设,管理着包括部分内核和片上所有外设的中断相关的功能。 两个重要的库文件:core_cm3.h(定义所有内核上面的寄存器,NVIC寄存器就在这里面)和misc.h(相关的函数)。

对于中断而言,最重要的是优先级,由NVIC->IPRx(中断优先级寄存器)设定。打开内核寄存器的手册,

STM32的中断介绍

 这个表里面的0-80对应着向量表里面外部中断的位置0-59,每一位都有8位位宽,真正起作用的只有4位。

STM32的中断介绍

函数:

NVIC_SetPriority (IRQn_Type IRQn, uint32_t priority)

// core_cm3.h 1586行

两个形参:中断号优先级。中断号对应手册向量表的位置编号。

配置的时候先判断中断号是否大于0,小于0是内核的中断;大于0是外部中断。如果是外部中断,让优先级左移4位。如果是小于0,就配置另一个寄存器,SCB->SHP。

(2)中断编程的顺序:

1-使能中断请求

2-配置中断优先级分组

3-配置NVIC寄存器,初始化NVIC_InitTypeDef;

4-编写中断服务函数

1.使能中断请求:

这个与具体外设相关。以串口为例,发送数据完成之后,产生一个中断。我们去具体寄存器寻找,在控制寄存器 1(USART_CR1)里面有一位如下图,将这一位置即可。

STM32的中断介绍

2.中断优先级分组:

内核和外设的寄存器的优先级哪个更高取决于优先级分组,这个则是由寄存器SCB->AIRCR:PRIGROUP[10:8] 来配置的。

函数:

NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)  

 // misc.c  96行

STM32的中断介绍

STM32的中断介绍

优先级分组1:一个位表示主优先级,剩下三个位表示子优先级。

判断优先级:分组>主优先级>子优先级.如果都相同,则看硬件中断编号(中断向量表)。

3.配置NVIC寄存器,初始化NVIC_InitTypeDef;

初始化的成员在 //misc.h  50行

typedef struct
{
  uint8_t NVIC_IRQChannel;                    //指定中断源          

  uint8_t NVIC_IRQChannelPreemptionPriority;  //设置抢占优先级(主优先级),
                                              //中断优先级分组不同,抢占优先级的位数不同。
                                              //如果分组为1,主优先级位数为1,
                                              //那么主优先级只能为0或1

  uint8_t NVIC_IRQChannelSubPriority;         //设置子优先级如果前面分组为1,主优先级为1,
                                              //子优先级就为3,2的3次方为8
                                              //(即0-78个数随便写),让他等于0即可。

  FunctionalState NVIC_IRQChannelCmd;         //使能或者失能
   
} NVIC_InitTypeDef;

注意:

无论是抢占优先级(主优先级)还是响应优先级(子优先级),优先级数值越小,就代表优先级越高。

优先级较高的中断可以打断优先级较低的中断。

抢占优先级相同且响应优先级相同的中断,假如同时发生,会按照硬件内部固定的优先级执行。

中断优先级的分组对内核和外设同样适用。当比较的时候,只需要把内核外设的中断优先级的四个位按照外设的中断优先级来分组来解析即可,即人为的分出抢占优先级和子优先级。

4.编写中断服务函数

中断服务函数名一定要与中断向量表里面的名称一样。工程很大的话,就把所有的中断放在一个文件下,一般把中断服务函数放在stm32f10x_it.c中。

二、EXTI—外部中断/事件控制器

(1)简介

EXTI管理了控制器的20个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。EXTI可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。

外部:芯片里的GPIO。可以对外输出0或1,输入的时候也可以检测输入的是0还是1.当出现0和1之间变化的时候,就会产生一个中断,也可以产生一个事件。

(2)EXTI结构图

红色是中断,绿色是事件。

STM32的中断介绍

 输入线:EXTI 0-15是连接到GPIO的(每一个GPIO端口都有16个引脚),当我们使用EXTI0的时候,控制的是所有端口的第0个引脚。具体是哪个端口,在AFIO_EXTICR1、2、3、4这4个寄存器的EXTIx[3:0]位控制。(x属于0-15)

边沿检测电路:检测上升沿还是下降沿,由上升沿触发选择寄存器(EXTI_RTSR)和下降沿触发选择寄存器(EXTI_FTSR)控制。

或门:收到边沿检测电路传出的信号和软件中断事件寄存器(EXTI_SWIER)控制。软件中断事件寄存器返回1之后,就不受边沿检测电路控制。

在经过或门之后,分为两路:当中断屏蔽寄存器和请求挂起寄存器相关位都置1的时候就会产生中断,交给NVIC,再交给内核相应。如果事件屏蔽寄存器相关位置1,就会把这个1信号给脉冲发生器,产生脉冲(脉冲就是高电平)。脉冲:ITM定时器开始计数、触发ADC的采集。【作为触发信号】

STM32的中断介绍

(3)初始化结构体成员

EXTI_InitTypeDef

1-EXTI_Line:用于产生中断/事件线(框图里的输入线)

2-EXTI_Mode:EXTI模式(中断/事件)(中断屏蔽寄存器/事件屏蔽寄存器)

3-EXTI_Trigger:触发(上升沿/下降沿/上下)

4-EXTI_LineCmd:使能或者失能(IMR/EMR)

(4)程序设计:

通过两个按键控制,PA0上升沿(按下)触发,PC13下降沿(弹开)触发。产生一次中断,LED反转一次。

思路设计:

先配置外设(按键等)用到的外部中断(EXTI)

  功能:初始化外设(按键等)要连接到 EXTI 的 GPIO。

        配置 EXTI 结构体,初始化 EXTI,产生中断信号。

再配置NVIC中断控制器

  功能:配置中断优先级分组,再初始化 NVIC 结构体,然后初始化 NVIC 去处理中断。

1.初始化要连接到EXTI的GPIO。

1.观察外设(GPIO)端口结构体的成员:端口、速度、输出/入方式,我们把常用到的端口、宏定义(与硬件相关的)用我们熟悉的/好理解的名字在bsp_led.h文件里面重新define宏定义一下。一般情况下,GPIO端口的重新宏定义包括APB2时钟、具体哪个GPIOX(ABCD)端口、GPIOX的管脚pin。

2.在bsp_led.c文件里面把GPIO初始化好,详细步骤参见上面初始化I/O口的步骤:打开GPIO的时钟;配置外设初始化结构体;调用外设初始化函数,把配置好的结构体成员写到寄存器里面。

	GPIO_InitTypeDef GPIO_InitStruct;//外设的初始化结构体变量
	EXTI_InitTypeDef EXTI_InitStruct;//外设的初始化结构体变量
 	NVIC_Config();
    /*第一步:初始化要连接到 EXTI 的 GPIO*/
	/*1:打开外设的时钟(RCC寄存器控制)*/
	RCC_APB2PeriphClockCmd(KEY1_EXTI_GPIO_CLK |KEY2_EXTI_GPIO_CLK,ENABLE);
	
	/*2:配置外设初始化结构体*/
	GPIO_InitStruct.GPIO_Pin = KEY1_EXTI_GPIO_PIN;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStruct.GPIO_Pin = KEY2_EXTI_GPIO_PIN;
	/*3:调用外设(GPIO)初始化函数,把配置好的结构体成员写到寄存器里面*/
	GPIO_Init(KEY1_EXTI_GPIO_PORT,&GPIO_InitStruct);//初始化端口
	GPIO_Init(KEY2_EXTI_GPIO_PORT,&GPIO_InitStruct);//初始化端口

2.初始化EXTI用于产生中断/事件

   和第一步一样,先观察该外设(EXTI)的初始化结构体成员:

typedef struct
{
  uint32_t EXTI_Line;               //哪一条输入线(总共20条)   

  EXTIMode_TypeDef EXTI_Mode;       //这条线的模式(中断/事件)

  EXTITrigger_TypeDef EXTI_Trigger; //触发选择(上升/下降/同时)

  FunctionalState EXTI_LineCmd;     //使能

}EXTI_InitTypeDef;

把需要宏定义的变量定义好:

#define KEY1_EXTI_GPIO_PORTSOURCE  GPIO_PortSourceGPIOA//中断输入线属于哪个端口
#define KEY2_EXTI_GPIO_PORTSOURCE  GPIO_PortSourceGPIOC

#define KEY1_EXTI_GPIO_PINSOURCE   GPIO_PinSource0//中断输入线属于哪个引脚
#define KEY2_EXTI_GPIO_PINSOURCE   GPIO_PinSource13

#define KEY1_EXTI_LINE             EXTI_Line0//选择哪条输入线
#define KEY2_EXTI_LINE             EXTI_Line13

根据前面讲解的功能框图,打开AFIO的时钟;确定中断输入线用到哪个端口、哪个引脚(函数作用为选择用作EXTI线的GPIO引脚);配置初始化结构体;调用 EXTI 初始化函数,把配置好的结构体成员写到寄存器里面。至此中断信号已经产生。

到这就可以发现,这些配置寄存器的方法都大体相同。

    /*第二步:初始化EXTI外设*/	
	/*1:打开外设的时钟(RCC寄存器控制)*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	/*2.确定中断输入线用到哪个端口、哪个引脚*/
	GPIO_EXTILineConfig(KEY1_EXTI_GPIO_PORTSOURCE, KEY1_EXTI_GPIO_PINSOURCE);
	/*3.配置初始化结构体*/
	EXTI_InitStruct.EXTI_Line = KEY1_EXTI_LINE;//选择哪条输入线
	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;//这条线的模式(中断/事件)
	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;//触发选择(上升/下降/同时)
	EXTI_InitStruct.EXTI_LineCmd = ENABLE;//使能
	/*4.调用 EXTI 初始化函数,把配置好的结构体成员写到寄存器里面*/
	EXTI_Init(&EXTI_InitStruct);
	
	/*2.确定中断输入线用到哪个端口、哪个引脚*/
	GPIO_EXTILineConfig(KEY2_EXTI_GPIO_PORTSOURCE, KEY2_EXTI_GPIO_PINSOURCE);
	/*3.配置初始化结构体*/
	EXTI_InitStruct.EXTI_Line = KEY2_EXTI_LINE;//选择哪条输入线
	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;//这条线的模式(中断/事件)
	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;//触发选择(上升/下降/同时)
	EXTI_InitStruct.EXTI_LineCmd = ENABLE;//使能
	/*4.调用 EXTI 初始化函数,把配置好的结构体成员写到寄存器里面*/
	EXTI_Init(&EXTI_InitStruct);
	//至此,中断信号已经产生	

3.初始化NVIC,用于处理中断

   先配置中断优先级分组,再初始化NVIC的初始化结构体,然后调用初始化NVIC外设函数,把配置好的结构体成员写到寄存器里面。

static void NVIC_Config(void)//配置NVIC中断控制器  静态的函数,表示只能在这个文件中使用
{
	NVIC_InitTypeDef NVIC_InitTStruct;//初始化结构体的变量
	/*第一步:配置中断优先级分组*/
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	/*第二步:初始化 NVIC 的初始化结构体*/
	NVIC_InitTStruct.NVIC_IRQChannel = KEY1_EXTI_IRQN;
	NVIC_InitTStruct.NVIC_IRQChannelPreemptionPriority = 1;//前面配置的中断优先级分组为1,主优先级只有一个位来表示
	NVIC_InitTStruct.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitTStruct.NVIC_IRQChannelCmd = ENABLE;
	/*第三步:调用初始化NVIC外设函数,把配置好的结构体成员写到寄存器里面*/
	NVIC_Init(&NVIC_InitTStruct);
	
	/*第二步:初始化 NVIC 的初始化结构体*/
	NVIC_InitTStruct.NVIC_IRQChannel = KEY2_EXTI_IRQN;
	NVIC_InitTStruct.NVIC_IRQChannelPreemptionPriority = 1;//前面配置的中断优先级分组为1,主优先级只有一个位来表示
	NVIC_InitTStruct.NVIC_IRQChannelSubPriority = 1;//这样key1的中断优先级就大于key2的
	NVIC_InitTStruct.NVIC_IRQChannelCmd = ENABLE;
	/*第三步:调用初始化NVIC外设函数,把配置好的结构体成员写到寄存器里面*/
	NVIC_Init(&NVIC_InitTStruct);
}

4.编写中断服务函数

  首先,有一个检测是否产生中断的函数,如果产生了中断,就……

void  KEY1_EXTI_IRQHandler(void)
{
	if(EXTI_GetITStatus(KEY1_EXTI_LINE) != RESET )//如果产生了中断
	{
		LED1_TOGGLE;//LED1 亮灭反转
	}
	EXTI_ClearITPendingBit(KEY1_EXTI_LINE);//清除相关的中断标志位
} 

void  KEY2_EXTI_IRQHandler(void)
{
	if(EXTI_GetITStatus(KEY2_EXTI_LINE) != RESET )//如果产生了中断
	{
		LED2_TOGGLE;//LED1 亮灭反转
	}
	EXTI_ClearITPendingBit(KEY2_EXTI_LINE);//清除相关的中断标志位
} 

5.main函数

等待外部中断的到来,然后去中断服务函数里面执行程序。文章来源地址https://www.toymoban.com/news/detail-417958.html

int main(void)
{
	/*在程序来到main函数这里的时候,系统时钟已经配置成72M*/
	
	LED_GPIO_Config();//初始化函数
	
	/*等待外部中断的到来,然后去中断服务函数里面执行程序*/
	EXTI_KEY_Config();
	while(1)
	{
		
	}
}

到了这里,关于STM32的中断介绍的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • stm32标准库和HAL库的对比学习3.《学习外部中断EXIT和应用》

            本人是大一的学生,学习了一段时间的stm32,此系列博客为个人的学习笔记,方便个人复习,如有错误或问题,非常非常欢迎大家来大力指正。 简单用文字说一下原理。 如果先要清楚了解建议去b站看一下keysking大佬的教程,很有趣易懂( 本视频的部分图也来自keys

    2024年01月19日
    浏览(48)
  • STM32学习笔记(四)丨TIM定时器及其应用(定时中断、内外时钟源选择)

    ​  本次课程采用单片机型号为STM32F103C8T6。 ​  课程链接:江科大自化协 STM32入门教程   往期笔记链接:   STM32学习笔记(一)丨建立工程丨GPIO 通用输入输出   STM32学习笔记(二)丨STM32程序调试丨OLED的使用   STM32学习笔记(三)丨中断系统丨EXTI外部中断

    2023年04月13日
    浏览(63)
  • 明解STM32—GPIO应用设计篇之IO外部中断EXTI原理及使用方法

    ​ 一、前言         在之前针对STM32的GPIO相关API函数及配置使用进行了详细的介绍,GPIO作为输入引脚时,调用相关读信号引脚函数接口就可以在程序的循环中,轮询的对输入信号进行读取检测操作,除了轮询的方式访问输入引脚,还可以通过另外一种叫做外部中断的方式

    2024年02月08日
    浏览(46)
  • 7、江科大stm32视频学习笔记——中断的应用:对射式红外传感器计次&旋转编码器计次

    目录 1、标志位函数 2、 初始化的中断的步骤 3、对射式红外传感器计次 (1)接线图 (2)CountSensor.c (3)main.c 4、旋转编码器计次 (1)接线图(旋转编码器接在PB1、PB0引脚) (2)Encoder.c (3)main.c 5、建议 //在 主程序 中查看标志位和清楚标志位,用以下两个函数,能不能

    2024年02月11日
    浏览(47)
  • (STM32)中断系统和外部中断

    中断系统:是执行和管理中断的逻辑结构 外部中断:是众多能产生中断的外设之一 中断:指的是中断源(中断通道),中断产生CPU暂停正在执行程序,去执行中断程序,然后返回。提高效率 F1系列的STM32有68个中断源,不同系列需要看手册 EXTI(外部中断)、TIM、ADC、USART、SPI、

    2024年02月06日
    浏览(43)
  • stm32 OV7670摄像头模块的介绍以及应用(SCCB的使用)

    今天学习摄像头模块,使用该模块进行拍摄,照相等功能进行对stm32 控制板的结合,了解他的原理以及应用。 主角: ov7670摄像头模块。(大概了解一下产品背景)  OV7670 是 OV( OmniVision)公司生产的一颗 1/6 寸的 CMOS VGA 图像传 感器。该传感器体积小、工作电压低,提供单片

    2023年04月09日
    浏览(54)
  • 【STM32】STM32学习笔记-TIM定时中断(13)

    TIM(Timer)定时器 定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断 16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时 不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码

    2024年01月17日
    浏览(46)
  • STM32 HAL库 STM32CubeMx -- 外部中断

    中断,是指处理机处理程序运行中出现的紧急事件的整个过程。程序运行过程中,系统外部、系统内部或者现行程序本身若出现紧急事件,处理机立即中止现行程序的运行,自动转入相应的处理程序(中断服务程序),待处理完后,再返回原来的程序运行,这整个过程称为程序

    2024年02月08日
    浏览(47)
  • 【STM32】STM32学习笔记-EXTI外部中断(11)

    中断 :在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行 中断优先级 :当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加

    2024年02月04日
    浏览(40)
  • STM32_串口中断接收数据_空闲中断

    引言: 1、串口中断接收数据首先要保证完整性(设置串口中断优先级) 2、串口中断接收数据要保证实时性(打开串口空闲中断——空闲时间是2个字节的时间) 3、串口中断接收+DMA缓存,等到需要处理时候在进行处理数据 方法一:直接利用stm32的RXNE和IDLE中断进行接收不定字

    2024年02月13日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包