当前位置: 代码迷 >> 综合 >> 2022-3-9 stm32mini 库函数 外部中断实验-EXTI 学习笔记
  详细解决方案

2022-3-9 stm32mini 库函数 外部中断实验-EXTI 学习笔记

热度:24   发布时间:2023-12-06 08:55:51.0

目录

外部中断实现的功能:

编写外部中断初始化函数

1)初始化 IO 口为输入。

2)开启 IO 口复用时钟,设置 IO 口与中断线的映射关系。

3)初始化线上中断,设置触发条件等。

4)配置中断分组(NVIC),并使能中断。

外部中断初始化函数完整代码

编写服务函数

exti.c中完整代码为:

main.c中完整代码???????


这章的代码主要分布在固件库的 stm32f10x_exti.h 和 stm32f10x_exti.c 文件中,但中断线及中断初始化配置文件在stm32f10x_gpio.h 和 stm32f10x_gpio.c中 。

外部中断实现的功能:

利用key按键,中断控制led灯。

KEY1对LED1取反

KEY0对LED0取反

WK UP对LED1和LED0同时取反

建立工程文件

工程文件如下:

 

编写外部中断初始化函数

1)初始化 IO 口为输入。


void EXTIX_Init(void)
{KEY_Init();//初始化io口}

2)开启 IO 口复用时钟,设置 IO 口与中断线的映射关系。

例如我们要用的WK UP对应串口为PA0,则函数中对应变量填(GPIO_PortSourceGPIOA,GPIO_PinSource0)

 当我们要利用其他key时,这行代码只需更改红色部分即可。

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//中断线0

3)初始化线上中断,设置触发条件等。

 EXTI_InitTypeDef EXTI_InitStructure;//定义结构体变量EXTI_InitStructure.EXTI_Line=EXTI_Line0; //中断线0,与GPIO中相同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 寄存器

4)配置中断分组(NVIC),并使能中断。

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

外部中断初始化函数完整代码

void EXTIX_Init(void)
{KEY_Init();//初始化io口GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource0);//中断线0EXTI_InitTypeDef EXTI_InitStructure;//定义结构体变量EXTI_InitStructure.EXTI_Line=EXTI_Line0; //中断线0,与GPIO中相同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 寄存器NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按键外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级 2,NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级 2NVIC_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);  //手动清除挂起位
}

这里需要说明一下,中断服务函数的名字是 在 MDK 中事先有定义的。STM32 的 IO 口外部中断函数只有 6 个,分别为:

EXPORT EXTI0_IRQHandler 
EXPORT EXTI1_IRQHandler 
EXPORT EXTI2_IRQHandler 
EXPORT EXTI3_IRQHandler 
EXPORT EXTI4_IRQHandler 
EXPORT EXTI9_5_IRQHandler 
EXPORT EXTI15_10_IRQHandler

中断线 0-4 每个中断线对应一个中断函数,中断线 5-9 共用中断函数 EXTI9_5_IRQHandler,中 断线 10-15 共用中断函数 EXTI15_10_IRQHandler。

此时,我们的exti.c文件中的代码为:

#include "exti.h"void EXTIX_Init(void)
{KEY_Init();//初始化io口GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//中断线0EXTI_InitTypeDef EXTI_InitStructure;//定义结构体变量EXTI_InitStructure.EXTI_Line=EXTI_Line0; //中断线0,与GPIO中相同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 寄存器NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按键外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级 2,NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级 2NVIC_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);  //手动清除,确保下次能进入中断服务函数
}

按照以上方法,只需更改gpio口和中断线序号,就可以设置其他的服务函数;

exti.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;//中断线5,与GPIO中相同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 寄存器NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;			//使能按键外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//抢占优先级 2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;					//子优先级 1NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;					//使能外部中断通道NVIC_Init(&NVIC_InitStructure); //GPIOA.15	  中断及中断初始化设置GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15);EXTI_InitStructure.EXTI_Line=EXTI_Line15;  //中断线15,与GPIO中相同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 寄存器NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;		//使能按键外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//抢占优先级 2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;					//子优先级 0NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;						//使能外部中断通道NVIC_Init(&NVIC_InitStructure); //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;	//抢占优先级 2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;					//子优先级 2NVIC_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); //手动清除,确保下次能进入中断服务函数
}void EXTI9_5_IRQHandler(void)
{			delay_ms(10);   //消抖	 			 if(KEY0==0)	{LED0=!LED0;}EXTI_ClearITPendingBit(EXTI_Line5);    //手动清除,确保下次能进入中断服务函数  
}void EXTI15_10_IRQHandler(void)
{delay_ms(10);    //消抖	 if(KEY1==0)	{LED1=!LED1;}EXTI_ClearITPendingBit(EXTI_Line15);  //手动清除,确保下次能进入中断服务函数
}

接下来编写主函数

main.c中完整代码

#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);// 中断优先级2uart_init(9600);	 //设置波特率为9600LED_Init();		  	 //led串口初始化EXTIX_Init();		//中断初始化LED0=0;				//点亮LEDwhile(1){	    printf("OK\n");	delay_ms(1000);	  } 
}