外部中断实验-对射式传感器OLED 屏幕计数

本文详细介绍了STM32F10x中NVIC中断控制器的抢占优先级和响应优先级,以及EXTI外部中断的配置过程,包括GPIO、AFIO和EXTI中断线的初始化,以及NVIC分组设置。最后展示了中断函数的配置和实验结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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  实验结果演示

实验成功

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值