1、使用GPIOA1来作为外部中断源时,需要定义3个结构体,分别是:GPIO、外部中断、中断优先级控制相关

STM32CubeMX配置STM32F103C8T6的外部中断按键_单片机

中断控制部分的结构体在stm32固件库的 中断相关的.h文件找到

STM32CubeMX配置STM32F103C8T6的外部中断按键_外部中断_02

 

 2、GPIOA1既是作为输入,也作为外部中断源,需要打开GPIOA的时钟以及GPIO的复用时钟

对其使能

STM32CubeMX配置STM32F103C8T6的外部中断按键_单片机_03

 时钟相关函数可以在rcc.h时钟相关的h文件找到

STM32CubeMX配置STM32F103C8T6的外部中断按键_stm32_04

3、 再设置GPIOA1为外部中断源:

STM32CubeMX配置STM32F103C8T6的外部中断按键_外部中断_05

4、 然后对中断优先级分组:

STM32CubeMX配置STM32F103C8T6的外部中断按键_#include_06

STM32CubeMX配置STM32F103C8T6的外部中断按键_嵌入式硬件_07

 

这里选择2组,只有一个中断源选哪个都无所谓 。

5、接着对第一步定义的三个结构体进行配置:

STM32CubeMX配置STM32F103C8T6的外部中断按键_外部中断_08

 GPIO的模式看情况来配置,这里我需要GPIOA1来做振动传感器的输出端,不震动输出高电平,震动输出低电平,所以这里选择的是下拉输入,配置好之后再对各自的内容进行初始化就完成了外部中断的c文件相关的代码。

6、主函数部分的中断代码如下:

STM32CubeMX配置STM32F103C8T6的外部中断按键_外部中断_09

外部中断1处理函数在启动文件当中封装好了可以打开直接复制调用

STM32CubeMX配置STM32F103C8T6的外部中断按键_#include_10

每次执行该中断时会获取中断标志位,执行完成后标志位需要软件置位

STM32CubeMX配置STM32F103C8T6的外部中断按键_stm32_11

 

STM32CubeMX配置STM32F103C8T6的外部中断按键_stm32_12

 外部中断c文件代码

#include "exti.h"
#include "stm32f10x.h"


void exti_Init(void)
{
	GPIO_InitTypeDef shake_init; //定义GPIO结构体
	EXTI_InitTypeDef exte_init;//定义外部中断结构体
	NVIC_InitTypeDef nvic_init;//定义中断控制结构体(misc.h文件)
	//打开GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	//GPIOA1即是GPIO输出端口也是外部中断源所以打开复用时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);//GPIOA1口设置为外部中断源


	//中断优先级分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);


	//配置GPIOA1配置
	shake_init.GPIO_Mode  = GPIO_Mode_IPD;//下拉输入
	shake_init.GPIO_Pin   = GPIO_Pin_1;
	shake_init.GPIO_Speed = GPIO_Speed_10MHz;
	//GPIOA初始化
	GPIO_Init(GPIOA, &shake_init);
	
	//配置EXTI外部中断
	exte_init.EXTI_Line    = EXTI_Line1;
	exte_init.EXTI_Mode    = EXTI_Mode_Interrupt;//中断模式
	exte_init.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿信号
	exte_init.EXTI_LineCmd = ENABLE;//使能中断
	EXTI_Init(&exte_init);//中断初始化
	
	//配置NVIC中断控制器
	nvic_init.NVIC_IRQChannel  									=	EXTI1_IRQn;//用的是GPIO1所以用中断通道1
	nvic_init.NVIC_IRQChannelCmd 								=	ENABLE	;	
	nvic_init.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
	nvic_init.NVIC_IRQChannelSubPriority        = 1;//子优先级
	NVIC_Init(&nvic_init);//中断控制初始化


}

main.c:

#include "led.h"
#include "stm32f10x.h"
#include "relay.h"
#include "exti.h"
#include "shake.h"
void delay(uint16_t time)
{
	uint16_t i= 0;
	while(time--)
	{
		i=12000;
		while(i--);
	}

}



int  main()
{

	LED_Init();
	Relay_Init();
	Shake_Init();
	exti_Init();
void EXTI1_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line1) !=  RESET)
	{
		GPIO_ResetBits(GPIOA,GPIO_Pin_3);//闭合继电器
		delay(1000); 
		GPIO_SetBits(GPIOA,GPIO_Pin_3);//打开继电器
	}
		EXTI_ClearFlag(EXTI_Line1);//清除中断标志位

}
}

使用中断来代替while函数来判断是否震动点亮led的方式会减少数据的调用,提高单片机工作效率。