1 NVIC功能:判断优先级
NVIC优先级分组
1.1抢占优先级:优先级高的,可以打断正在执行的中断(可进行中断嵌套)
1.2响应优先级:不可以打断正在执行的中断,但可以插队
NVIC中断判断由优先级寄存器的4位(0-15)来决定(值越小,优先级越高),抢占优先级和响应优先级相同的,按中断号排队。
2 EXTI简介
2.1 EXTI外部中断简介
EXTI可以检测指定的GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立刻向NVIC发出中断申请,经过NVIC判断后可中断CPU主程序,使CPU执行EXTI对应的中断程序。
2.2 支持的触发方式
上升沿/下降沿/双边沿/软件触发
2.3 支持的GPIO口
所有的GPIO口,但是相同的Pin不能同时触发中断(PA0和PB0只能有一个触发)
2.4 通道数
16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒。
PVD电源电压检测,当电源从电压过低恢复时,PVD借助外部中断退出停止模式
RTC闹钟,闹钟运行中进入停止模式,闹钟结束后借助外部中断退出停止模式
2.5 触发响应方式
中断响应(申请中断)/事件响应(用来触发其他外设合作)
2.6 EXTI基本结构
3 配置外部中断
中断配置以PB4端口为例
3.1 配置时钟(把我们需要的外部时钟都打开)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//使能AFIO时钟
注意,EXTI跟NVIC两个外设是一直打开的,无需开启时钟(NVIC为内核外设,无需开启)
3.2 配置GPIO
GPIO_InitTypeDef GPIO_Initstrucuure;
GPIO_Initstrucuure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
GPIO_Initstrucuure.GPIO_Pin = GPIO_Pin_4;//端口选择
GPIO_Initstrucuure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_Initstrucuure);//初始化GPIO
3.3 配置AFIO
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource4);//配置AFIO
参数1 GPIO_PortSourceGPIOx,x可以取为A-G
参数2 GPIO_PinSourcex,x可以取为0-15
注意,此函数在gpio.h文件中
3.4 配置EXTI
打开exti.h文件
3.4.1 EXTI函数介绍
void EXTI_DeInit(void);//调用清除EXTI配置,恢复上电前状态
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);//初始化EXTI函数,使用方法类似GPIO_Init
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);//传递结构体地址
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);//软件触发外部中断
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);//获取指定标志位是否置1
void EXTI_ClearFlag(uint32_t EXTI_Line);//对置1的标志位清除
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);//获取中断标志位是否置1
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);//清除中断挂起标志位
3.4.2 配置EXTI
EXTI_InitTypeDef EXTI_Initstructure;//取一个变量名,然后加点引出结构体成员
EXTI_Initstructure.EXTI_Line = EXTI_Line4;//中断线路选择
EXTI_Initstructure.EXTI_LineCmd = ENABLE;//选择中断线状态
EXTI_Initstructure.EXTI_Mode = EXTI_Mode_Interrupt;//指定外部中断模式
//两种模式分别是EXTI_Mode_Interrupt;中断模式
//EXTI_Mode_Event;事件模式
EXTI_Initstructure.EXTI_Trigger = EXTI_Trigger_Falling;//指定触发信号有效边沿
//EXTI_Trigger_Rising;上升沿
//EXTI_Trigger_Falling;下降沿
//EXTI_Trigger_Rising_Falling;双边沿
EXTI_Init(&EXTI_Initstructure);//EXTI初始化,配置完成
3.5 配置NVIC
打开misc.h文件,拉到最下方
3.5.1 NVIC函数介绍
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);//中断分组
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);//根据结构体里面的指定参数初始化NVIC
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);//设置中断向量表
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);//系统低功耗配置
3.5.2 配置NVIC
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置抢占优先级和响应优先级的分组
NVIC_InitTypeDef NVIC_InitStructure;//定义结构体变量名称,加点引出结构体成员
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;//选择芯片和通道
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//指定中断通道是使能还是失能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =1;//指定抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;//指定响应优先级,注意,参数选择与分组方式有关
NVIC_Init(&NVIC_InitStructure);//NVIC初始化,配置完成
至此,外部中断配置结束
4 中断函数配置
中断函数名称参考启动文件startup_stm32f10x_md.s文件,找到对应的中断函数名称
void EXTI4_IRQHandler(void)
{
if( EXTI_GetITStatus(EXTI_Line4) == SET)//中断标志位判断
{
jici ++;//中断程序
EXTI_ClearITPendingBit(EXTI_Line4);//清除中断标志位
}
}
因为需要一个数字来统计中断触发的次数,在模块上定义变量
uint16_t jici;//定义变量
uint16_t cishu_GET(void)//定义一个GET函数
{
return jici;//返回变量
}
头文件声明
#include "stm32f10x.h"
#ifndef __ZHONGDUAN_H
#define __ZHONGDUAN_H
void ZHONGDUAN_Init(void);
uint16_t cishu_GET(void);
#endif
5 main函数
#include "stm32f10x.h"
#include "relay.h"
#include "LED.h"
#include "DONG.h"
#include "OLED.h"
#include "ZHONGDUAN.h"
void dalay(uint16_t time)//延时函数
{
uint16_t i = 0;
while(time--)
{
i =12000;
while(i--);
}
}
int main(void)
{
ZHONGDUAN_Init();//中断函数初始化
OLED_Init();//OLED初始化
OLED_ShowString(1, 1, "cishu:");//OLED显示字符串
while(1)
{
OLED_ShowNum(1, 7, cishu_GET(), 5);//OLED显示中断触发返回的参数值
}
}
6 实验结果演示
实验成功