【stm32】EXTI外部中断

EXTI外部中断

1、中断系统

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

2、中断执行流程

3、STM32中断

  • 68个可屏蔽中断通道,包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设
  • 使用NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级

    中断地址的作用:
    \qquad 在程序中的中断函数,地址由编译器进行分配,不固定,但中断跳转由于硬件的限制,只能跳转到固定的地址执行程序 ,为了能让硬件跳转到一个不固定的中断函数里,就需要在内存中定义一个地址的列表,列表地址是固定的,中断发生后,就跳到这个固定位置,在这个固定位置,由编译器,再加上一条跳转到中断函数的代码,这样中断跳转就可以跳转到任意位置了,这个中断地址的列表,就叫中断问量表

4、NVIC基本结构

NVIC:嵌套中断向量控制器

在STM32中,NVIC用来统一分配中断优先级和管理中断,属于内核外设

5、NVIC优先级分组

  • NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级
  • 抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队

中断优先级:值越小,优先级越高

6、EXTI简介(引脚电平变化,申请中断)

  • EXTI(Extern Interrupt)外部中断
  • EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序
  • 支持的触发方式:上升沿/下降沿/双边沿/软件触发
  • 支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断
  • 通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒
  • 触发响应方式:中断响应/事件响应

中断响应是正常的流程,引脚电平变化触发中断

事件响应不会触发中断,而是触发别的外设(ADC,DMA等)操作,属于外设之间的联合工作

7、EXTI基本结构

EXTI9_5和EXTI15_10:通过标志位区分哪个中断触发的

其它外设:用来触发其它外设操作的,也就是事件响应

8、AFIO复用IO口

  • AFIO主要用于引脚复用功能的选择和重定义
  • 在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择

9、EXTI框图

10、旋转编码器简介

  • 旋转编码器:用来测量位置、速度或旋转方向的装置,当其旋转轴旋转时,其输出端可以输出与旋转速度和方向对应的方波信号,读取方波信号的频率和相位信息即可得知旋转轴的速度和方向
  • 类型:机械触点式/霍尔传感器式/光栅式


    电路描述:
    \qquad 左右两边电路分别接了上拉电阻R1,R2,在默认状态时,A,B输出为高电平,看哪边电路导通,此时与GND相连,则输出口为低电平

11、程序设计:

1.使用对射式红外传感器触发外部中断

\qquad 当挡光片在这个对射式红外传感器中间经过时,DO输出电平变化的信号,电平跳变的信号触发STM32 PB14号口的中断,在中断函数中,执行变量自加,主循环调用OLED显示该变量。
\qquad 接上模块后,使用挡光片在传感器中间槽上来回进出,进入时开关指示灯灭,出来后开关指示灯亮,说明高低电平输出没问题

步骤:

1.配置RCC,打开时钟

2.配置GPIO,选择端口为输入模式

3.配置AFIO,选择所使用的这一路GPIO,连接到EXTI

4.配置EXTI,选择边沿触发方式(上升,下降,双边),选择触发响应方式(中断响应,事件响应)

6.配置NVIC,给中断选择合适优先级

c文件:

c 复制代码
#include "stm32f10x.h"                  // Device header

static uint32_t countSensor = 0;
static uint8_t flag_count = 0;

void countSensor_init(void)
{
    EXTI_InitTypeDef   EXTI_InitStructure;
    GPIO_InitTypeDef   GPIO_InitStructure;
    NVIC_InitTypeDef   NVIC_InitStructure;
    /* Enable GPIOB clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    /* Enable AFIO clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    
    /* Configure PB14 pin as input floating */
    GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_14;
    GPIO_InitStructure.GPIO_Mode     = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Speed     = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    /* Connect EXTI14 Line to PB14 pin */
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);

    /* Configure EXTI14 line */
    EXTI_InitStructure.EXTI_Line = EXTI_Line14;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;  
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    /* Enable and set EXTI14 Interrupt to the lowest priority */
    NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

uint32_t getCountValue(void)
{
    if(flag_count==1){
        if(countSensor<10){
            countSensor++;
        }else{
            countSensor=0;
        }
        flag_count = 0;
    }
    return countSensor;
}

void EXTI15_10_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line14) != RESET)
    {
        flag_count = 1;
        /* Clear the  EXTI line 14 pending bit */
        EXTI_ClearITPendingBit(EXTI_Line14);
    }
}

h文件:

c 复制代码
#ifndef __COUNTSENSOR_H
#define __COUNTSENSOR_H

extern void countSensor_init(void);
extern uint32_t getCountValue(void);

#endif

main.c

c 复制代码
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "countsensor.h"

int main(void)
{
    OLED_Init();
    countSensor_init();
    OLED_ShowString(1, 1, "count:");

    while (1)
    {
        OLED_ShowNum(1,7,getCountValue(),2);
    }
}

2.旋转编码器触发外部中断

c文件:

c 复制代码
#include "stm32f10x.h"                  // Device header

int32_t Encoder_Count;

void encoder_init(void)
{
    EXTI_InitTypeDef   EXTI_InitStructure;
    GPIO_InitTypeDef   GPIO_InitStructure;
    NVIC_InitTypeDef   NVIC_InitStructure;
    /* Enable GPIOB clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    /* Enable AFIO clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    
    /* Configure PB0/PB1  pin as input floating */
    GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_0 | GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode     = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Speed     = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    /* Connect EXTI0/1 Line to PB1/0 pin */
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);

    /* Configure EXTI1/0 line */
    EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;  
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    /* Enable and set EXTI0 Interrupt to the lowest priority */
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    /* Enable and set EXTI1 Interrupt to the lowest priority */
    NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

int32_t Encoder_Get(void)
{
    int32_t Temp;
    Temp = Encoder_Count;
    Encoder_Count = 0;
    return Temp;
}

void EXTI0_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line0) != RESET)
    {
        /*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
        if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
        {
            if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
            {
                Encoder_Count --;
            }
        }
        /* Clear the  EXTI line 0 pending bit */
        EXTI_ClearITPendingBit(EXTI_Line0);
    }
}

void EXTI1_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line1) != RESET)
    {
        /*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
        if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
        {
            if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
            {
                Encoder_Count ++;
            }
        }
        /* Clear the  EXTI line 1 pending bit */
        EXTI_ClearITPendingBit(EXTI_Line1);
    }
}

h文件

c 复制代码
#ifndef __ENCODER_H
#define __ENCODER_H

extern void encoder_init(void);
extern int32_t Encoder_Get(void);

#endif

main.c

c 复制代码
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "encoder.h"

int32_t num ;

int main(void)
{
    OLED_Init();
    encoder_init();
    OLED_ShowString(1, 1, "count:");
    
    while (1)
    {
        num += Encoder_Get();
        OLED_ShowSignedNum(1,7,num,5);
    }    
}

注意:在配置外设GPIO时,如果不确定该配置为什么模式,可参阅参考手册外设的GPIO配置

,里面有每个外设的各个引脚所配置的模式 ,如下

使用外部中断模块的特性:

\qquad 对于stm32,想要获取的信号是外部驱动的很快的突发信号,如旋转编码器,红外遥控接收头,按键等。

相关推荐
合宙Luat3 小时前
合宙LuatOS开发板Core_Air780EP使用说明
单片机·嵌入式硬件·物联网·硬件工程·lua
手打猪大屁3 小时前
STM32——串口通信(发送/接收数据与中断函数应用)
经验分享·笔记·stm32·单片机·嵌入式硬件
yyqzjw5 小时前
【STM32】cubemx配置GPIO
stm32·单片机·嵌入式硬件
嵌入式大圣8 小时前
单片机工程师:创新与挑战之路
单片机·嵌入式硬件
TNT_JQR8 小时前
蓝桥杯嵌入式国三备赛经验分享
经验分享·嵌入式硬件·蓝桥杯
好家伙VCC8 小时前
一些面试和找工作的技巧-新资要的低并不会给你加分薪资要的高不会成为公司拒绝你的核心理由
单片机·嵌入式硬件·学习·面试·职场和发展·鲁棒优化
爱学电子的刻刻帝11 小时前
STM32智能家居语音系统
stm32·单片机·智能家居·语音控制
TeYiToKu12 小时前
笔记整理—内核!启动!—kernel部分(2)从汇编阶段到start_kernel
linux·c语言·汇编·笔记·单片机·嵌入式硬件
小狗爱吃黄桃罐头14 小时前
江协科技STM32学习- P11 中断系统,EXTI外部中断
stm32·江科大stm32
&AtTiTuDe;15 小时前
ADC 简介(STM32F407)
stm32·单片机·嵌入式硬件