5EXTI外部中断

中断相当于吃饭吃着有人敲门。然后去开门,回来继续吃饭

有几个概念:

中断优先级:当有多个中断源申请中断时,优先响应更加紧急

中断嵌套:就是中断里面还可以继续嵌套更多的中断,无限套娃 

所有的中断使用嵌套向量中断控制器NVIC统一管理中断

用医院的叫号系统来举例子。假设医生正在给某个病人看病,外面还有很多病人排队:

  1. 新来的病人 抢占优先级高 就相当于直接进屋打断医生,给自己看病。
  2. 新来的病人 响应优先级高 就相当于不打扰医生,但直接插队,排在队伍的第一个。

 

中断系统是管理和执行中断的逻辑结构,外部中断是众多中断的外设之一,比如EXTI(外部中断)可以监测GPIO的电平信号,当其指定GPIO口 产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决即可中断CPU主程序,执行对应中断程序

有16个通道,但是相同的pin不能同时触发中断,

触发方式:

中断响应:就是正常的中断流程,申请中断让CPU执行中断函数;

事件响应:就是外部中断发生时,不把外部中断信号给CPU,而是选择触发一个事件,将这个信号通向其他外设

AFIO中断引脚选择:主要完成两个任务:复用引脚重映射,中断引脚选择 

1旋转编码器 

旋转编码器 是一种用来测量位置、速度或旋转方向的装置,当其旋转轴旋转时,其输出端可以输出与旋转速度和方向对应的方波信号,读取方波信号的频率和相位信息即可得知旋转轴的速度和方向。

对射式红外传感器计次

产生下降沿计次

 main.c

#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "CountSensor.h"

int main(void){
    //OLED初始化
    OLED_Init();
    OLED_ShowString(1,1,"Neg-edge:");
    OLED_ShowNum(2,1,0,5); 
    
    CountSensor_Init();
    
    while(1){
        OLED_ShowNum(2,1,CountSensor_Get(),5);  
    };
}

countersensor.h

#ifndef __COUNTERSENSOR_H
#define __COUNTERSENSOR_H

void CountSensor_Init(void);
uint16_t CountSensor_Get(void);

#endif

countersensor.c

#include "stm32f10x.h"                  // Device header

uint16_t CountSensor_Count = 0;//中断触发次数

/**
  * @brief  对射式红外传感器起初始化-PB14
  */
void CountSensor_Init(void){
    //EXIT初始化
    //1. 开启GPIO、AFIO的外设时钟(EXTI和NVIC的时钟是一直打开的)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    //2. 配置GPIO-PB14上拉输入
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//上拉输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    //3. 配置AFIO(库函数在GPIO中)
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);//数据选择器
    //4. 配置NVIC
    EXTI_InitTypeDef EXTI_InitStructure;
    EXTI_InitStructure.EXTI_Line = EXTI_Line14;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
    EXTI_Init(&EXTI_InitStructure);
    //5. 配置NVIC(库函数在misc.h文件中)
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置中断的优先级分组,每个工程只能出现一次!!
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&NVIC_InitStructure);
}

/**
  * @brief  输出中断触发的次数
  * @retvl  无符号16位整型,范围0~65535
  */
uint16_t CountSensor_Get(void){
    return CountSensor_Count;
}

//中断函数的名字从启动文件“stratup_stm32f10x_md”中来
//中断函数都是无参无返回值的
void EXTI15_10_IRQHandler(void){
    //中断标志位判断
    if(EXTI_GetITStatus(EXTI_Line14)==SET){
        CountSensor_Count++;
        EXTI_ClearITPendingBit(EXTI_Line14);//清除中断标志位
    }
}

旋转编码器计次

main.c

#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "RotaryEncoder.h"

int main(void){
    //配置中断的优先级分组,每个工程只能出现一次!!
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    //OLED显示屏初始化
    OLED_Init();
    OLED_ShowString(1,1,"RE_Count:");
    OLED_ShowSignedNum(2,1,0,5);
    
    //传感器初始化
    RotaryEncoder_Init();
    
    while(1){
        OLED_ShowSignedNum(2,1,RotaryEncoder_GetCount(),5);
        if(RotaryEncoder_GetChange()==1)      {OLED_ShowString(3,1,"Clockwise.     ");}
        else if(RotaryEncoder_GetChange()==-1){OLED_ShowString(3,1,"anti-Clockwise.");}
    };
}

 rotayEncoder.h

#ifndef __ROTARYENCODER_H
#define __ROTARYENCODER_H

void RotaryEncoder_Init(void);
int16_t RotaryEncoder_GetCount(void);
int16_t RotaryEncoder_GetChange(void);

#endif

rotayencoder.c

#include "stm32f10x.h"                  // Device header

//旋转编码器计次
int16_t RotaryEncoder_Count_cur = 0;
int16_t RotaryEncoder_Count_pre = 0;

/**
  * @brief  旋转编码器(Rotary Encoder)初始化-A口PB0、B口PB1
  */
void RotaryEncoder_Init(void){
    //开启外设时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    
    //配置GPIOB-PB0、PB1上拉输入
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    //配置AFIO(库函数在GPIO中)
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);
    
    //配置EXTI
    EXTI_InitTypeDef EXTI_InitStructure;
    EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
    EXTI_Init(&EXTI_InitStructure);
    
    //配置NVIC(库函数在misc.h文件中)
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&NVIC_InitStructure);
    NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_Init(&NVIC_InitStructure);    
}

/**
  * @brief  获取从程序复位开始的计次
  * @retvl  int16_t变量,范围-32768~32767
  */
int16_t RotaryEncoder_GetCount(void){
    return RotaryEncoder_Count_cur;
}

/**
  * @brief  获取状态变化值
  * @retvl  int16_t变量,-1表示逆时针转、0初始化状态、1表示顺时针转
  */
int16_t RotaryEncoder_GetChange(void){
    return (RotaryEncoder_Count_cur - RotaryEncoder_Count_pre);
}

/**
  * @brief  A口下降沿中断函数
  */
void EXTI0_IRQHandler(void){
    if(EXTI_GetITStatus(EXTI_Line0)==SET){
        if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)==0){
            RotaryEncoder_Count_pre = RotaryEncoder_Count_cur;
            RotaryEncoder_Count_cur--;//B口超前减计数
        }
        EXTI_ClearITPendingBit(EXTI_Line0);
    }
}

/**
  * @brief  B口下降沿中断函数
  */
void EXTI1_IRQHandler(void){
    if(EXTI_GetITStatus(EXTI_Line1)==SET){
        if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0)==0){
            RotaryEncoder_Count_pre = RotaryEncoder_Count_cur;
            RotaryEncoder_Count_cur++;//A口超前加计数
        }
        EXTI_ClearITPendingBit(EXTI_Line1);
    }
}

你可能感兴趣的:(STM32笔记,单片机,嵌入式硬件)