一、基本概念

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)假设某个中断源被指定为某个抢占式优先级别,又没有其他中断源处于同一个抢占式优先级别,则能够为这个中断源指定随意有效的响应优先级别。

二、 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。

三、程序实现

事实上上面那些基本概念和知识仅仅是对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 PBport时钟,而且打开复用时钟

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

}

    设置对应的时钟所须要的RCC函数在stm32f10x_rcc.c中,所以要在project中加入此文件。

 

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 = 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中,须要将此文件复制并加入到project中。详细位置能够查看关于GPIO的笔记。这段代码编译起来没有不论什么问题,可是在链接的时候就会报错,须要把STM32F10xR.LIB加入project中,详细位置在…KeilARMRV31LIBSTSTM32F10xR.LIB。

 

3.       IO口初始化

void IO_cfg()

{

       GPIO_InitTypeDef GPIO_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_InitTypeDef EXTI_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单片机那样,能够用过interruptkeyword来定义中断响应函数,STM32的中断响应函数接口存在中断向量表中,是由启动代码给出的。默认的中断响应函数在stm32f10x_it.c中。因此我们须要把这个文件增加到project中来。

在这个文件里,我们发现,非常多函数都是仅仅有一个函数名,并没有函数体。我们找到EXTI2_IRQHandler()这个函数,这就是EXTI2中断响应的函数。我的目标是将LED灯点亮,所以函数体事实上非常easy:

void EXTI2_IRQHandler(void)

{

       //点亮LED灯

       GPIO_SetBits(GPIOD,GPIO_Pin_6);

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

       EXTI_ClearITPendingBit(EXTI_Line2);

}

 

void EXTI3_IRQHandler(void)

{

       GPIO_SetBits(GPIOD,GPIO_Pin_3);

       EXTI_ClearITPendingBit(EXTI_Line3);

}

 

void EXTI9_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);

}

转自http://huhui1101.blog.163.com/blog/static/8784066520126294740460/

STM32外部中断具体解释的更多相关文章

  1. 转别人的 STM32外部中断使用注意事项

    前言:这些问题都是我之前在工作中遇到的,后来觉得需要总结,自己记忆不好,所以在这个给自己打个mark. 一:触发方式 STM32 的外部中断是通过边沿来触发的,不支持电平触发: 二:外部中断分组 ST ...

  2. STM32外部中断初理解

    PA0,PB0...PG0--->EXTI0 PA1,PB1...PG1--->EXTI1 ....... PA15,PB15...PG15--->EXTI15 以上为GPIO和中断 ...

  3. STM32 外部中断

    1)STM32一般有19 个外部中断为: 线 0~15:对应外部 IO 口的输入中断.线 16:连接到 PVD 输出. 线 17:连接到 RTC 闹钟事件. 线 18:连接到 USB 唤醒事件. 2) ...

  4. stm32 外部中断学习

    今天我们看看STM32的外部中断实验. STM32 供 IO 口使用的中断线只有 16 个,但是 STM32 的 IO 口却远远不止 16 个,那么 STM32 是怎么把 16 个中断线和 IO 口一 ...

  5. STM32 外部中断详解(原理+配置代码)

    本文介绍了STM32基于标准外设库的外部中断配置,以及基于参考手册如何更加寄存器配置外部中断 文章目录 1 前言 2 STM32的外部中断 3 中断服务函数的映射关系 4 外部中断的配置 5 寄存器的 ...

  6. STM32——外部中断EXIT实现

    外部中断实现步骤: 一.初始化,包括:1.AFIO时钟中断和GPIO时钟使能:                          2.GPIO初始化                           ...

  7. (stm32f103学习总结)—stm32外部中断

    一.外部中断介绍 1.1 EXTI简介 EXTI简介 STM32F10x外部中断/事件控制器(EXTI)包含多达 20 个用于产生事 件/中断请求的边沿检测器.EXTI的每根输入线都可单独进行配置,以 ...

  8. STM32外部中断.

    void EXTIX_Init(void){     EXTI_InitTypeDef EXTI_InitStructure;    NVIC_InitTypeDef NVIC_InitStructu ...

  9. STM32之外部中断控制

    一.STM32外部中断 1.STM32外部中断结构图 如上图所示:主要包括四个环节,GPIO.AFIO.EXTI.NVIC.以STM32F103VE(100脚)为例说明硬件模块的数量: GPIO:   ...

随机推荐

  1. HttpClient get返回String类型 JAVA

    public static String httpGet(String url) { // get请求返回结果 String strResult = ""; try { Defau ...

  2. SQL2008转SQL2005数据库经验

    1.用SQL2008创建兼容2005的结构脚本. 2.在2005中生成数据库结构. 3.利用2005中的数据导入直接从源数据库中导入数据,此处注意自增长标识的选项需要添加,多表优化选项可以去掉,这里不 ...

  3. webview笔记

    1. 用户上传文件 webChromeClient的onShowFileChooser这个方法,这将打开一个文件选择器,如果要取消这个请求则是调用filePathCallback.onReceiveV ...

  4. java下socket传文件

    package cn.stat.p4.ipdemo; import java.io.BufferedReader; import java.io.BufferedWriter; import java ...

  5. [Leetcode][019] Remove Nth Node From End of List (Java)

    题目在这里: https://leetcode.com/problems/remove-nth-node-from-end-of-list/ [标签] Linked List; Two Pointer ...

  6. js分页算法

    function get_hs_page(cur_page, total_page) { var result = ""; for(var i = 1; i <= total ...

  7. js拖动层

    模仿网易彩票网(http://caipiao.163.com/)的登陆框自己做了一个拖动层,不过有点小问题——在谷歌浏览拖动的时候鼠标状态变成了文字状态(cursor:text;) <!DOCT ...

  8. n阶行列式计算----c语言实现(完结)

    花了半天时间,写了这个n阶行列式计算的程序,应该算是比较优美吧,有很多地方多次做了优化,程序占用内存不是很大,要是说小吧,也不合适,因为里边有一个递归,而且递归的深度还比较深.时间复杂度具体没有细看, ...

  9. Python实现合并排序MergeSort

    def merge(sort_list, start, mid, end): left_list = sort_list[start:mid] right_list = sort_list[mid:e ...

  10. 利用pyapns进行ios推送

    ios客户端的同事提供了2个证书,分别是aps_development.cer  和 pushdevelopment.p12, 我最终目的就是把这2个证书合并成1个pem证书,然后通过pyapns进行 ...