EXTI——GPIO外部中断

前言

STM32的每一个GPIO都可以产生这个中断,体现在GPIO就是电平的变化,可能由高电平变成低电平,或者由低电平变为高电平,这些电平的变化需要一个外设来管理,最后传给NVIC,就是内核里面的嵌套向量中断控制器来处理这个中断,而这个检测GPIO口电平的变化的外设就是EXTI。

EXTI简介及其寄存器

EXTI :外部中断/事件控制器
外部就是检测GPIO

EXTI框图

在这里插入图片描述

输入线

共20根
在这里插入图片描述
另外四个EXTI线的连接方式如下:
● EXTI线16连接到PVD输出
● EXTI线17连接到RTC闹钟事件
● EXTI线18连接到USB唤醒事件
● EXTI线19连接到以太网唤醒事件(只适用于互联型产品)
配置输入线的寄存器为外部中断配置寄存器 1至4(AFIO_EXTICRx,x=(1,2,3,4)),寄存器各位配置的如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

边沿检测电路

可选择上升沿或下降沿触发选择寄存器
有关的寄存器有 上升沿触发选择寄存器(EXTI_RTSR),下降沿触发选择寄存器(EXTI_FTSR)
在这里插入图片描述
由于输入线二十条,则上升沿和下降沿寄存器都有20个有效位来控制,置1就可使对应的输入线上升沿或下降沿触发中断

软件中断事件寄存器

在这里插入图片描述
对应位置1,则会在挂起寄存器对应位置一,先标志一下

软件中断事件寄存器和和边沿检测电路均置一,则通过或门输出一

中断屏蔽寄存器

在这里插入图片描述
对应位置一才会相应中断
中断屏蔽寄存器和请求挂起寄存器均置一时通过与门才会输出1传至NVIC中断控制器,产生相应中断

代码编写(按键控制LED的亮灭)

按键对应GPIO初始化

按键连接的GPIO为PA0,将其设为浮空输入模式

    GPIO_InitTypeDef  GPIO_InitStruct;
	//初始化要连接到EXTI的GPIO
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitStruct.GPIO_PinGPIO_Pin_0;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING ;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	

初始化EXTI

	EXTI_InitTypeDef  EXTI_InitStruct;
	
	//初始化EXTI用于产生中断或事件
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//打开时钟
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//输入线为PA0
	EXTI_InitStruct.EXTI_Line=EXTI_Line0;
	EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;//产生中断
	EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Rising;上升沿触发中断
	EXTI_InitStruct.EXTI_LineCmd=ENABLE;//使能中断
	EXTI_Init(&EXTI_InitStruct);
	

初始化NVIC

用于处理中断

static void EXTI_NVIC_Config(void) //static指只能被bsp_exti使用
{
	NVIC_InitTypeDef   NVIC_InitStruct;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//配置中断优先级
	NVIC_InitStruct.NVIC_IRQChannel=EXTI0_IRQn ;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStruct);
}

编写中断服务函数

编写中断服务函数 写在stm32f10x_it.c中


注意名称一定要正确,正确名称可在startup_stm32f10x_hd.s寻找


void EXTI0_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line0)!=RESET)
	{
		LED_G_TOGGLE;
	}
	EXTI_ClearITPendingBit(EXTI_Line0);
}

每产生一次中断,就使LED改变一次状态
至此,该编成的全部细节已经写完,接下来就是讲这些细节拼装起来
最终编程为

main函数

#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_exti.h"

int main()
{
  LED_GPIO_Config();
	EXTI_Key1_Config();
	while(1)
	{;
	}
}

bsp.exti.c

static void EXTI_NVIC_Config(void) //static指只能被bsp_exti使用
{
	NVIC_InitTypeDef   NVIC_InitStruct;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	NVIC_InitStruct.NVIC_IRQChannel=EXTI0_IRQn ;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStruct);
}

void EXTI_Key1_Config(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	EXTI_InitTypeDef  EXTI_InitStruct;
	//配置中断优先级
	//初始化NVIC,用于处理中断
	EXTI_NVIC_Config();
	//初始化要连接到EXTI的GPIO
	RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE);
	GPIO_InitStruct.GPIO_Pin=KEY1_INT_GPIO_PIN;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING ;
	GPIO_Init(KEY1_INT_GPIO_PORT,&GPIO_InitStruct);
	
	//初始化EXTI用于产生中断或事件
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
	EXTI_InitStruct.EXTI_Line=EXTI_Line0;
	EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Rising;
	EXTI_InitStruct.EXTI_LineCmd=ENABLE;
	EXTI_Init(&EXTI_InitStruct);
	
	//编写中断服务函数  写在stm32f10x_it.c中
}

bsp.exti.h

#ifndef __BSP_EXTI_H
#define __BSP_EXTI_H

#include "stm32f10x.h"

#define KEY1_INT_GPIO_PIN     GPIO_Pin_0
#define KEY1_INT_GPIO_PORT    GPIOA
#define KEY1_INT_GPIO_CLK     RCC_APB2Periph_GPIOA

void EXTI_Key1_Config(void);

#endif /*__BSP_EXTI_H*/

bsp.led.c

#include "bsp_led.h"

void LED_GPIO_Config(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	
	RCC_APB2PeriphClockCmd(LED_G_GPIO_CLK,ENABLE);//打开GPIOB时钟
	
	GPIO_InitStruct.GPIO_Pin=LED_G_GPIO_PIN;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(LED_G_GPIO_PORT,&GPIO_InitStruct);//配置GPIOB
}

bsp.led.h

#ifndef __BSP_LED_H
#define __BSP_LED_H

#include "stm32f10x.h"

#define LED_G_GPIO_PIN     GPIO_Pin_0
#define LED_G_GPIO_PORT    GPIOB
#define LED_G_GPIO_CLK     RCC_APB2Periph_GPIOB

#define LED_G_TOGGLE       {LED_G_GPIO_PORT->ODR^=LED_G_GPIO_PIN;}

void LED_GPIO_Config(void);

#endif /*__BSP_LED_H*/

stm32f10x.it.c中 void EXTI0_IRQHandler(void)部分

void EXTI0_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line0)!=RESET)
	{
		LED_G_TOGGLE;
	}
	EXTI_ClearITPendingBit(EXTI_Line0);
}

至此,编码已全部写完,下一节我们将学习Systick系统定时器。

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值