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

相关文章

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

C# WinForms存储过程操作数据库的实例讲解

《C#WinForms存储过程操作数据库的实例讲解》:本文主要介绍C#WinForms存储过程操作数据库的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、存储过程基础二、C# 调用流程1. 数据库连接配置2. 执行存储过程(增删改)3. 查询数据三、事务处

Spring Boot 3.4.3 基于 Spring WebFlux 实现 SSE 功能(代码示例)

《SpringBoot3.4.3基于SpringWebFlux实现SSE功能(代码示例)》SpringBoot3.4.3结合SpringWebFlux实现SSE功能,为实时数据推送提供... 目录1. SSE 简介1.1 什么是 SSE?1.2 SSE 的优点1.3 适用场景2. Spring WebFlu

java之Objects.nonNull用法代码解读

《java之Objects.nonNull用法代码解读》:本文主要介绍java之Objects.nonNull用法代码,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录Java之Objects.nonwww.chinasem.cnNull用法代码Objects.nonN

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

python+opencv处理颜色之将目标颜色转换实例代码

《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤

在C#中调用Python代码的两种实现方式

《在C#中调用Python代码的两种实现方式》:本文主要介绍在C#中调用Python代码的两种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#调用python代码的方式1. 使用 Python.NET2. 使用外部进程调用 Python 脚本总结C#调