STM32-中断应用

发布者:SecretWhisper最新更新时间:2017-10-26 来源: eefocus关键字: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在管理的。

3 、程序开发

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

1.设置好相应的时钟;

2.设置相应的中断;

3.IO口初始化;

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

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

 

实验过程:通过按键来触发相应的中断。根据原理图,K2/K1/K0连接的是PE2/PE3/PE4,因此我将用EXTI2/EXTI1/EXTI0三个外部中断。PB5/PE5分别连接了两个LED灯。中断的效果是按下按键,相应的LED灯将会被操作。

 

1.设置相应的时钟

首先需要打开GPIOB、GPIOE(因为按键另外一端连接的是PE口)。然后由于是要用于触发中断,所以还需要打开GPIO复用的时钟。详细代码如下:

void RCC_cfg()

{

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

       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);

}

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

 

2.设置好相应的中断

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

void NVIC_cfg()

{

        NVIC_InitTypeDef NVIC_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 = EXTI1_IRQChannel;            //选择中断通道1

        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 = EXTI0_IRQChannel;  //选择中断通道0

        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组。

 

3.IO口初始化

void IO_cfg()

{

       GPIO_InitTypeDef GPIO_InitStructure;

///////////LED//////////////

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

       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_PP; //选择输入模式推挽输出

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

       GPIO_Init(GPIOE,&GPIO_InitStructure);                                 //设置PE5

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

       GPIO_Init(GPIOB,&GPIO_InitStructure);                                 //设置PB5

/////////KEY/////////////////////////

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;      //选择引脚2,3,4

       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|GPIO_Pin_3|GPIO_Pin_4);     //初始化将PE.2引脚设置为低电平输出    

}

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

 

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

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

void EXTI_cfg()

{

       EXTI_InitTypeDef EXTI_InitStructure;

       //清空中断标志

       EXTI_ClearITPendingBit(EXTI_Line2);

       EXTI_ClearITPendingBit(EXTI_Line3);

       EXTI_ClearITPendingBit(EXTI_Line4);

 

       //选择中断管脚PE.2 PE.3 PE.4

       GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource2);

       GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource3);

       GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource4);

 

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

       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灯点亮,所以函数体其实很简单:

void EXTI2_IRQHandler(void)

{

       //点亮LED灯

       GPIO_SetBits(GPIOB,GPIO_Pin_5);

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

       EXTI_ClearITPendingBit(EXTI_Line2);

}

 

void EXTI3_IRQHandler(void)

{

       GPIO_SetBits(GPIOe,GPIO_Pin_5);

       EXTI_ClearITPendingBit(EXTI_Line3);

}

 

void EXTI4_IRQHandler(void)

{

       GPIO_SetBits(GPIOB,GPIO_Pin_5);

       GPIO_SetBits(GPIOE,GPIO_Pin_5);

       EXTI_ClearITPendingBit(EXTI_Line4);

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函数函数体中都是调用初始化配置函数,然后进入死循环,等待中断响应。


关键字:STM32  中断应用 引用地址:STM32-中断应用

上一篇:STM32-系统时钟
下一篇:STM32 GPIO口的使用

推荐阅读最新更新时间:2024-03-16 15:41

STM32 中断使用
STM32中断有时候用多了容易乱,特此记录一下,因为之前一直是M3 M0交叉用,固件库有些区别容易弄混,这里说一下M3外部中断的配置 步骤: 1.将对应的IO配置为输入 2.将IO对应的中断的优先等级用NVIC配置好 3.设置好对应IO的中断模式和触发方式 4.将IO所属的中断线设为中断输入源 1---------以PB5为例子 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_Init(G
[单片机]
掌握这三个思路告诉你如何使用STM32测量频率和占空比
题目 (1)测量脉冲信号频率fo,频率范围为10Hz~2MHz,测量误差的绝对值不大于0.1%。 (2)测量脉冲信号占空比D,测量范围为10%~90%,测量误差的绝对值不大于2%。 使用官方STM32F429 Discovery开发板,主频180MHz,定时器频率90MHz。 思路一、外部中断 这种方法是很容易想到的,而且对几乎所有MCU都适用(连51都可以)。方法也很简单,声明一个计数变量TIM_cnt,每次一个上升沿/下降沿就进入一次中断,对TIM_cnt++,然后定时统计即可。如果需要占空比,那么就另外用一个定时器统计上升沿、下降沿之间的时间即可。 缺陷显而易见,当频率提高,将会频繁进入中断,占用大量时间。而当频
[单片机]
掌握这三个思路告诉你如何使用<font color='red'>STM32</font>测量频率和占空比
STM32关于NVIC寄存器方向理解
中断向量嵌套控制器是用来管理所有中断和事件的,包括中断的使能和除能,中断的优先级。这个是属于内核的东西,所以ST的参考手册上对它的描述较少,但他又是十分重要的东西,要了解它就要看ARM的《Cortex™-M4 Devices Generic User Guide》。 相关寄存器 译自《Cortex™-M4 Devices Generic UserGuide》,若有错误,请以原文为准。 中断使能寄存器NVIC_ISER 中断使能寄存器共有8个,ISER 设置0~31号中断的使能,ISER 设置32~63号中断的使能,如此类推。以下以ISER 为例: SETENA中断设置使能位。 写: 0 =无影响 1 =使能中断。
[单片机]
<font color='red'>STM32</font>关于NVIC寄存器方向理解
STM32单片机串口通讯代码
简介:在STM32开发中,串口是我们最常用的接口。通过串口,我们很方便地把数据输出到电脑,方便我们进行程序调试。下面我们来看看STM32的串口通讯代码。 要实现串口通讯,我们要进行下面几个步骤: 首先:要打开GPIO口的时钟和串口模块时钟。在圆点博士小四轴中,我们用的是GPIOA和COM1模块。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); 其次:要指定GPIO口,即确定哪些IO是用于串口通讯的。记得使用GPIO_Mode_AF_PP模式
[单片机]
基于Cortex-M3内核处理器的嵌入式Web服务器
   引言   目前,网络化控制己成为远程控制的主要研究方向,利用网络实现对局域乃至全球范围内设备的监控是工业控制系统的发展趋势 。嵌入式Internet远程监控技术作为网络化控制的代表,它解决了工业控制领域中异构网络互联问题,提高了传统装备的智能化水平,促进了传统产业结构的调整。嵌入式Web服务器尤其适用于嵌入式Internet应用,它通过Ethernet或Modem的连接可以轻松连接到任何网络,真正实现对设备的远程管理和控制。    实现方案   嵌入式Web服务器必须具备的基本功能包括:可控制与其连接的设备并获取设备的状态和数据;现场信息可以网页形式发布;可及时响应远程用户的控制命令。此外,嵌入式设备应具有功能简
[嵌入式]
关于STM32 ST-LINK Utility查看内核运行状态,助你判断程序是否跑飞
本文围绕STM32 ST-LINK Utility讲几点主要功能及相关拓展知识: 1.STM32编程下载; 2.利用该编程工具查看内核运行状态; 3.Option Bytes选项字配置; 1STM32编程下载 STM32 ST-LINK Utility一个最重要的功能就是对STM32进行编程。支持常见的hex、bin文件,还有早期摩托罗拉定义的srec和s19格式的文件(说实话,我都不了解这两种格式的文件)。 这里主要想提示一下初学者:hex带有地址,而bin文件不带地址,下载时需要填写起始地址。 下面看两张在STM32 ST-LINK Utility中下载选择文件的图大家就明白了。 1.选择hex下载,地址不可修改(灰色)
[单片机]
关于<font color='red'>STM32</font> ST-LINK Utility查看内核运行状态,助你判断程序是否跑飞
STM32的GPIO电路原理
GPIO是通用输入/输出端口的简称,是STM32可控制的引脚。GPIO的引脚与外部硬件设备连接,可实现与外部通讯、控制外部硬件或者采集外部硬件数据的功能。 STM32F103ZET6芯片为144脚芯片,包括7个通用目的的输入/输出口(GPIO)组,分别为GPIOA、GPIOB、GPIOC、GPIOD、GPIOE、GPIOF、GPIOG,同时每组GPIO口组有16个GPIO口。通常简略称为PAx、PBx、PCx、PDx、PEx、PFx、PGx,其中x为0-15。 STM32的大部分引脚除了当GPIO使用之外,还可以复用为外设功能引脚,比如串口。 GPIO基本结构 每个GPIO内部都有这样的一个电路结构,这个结构在本文下面会具体介
[单片机]
如何在STM32中收发float数据?
实际应用中,我们可能需要两个设备通过串口传输浮点数据: 本篇笔记为了方便演示,使用串口助手模拟其中一个设备,本篇笔记内容如下: 我们创建一个用于管理float类型数据的共用体: union float_data { float f_data; uint8_t by te [4]; }; 数据的流向如: 本次使用串口助手模拟发送设备,省略了第一步,主要看第②、③步。 创建两个共用体变量,用于发送与接收: union float_data rx_float_data, tx_float_data; 收发相关代码: // 公众号: 嵌入式 大杂烩 if(HAL_ UART _Receive(&huart3, rx_float
[单片机]
如何在<font color='red'>STM32</font>中收发float数据?
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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