STM32 中断实验

实验目的: 对系统中断的过程有一个大概的了解,能够自主写出代码控制各IO口的中断信息;应用目的通
过板载的 4 个按键,控制板载的两个 LED 的亮灭以及蜂鸣器的发声。

简介
STM32支持19个外部中断请求,也即有19根中断线来响应

线 0~15:对应外部 IO 口的输入中断。
这16根线每根对应7个IO口,从A~G,号码与线号对应,但每次只能连接到一个IO口上

线 16:连接到 PVD 输出。
补充 PVD = Programmable Votage Detector 可编程电压监测器
它的作用是监视供电电压,在供电电压下降到给定的阀值以下时,产生一个中断,通知软件做紧急处理。当供电电压又恢复到给定的阀值以上时,也会产生一个中断,通知软件供电恢复。供电下降的阀值与供电上升的PVD阀值有一个固定的差值,引入这个差值的目的是为了防止电压在阀值上下小幅抖动,而频繁地产生中断。

线 17:连接到 RTC 闹钟事件。
线 18:连接到 USB 唤醒事件。

线16~18都是特定的中断响应
在这里插入图片描述

用来配置这种映射关系的函数为

void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) {}
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);	//将中断线 2 与 GPIOE 连接,IO口即为GPIOE2;

也就是说使用了这个函数以后IO口与中断线关联,就可以进行下一步中断线 | 上中断的操作;

初始化:

void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
EXTI_InitTypeDef  EXTI_InitStructure; 
EXTI_InitStructure.EXTI_Line = EXTI_Line4; 
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;  
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 
EXTI_InitStructure.EXTI_LineCmd = ENABLE; 
EXTI_Init(&EXTI_InitStructure);    //根据 EXTI_InitStruct 中指定的;
//参数初始化外设 EXTI 寄存器;

一个EXTI_InitTypeDef结构体内有四个成员:

typedef struct 
{ 
  uint32_t EXTI_Line;  
  EXTIMode_TypeDef EXTI_Mode;    
  EXTITrigger_TypeDef EXTI_Trigger;  
  FunctionalState EXTI_LineCmd;   
}EXTI_InitTypeDef;

第一个参数是中断线的标号,取值范围为
EXTI_Line0~EXTI_Line15。这个在上面已经讲过中断线的概念。也就是说,这个函数配置的是某个中断线上的中断参数。第二个参数是中断模式,可选值为中断 EXTI_Mode_Interrupt 和事件 EXTI_Mode_Event。第三个参数是触发方式,可以是下降沿触发 EXTI_Trigger_Falling,上升沿触发 EXTI_Trigger_Rising,或者任意电平(上升沿和下降沿)触发 EXTI_Trigger_Rising_Falling。最后一个参数就是使能中断线。

接下来还有中断优先级的定义
抢占优先级:多个IO同时发出中断请求时,抢占优先级越小,CPU越优先响应,但如果已经有中断被响应,那这时候就应该对比一下响应优先级,来判断是否要跳出去执行另一个中断;

NVIC_InitTypeDef NVIC_InitStructure; 
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;         //使能按键外部中断通道 
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级 2,  
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;  //子优先级 2 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   //使能外部中断通道 
NVIC_Init(&NVIC_InitStructure);                          //中断优先级分组初始化

中断服务函数
STM32 的 IO 口外部中断函数只有 6 个,分别为:

EXPORT  EXTI0_IRQHandler           
EXPORT  EXTI1_IRQHandler        
EXPORT  EXTI2_IRQHandler          
EXPORT  EXTI3_IRQHandler         
EXPORT  EXTI4_IRQHandler           
EXPORT  EXTI9_5_IRQHandler	//5~9共用     
EXPORT  EXTI15_10_IRQHandler	//10~15共用

//EXPORT表明该函数已经在其他文件中定义过了,可以直接使用;

两个常用函数

ITStatus EXTI_GetITStatus(uint32_t EXTI_Line)//判断某个中断线上的中断是否发生;
void EXTI_ClearITPendingBit(uint32_t EXTI_Line)//清除中断标志位;

具体实现函数 exit.c

#include "exti.h"
#include "led.h"
#include "key.h"
#include "delay.h"
#include "usart.h"

//外部中断初始化函数
void EXTIX_Init(void)
{

	EXTI_InitTypeDef EXTI_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //外部中断,需要使能AFIO时钟

	KEY_Init(); //初始化按键对应io模式

	//GPIOC.5 中断线以及中断初始化配置
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource5);

	EXTI_InitStructure.EXTI_Line = EXTI_Line5;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器

	//GPIOA.15	  中断线以及中断初始化配置
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource15);

	EXTI_InitStructure.EXTI_Line = EXTI_Line15;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器

	//GPIOA.0	  中断线以及中断初始化配置
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);

	EXTI_InitStructure.EXTI_Line = EXTI_Line0;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器

	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;			 //使能按键所在的外部中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;		 //子优先级1
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				 //使能外部中断通道
	NVIC_Init(&NVIC_InitStructure);								 //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

	NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;			 //使能按键所在的外部中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2,
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;		 //子优先级1
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				 //使能外部中断通道
	NVIC_Init(&NVIC_InitStructure);

	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;		 //使能按键所在的外部中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2,
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;		 //子优先级1
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				 //使能外部中断通道
	NVIC_Init(&NVIC_InitStructure);
}

void EXTI0_IRQHandler(void)
{
	delay_ms(10); //消抖
	if (WK_UP == 1)
	{
		LED0 = !LED0;
		LED1 = !LED1;
	}
	EXTI_ClearITPendingBit(EXTI_Line0); //清除EXTI0线路挂起位
}
void EXTI9_5_IRQHandler(void)
{
	delay_ms(10); //消抖
	if (KEY0 == 0)
	{
		LED0 = !LED0;
	}
	EXTI_ClearITPendingBit(EXTI_Line5); //清除LINE5上的中断标志位
}

void EXTI15_10_IRQHandler(void)
{
	delay_ms(10); //消抖
	if (KEY1 == 0)
	{
		LED1 = !LED1;
	}
	EXTI_ClearITPendingBit(EXTI_Line15); //清除LINE15线路挂起位
}

最后是主函数代码,要实现目的功能还是比较简单的

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "key.h"
#include "usart.h"
#include "exti.h"

int main(void)
{

	delay_init();									//延时函数初始化
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置中断优先级分组2
	uart_init(9600);								//串口初始化为9600
	LED_Init();										//初始化与LED连接的硬件接口
	EXTIX_Init();									//外部中断初始化
	LED0 = 0;										//点亮LED
	while (1)
	{
		printf("OK\n");
		delay_ms(1000);
	}

	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值