STM32第十节(中级篇):EXTI(第二节)——GPIO外部中断代码讲解

2024-04-13 16:12

本文主要是介绍STM32第十节(中级篇):EXTI(第二节)——GPIO外部中断代码讲解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

        好久不见,从今天开始我们接着学习有关EXTI中断的内容。本节课我们通过分析GPIO外部中断代码来讲解我们新的知识点。


STM32第十节(中级篇):EXTI(第二节)——GPIO外部中断代码讲解

        首先,我们拷贝一份上节课的文件,然后进行我们本节课的学习。我们先新建一个文件夹到USER里面,然后写一个.c.h文件,分别为bsp_exti.c以及bsp_exti.h文件。然后导入到keil5中。

EXTI函数库代码讲解

初始化GPIO

        我们打开bsp_exti.c文件,然后创建一个函数void EXIT_Key_Config(void),使得按键初始化,即连接到我们的GPIO端口。首先初始化GPIO,GPIO_InitTypeDef  GPIO_InitStruct; 。在这里,我们之前编写的led函数中就写过关于GPIO的宏定义。并且在bsp_exti.h文件中写入。以下代码就是我们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_GPIOAvoid EXIT_Key_Config(void);#endif /* __BSP_EXTI_H_ */

        我们可以看到,我们初始化GPIO的时候,还是老三样:初始化PIN,PORT以及打开为RCC_APB2Periph_GPIOAde的时钟,并将其宏定义为#define KEY1_INT_GPIO_CLK。

        然后我们打开bsp_exti.c文件,然后编写我们的函数。

        我们首先要打开APB2线路上的时钟,使用RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK, ENABLE);函数。他有两个参量,一个是打开RCC_APB2Periph_GPIOA端口,即KEY1_INT_GPIO_CLK。第二个参量我们设置为ENABLE 使得使能打开

        然后我们配置GPIO结构体内容,包括PIN要设置为KEY1_INT_GPIO_PIN,即Pin0。然后就是MODE的配置,配置为浮空输入模式,就是使用外部决定电压。我们默认有一个电阻拉低了电平。

        最后就是设置GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStruct);    函数,我们在这里就不阐述过多,直接写入成员变量KEY1_INT_GPIO_PORT, &GPIO_InitStruct,表示控制的是GPIOA端口以及取GPIO_InitStruct的地址。代码如下所示:

	GPIO_InitTypeDef  GPIO_InitStruct;// 初始化GPIORCC_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用于产生中断/事件

        从这个框图中我们可以知道要先选择输入线,那么我们在选择输入线的时候,自然是要配置寄存器,你们我们配置的是那个寄存器呢?显而易见我们要配置的是AFIO_EXTICR1寄存器。 

         首先,我们选择GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);函数来进行初始化EXTI。里面有两个形参,分别是GPIO_PortSourceGPIOA, 以及GPIO_PinSource0。我们刚刚操作的是AFIO外设,我们知道,输入线默认的时钟是关闭的,那么我们就要配置时钟,即    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);函数,打开RCC_APB2Periph_AFIO端口上的时钟。

        然后就是配置GPIO_InitStruct初始化结构体成员:

	EXTI_InitTypeDef  EXTI_InitStruct;// 初始化EXTIRCC_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);	//写入寄存器中(指针)

初始化NIVC处理中断

        我们知道,在刚刚我们已经配置好了选择线,那么现在就要打开NVIC,涉及到中断。那么我们就要配置中断优先级:那么我们就要编写EXTI_NVIC_Config()函数。我们要找到关于NVIC结构体,编写结构体成员变量,我们先定义一个变量,叫NVIC嵌套向量中断寄存器:NVIC_InitTypeDef  NVIC_InitStruct;定义结构体变量。接着我们就要进行中断分组:使用NVIC_PriorityGroupConfig(unit32_t NVIC_PriorityGroup)函数,配置中断分组。

    NVIC_InitTypeDef NVIC_InitStruct;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

        在配置完中断分组之后,我们就要初始化每个结构体成员,接着我们设置一个static关键字,使得该函数只能在该文件下使用,其他的文件函数是调用不了的:

static void EXTI_NVIC_Config(void)
{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);
}

        在我们配置中断优先级的时候,我们如果选择组0,那么我们就有0个位来表示(0)我们的主优先级,剩下四个位(16)来表示子优先级,对于剩下的中断优先级分组也是如此:

编写中断服务函数

        编译之后无错误之后,我们的中断服务函数要写在stm32f10x.it.c文件中。我们找到void SysTick_Handler(void)函数,在其下方编写新的函数void EXTI0_IRQHandler(void):

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

        我们还需要在stm32f10x.it.c文件中添加bsp_led,h文件,这样我们的中断函数就写完啦。接下来是代码展示(包括KEY2的搭建):

代码展示

bsp_exti.c文件

static void NVIC_Configuration(void)
{NVIC_InitTypeDef NVIC_InitStructure;/* 配置NVIC为优先级组1 *//* 提示 NVIC_PriorityGroupConfig() 在整个工程只需要调用一次来配置优先级分组*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);/* 配置中断源:按键1 */NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;/* 配置抢占优先级 */NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;/* 配置子优先级 */NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;/* 使能中断通道 */NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);/* 配置中断源:按键2,其他使用上面相关配置 */  NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;NVIC_Init(&NVIC_InitStructure);
}/*** @brief  配置 IO为EXTI中断口,并设置中断优先级* @param  无* @retval 无*/
void EXTI_Key_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure;/*开启按键GPIO口的时钟*/RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE);RCC_APB2PeriphClockCmd(KEY2_INT_GPIO_CLK,ENABLE);/* 配置 NVIC 中断*/NVIC_Configuration();/*--------------------------KEY1配置-----------------------------*//* 选择按键用到的GPIO */	GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;/* 配置为浮空输入 */	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);/* 选择EXTI的信号源 */GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE); EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;/* EXTI为中断模式 */EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;/* 上升沿中断 */EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;/* 使能中断 */	EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);/*--------------------------KEY2配置-----------------------------*//* 选择按键用到的GPIO */	GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;/* 配置为浮空输入 */	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);/* 选择EXTI的信号源 */GPIO_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, KEY2_INT_EXTI_PINSOURCE); EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;/* EXTI为中断模式 */EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;/* 下降沿中断 */EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;/* 使能中断 */	EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);
}

bsp_exti.h文件

#ifndef __EXTI_H
#define	__EXTI_H#include "stm32f10x.h"//引脚定义
#define KEY1_INT_GPIO_PORT         GPIOA
#define KEY1_INT_GPIO_CLK          (RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO)
#define KEY1_INT_GPIO_PIN          GPIO_Pin_0
#define KEY1_INT_EXTI_PORTSOURCE   GPIO_PortSourceGPIOA
#define KEY1_INT_EXTI_PINSOURCE    GPIO_PinSource0
#define KEY1_INT_EXTI_LINE         EXTI_Line0
#define KEY1_INT_EXTI_IRQ          EXTI0_IRQn#define KEY1_IRQHandler            EXTI0_IRQHandler#define KEY2_INT_GPIO_PORT         GPIOC
#define KEY2_INT_GPIO_CLK          (RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO)
#define KEY2_INT_GPIO_PIN          GPIO_Pin_13
#define KEY2_INT_EXTI_PORTSOURCE   GPIO_PortSourceGPIOC
#define KEY2_INT_EXTI_PINSOURCE    GPIO_PinSource13
#define KEY2_INT_EXTI_LINE         EXTI_Line13
#define KEY2_INT_EXTI_IRQ          EXTI15_10_IRQn#define KEY2_IRQHandler            EXTI15_10_IRQHandlervoid EXTI_Key_Config(void);#endif /* __EXTI_H */

stm32f10_it.c文件

void KEY1_IRQHandler(void)
{//确保是否产生了EXTI Line中断if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) {// LED1 取反		LED1_TOGGLE;//清除中断标志位EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);     }  
}void KEY2_IRQHandler(void)
{//确保是否产生了EXTI Line中断if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) {// LED2 取反		LED2_TOGGLE;//清除中断标志位EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);     }  
}

小结

        我们本节的内容到这里就都结束啦,下节课开始我们就开始学习有关SysTick(滴答计时器)相关的内容。

这篇关于STM32第十节(中级篇):EXTI(第二节)——GPIO外部中断代码讲解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/900608

相关文章

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

Java中Map.Entry()含义及方法使用代码

《Java中Map.Entry()含义及方法使用代码》:本文主要介绍Java中Map.Entry()含义及方法使用的相关资料,Map.Entry是Java中Map的静态内部接口,用于表示键值对,其... 目录前言 Map.Entry作用核心方法常见使用场景1. 遍历 Map 的所有键值对2. 直接修改 Ma

深入解析 Java Future 类及代码示例

《深入解析JavaFuture类及代码示例》JavaFuture是java.util.concurrent包中用于表示异步计算结果的核心接口,下面给大家介绍JavaFuture类及实例代码,感兴... 目录一、Future 类概述二、核心工作机制代码示例执行流程2. 状态机模型3. 核心方法解析行为总结:三

Java -jar命令如何运行外部依赖JAR包

《Java-jar命令如何运行外部依赖JAR包》在Java应用部署中,java-jar命令是启动可执行JAR包的标准方式,但当应用需要依赖外部JAR文件时,直接使用java-jar会面临类加载困... 目录引言:外部依赖JAR的必要性一、问题本质:类加载机制的限制1. Java -jar的默认行为2. 类加

Java进程CPU使用率过高排查步骤详细讲解

《Java进程CPU使用率过高排查步骤详细讲解》:本文主要介绍Java进程CPU使用率过高排查的相关资料,针对Java进程CPU使用率高的问题,我们可以遵循以下步骤进行排查和优化,文中通过代码介绍... 目录前言一、初步定位问题1.1 确认进程状态1.2 确定Java进程ID1.3 快速生成线程堆栈二、分析

python获取cmd环境变量值的实现代码

《python获取cmd环境变量值的实现代码》:本文主要介绍在Python中获取命令行(cmd)环境变量的值,可以使用标准库中的os模块,需要的朋友可以参考下... 前言全局说明在执行py过程中,总要使用到系统环境变量一、说明1.1 环境:Windows 11 家庭版 24H2 26100.4061

pandas实现数据concat拼接的示例代码

《pandas实现数据concat拼接的示例代码》pandas.concat用于合并DataFrame或Series,本文主要介绍了pandas实现数据concat拼接的示例代码,具有一定的参考价值,... 目录语法示例:使用pandas.concat合并数据默认的concat:参数axis=0,join=

java -jar命令运行 jar包时运行外部依赖jar包的场景分析

《java-jar命令运行jar包时运行外部依赖jar包的场景分析》:本文主要介绍java-jar命令运行jar包时运行外部依赖jar包的场景分析,本文给大家介绍的非常详细,对大家的学习或工作... 目录Java -jar命令运行 jar包时如何运行外部依赖jar包场景:解决:方法一、启动参数添加: -Xb

C#代码实现解析WTGPS和BD数据

《C#代码实现解析WTGPS和BD数据》在现代的导航与定位应用中,准确解析GPS和北斗(BD)等卫星定位数据至关重要,本文将使用C#语言实现解析WTGPS和BD数据,需要的可以了解下... 目录一、代码结构概览1. 核心解析方法2. 位置信息解析3. 经纬度转换方法4. 日期和时间戳解析5. 辅助方法二、L

Python使用Code2flow将代码转化为流程图的操作教程

《Python使用Code2flow将代码转化为流程图的操作教程》Code2flow是一款开源工具,能够将代码自动转换为流程图,该工具对于代码审查、调试和理解大型代码库非常有用,在这篇博客中,我们将深... 目录引言1nVflRA、为什么选择 Code2flow?2、安装 Code2flow3、基本功能演示