2-1 EXTI外部中断(gd32)

中断的概念

中断硬件结构/软件结构

EXTI中断

EXTI硬件结构

注:EXTI线在同一时刻只能连接一个GPIO口,如果我们先连接了PA0,然后又连接了PB0那么此时PA0这个IO口就失去作用。

中断触发函数

中断优先级

中断优先级

数值越小优先级越高,抢占优先级可以实现中断嵌套的效果,不同的分组有不同的抢占优先级

EXTI外部中断配置

配置步骤

根据学习库函数原理配置步骤一般为如下所示(类比学习hal库函数原理)

1:配置AFIO,中断引脚寻找

2:配资EXTI,边沿检测以及控制

3:配置NVIC,嵌套中断向量控制器(用于统一分配和管理优先级)

注:按照步骤将下图打通即可

配置EXTI外部中断

static void KeyExtiInit(void)
{
	/*使能EXTI时钟*/
	rcu_periph_clock_enable(RCU_AF);
	/*I/O连接到EXTI线*/
	gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOA, GPIO_PIN_SOURCE_0);
//	gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOC, GPIO_PIN_SOURCE_0);
	//gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOC, GPIO_PIN_SOURCE_0);
	/*配置上升/下降沿*/
	exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
	/*清除标志*/
	exti_interrupt_flag_clear(EXTI_0);
	/*使能中断*/
	nvic_irq_enable(EXTI0_IRQn, 1, 0);
	
	/*
	  key2
	*/
	gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOG, GPIO_PIN_SOURCE_13);
	/*配置上升/下降沿*/
	exti_init(EXTI_13, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
	/*清除标志*/
	exti_interrupt_flag_clear(EXTI_13);

    /*
	  KEY3
	*/
	gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOG, GPIO_PIN_SOURCE_14);
	/*配置上升/下降沿*/
	exti_init(EXTI_14, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
	/*清除标志*/
	exti_interrupt_flag_clear(EXTI_14);
	// 使能中断
	nvic_irq_enable(EXTI10_15_IRQn, 1, 0);

}

中断服务函数代码

 

// EXTI0中断服务函数,对应PA0口
void EXTI0_IRQHandler(void){
		// 判断中断标志位,产生中断时标志位会设置为1
	    if( exti_interrupt_flag_get(EXTI_0) == SET){
		      // 此时说明进入中断
              ToggleLed(LED1);		
        	  // 清除标志位,如果标志位没有清除为0,
			  //会不断地进入中断服务函数当中,所以要清除中断标志位
              exti_interrupt_flag_clear(EXTI_0);
				
		}
}

uint8_t flag = 0;

// EXTI_10_15中断服务函数,对应PA0口
void EXTI10_15_IRQHandler(void){
		// 判断中断标志位,产生中断时标志位会设置为1
	    if( exti_interrupt_flag_get(EXTI_13) == SET){
		      // 此时说明进入中断
              ToggleLed(LED2);		
        	  // 清除标志位,如果标志位没有清除为0,会不断地进入中断服务函数当中,
			  // 所以要清除中断标志位
              exti_interrupt_flag_clear(EXTI_13);			
		}
				// 判断中断标志位,产生中断时标志位会设置为1
	    if( exti_interrupt_flag_get(EXTI_14) == SET){
		      // 此时说明进入中断
              ToggleLed(LED3);		
        	  // 清除标志位,如果标志位没有清除为0,会不断地进入中断服务函数当中,
			  // 所以要清除中断标志位
              exti_interrupt_flag_clear(EXTI_14);
              flag = 1;			
		}
}

 整个程序的完整结构

KEY_DRV.c代码

#include <stdint.h>
#include "gd32f30x.h"
#include "KEY_DRV.h"
#include <stdint.h>
#include "LED.h"

static void KeyGpioInit(void)
{
	rcu_periph_clock_enable(RCU_GPIOA);
	gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_2MHZ, GPIO_PIN_0);
	
	// 初始化剩下的两个按键
	rcu_periph_clock_enable(RCU_GPIOG);
	gpio_init(GPIOG, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_2MHZ, GPIO_PIN_13);
	gpio_init(GPIOG, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_2MHZ, GPIO_PIN_14);
}

static void KeyExtiInit(void)
{
	/*使能EXTI时钟*/
	rcu_periph_clock_enable(RCU_AF);
	/*I/O连接到EXTI线*/
	gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOA, GPIO_PIN_SOURCE_0);
//	gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOC, GPIO_PIN_SOURCE_0);
	//gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOC, GPIO_PIN_SOURCE_0);
	/*配置上升/下降沿*/
	exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
	/*清除标志*/
	exti_interrupt_flag_clear(EXTI_0);
	/*使能中断*/
	nvic_irq_enable(EXTI0_IRQn, 1, 0);
	
	/*
	  key2
	*/
	gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOG, GPIO_PIN_SOURCE_13);
	/*配置上升/下降沿*/
	exti_init(EXTI_13, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
	/*清除标志*/
	exti_interrupt_flag_clear(EXTI_13);

    /*
	  KEY3
	*/
	gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOG, GPIO_PIN_SOURCE_14);
	/*配置上升/下降沿*/
	exti_init(EXTI_14, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
	/*清除标志*/
	exti_interrupt_flag_clear(EXTI_14);
	// 使能中断
	nvic_irq_enable(EXTI10_15_IRQn, 1, 0);

}

/**
***********************************************************
* @brief 按键硬件初始化
* @param
* @return 
***********************************************************
*/
void KeyDrvInit(void)
{
	KeyGpioInit();
	KeyExtiInit();
}

// EXTI0中断服务函数,对应PA0口
void EXTI0_IRQHandler(void){
		// 判断中断标志位,产生中断时标志位会设置为1
	    if( exti_interrupt_flag_get(EXTI_0) == SET){
		      // 此时说明进入中断
              ToggleLed(LED1);		
        	  // 清除标志位,如果标志位没有清除为0,
			  //会不断地进入中断服务函数当中,所以要清除中断标志位
              exti_interrupt_flag_clear(EXTI_0);
				
		}
}

uint8_t flag = 0;

// EXTI_10_15中断服务函数,对应PA0口
void EXTI10_15_IRQHandler(void){
		// 判断中断标志位,产生中断时标志位会设置为1
	    if( exti_interrupt_flag_get(EXTI_13) == SET){
		      // 此时说明进入中断
              ToggleLed(LED2);		
        	  // 清除标志位,如果标志位没有清除为0,会不断地进入中断服务函数当中,
			  // 所以要清除中断标志位
              exti_interrupt_flag_clear(EXTI_13);			
		}
				// 判断中断标志位,产生中断时标志位会设置为1
	    if( exti_interrupt_flag_get(EXTI_14) == SET){
		      // 此时说明进入中断
              ToggleLed(LED3);		
        	  // 清除标志位,如果标志位没有清除为0,会不断地进入中断服务函数当中,
			  // 所以要清除中断标志位
              exti_interrupt_flag_clear(EXTI_14);
              flag = 1;			
		}
}



KEY_DRV.h代码

#ifndef _KEY_DRIVE_H_
#define _KEY_DRIVE_H_
#include <stdint.h>


void KeyDrvInit(void);



#endif

LED.C

#include "gd32f30x.h"                   // Device header
#include "Delay.h"

// 结构体初始化
typedef struct{
  rcu_periph_enum rcu;
  uint32_t gpio;
  uint32_t pin;
	
}Led_GPIO_t;
 
// 保存GPIO口的资源信息
static Led_GPIO_t g_gpioList[] = {
      {RCU_GPIOA,GPIOA,GPIO_PIN_8},
	  {RCU_GPIOE,GPIOE,GPIO_PIN_6},
	  {RCU_GPIOF,GPIOF,GPIO_PIN_6},
};
// 获取内存空间的大小
#define LED_NUM_MAX (sizeof(g_gpioList)/sizeof(g_gpioList[0]))
 
 
void LedDrv_Init(void){
    uint8_t i = 0;
	for(i = 0; i < LED_NUM_MAX;i++){
	   rcu_periph_clock_enable(g_gpioList[i].rcu);
	   gpio_init(
				g_gpioList[i].gpio,
				GPIO_MODE_OUT_PP,
				GPIO_OSPEED_2MHZ,
				g_gpioList[i].pin
		   );
	   // 熄灭LED灯	
	   gpio_bit_reset(g_gpioList[i].gpio,g_gpioList[i].pin);	
	   
	}
}
 
 
void TurnOnLed(uint8_t ledNO){
   if(ledNO >= LED_NUM_MAX){
      return;
   }
   gpio_bit_set(g_gpioList[ledNO].gpio,g_gpioList[ledNO].pin);
};

void TrunOffLed(uint8_t LedOff){
   if(LedOff >= LED_NUM_MAX){
      return;
   }
   gpio_bit_reset(g_gpioList[LedOff].gpio,g_gpioList[LedOff].pin);
};

// led状态取反
void ToggleLed(uint8_t ledNO){
	FlagStatus bit_state;
	bit_state = gpio_input_bit_get(g_gpioList[ledNO].gpio,g_gpioList[ledNO].pin);
	// 当获取到的数据为0的时候 1 -0 等于 0 ,当获取到的数据为1的时候 1 - 1 = 0;
	bit_state = (FlagStatus)(1 - bit_state); 
	gpio_bit_write(g_gpioList[ledNO].gpio,g_gpioList[ledNO].pin,bit_state);
	
    
};


 

LED.H

 

#ifndef _LED_H_
#define _LED_H_
 
#include <stdint.h>
 
#define LED1 0
#define LED2 1
#define LED3 2
 
void LedDrv_Init(void);
// 点亮LED ledNO 标号0-2
void TurnOnLed(uint8_t ledNO);
void TrunOffLed(uint8_t LedOff);
void ToggleLed(uint8_t ledNO);
 
 
 
#endif

main.c

#include <stdint.h>
#include "gd32f30x.h"
#include "Delay.h"
#include "LED.h"
#include "KEY_DRV.h"

extern uint8_t flag;
int main(void)
{    
	LedDrv_Init();
	KeyDrvInit();
	while(1){
	   	if(flag == 1){
		    /*执行led是否被按下*/
			flag = 0;
			
		}	
	} 
	
}

仿真调试

 

按键运算补充

抢占优先级的作用

注:高优先级的任务会抢占低优先级的任务,数值越小表示优先级别越高,当抢占式优先级相同时

如果有一个任务响应式优先级更高,但是实际上抢占还是不会发生,仍然是执行前面优先级部分。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/617720.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[AutoSar]BSW_Diagnostic_004 ReadDataByIdentifier(0x22)的配置和实现

目录 关键词平台说明背景一、配置DcmDspDataInfos二、配置DcmDspDatas三、创建DcmDspDidInfos四、创建DcmDspDids五、总览六、创建一个ASWC七、mapping DCM port八、打开davinci developer&#xff0c;创建runnabl九、生成代码 关键词 嵌入式、C语言、autosar、OS、BSW、UDS、…

【HCIP学习】BGP选路、过滤及属性

一、BGP路由选路原则&#xff08;13条&#xff09; 1、首先丢弃下一跳&#xff08;NEXT_HOP&#xff09;不可达的路由&#xff1b; 2、优选Preferred-value值最大的路由&#xff1b;默认为0&#xff1b; Preferred-value&#xff1a;定义&#xff1a;首选项。 属性值&#…

5. 简单说一说uniapp中的语法吧

前言 如果你 知道Vue3并且对Vue3的语法有一定了解&#xff0c;请跳过这一章&#xff0c;由于后续项目主要是基于Vue3TypeScript&#xff0c;因此提前简单概述一些Vue3的基础语法~ 本文的目的是 期望通过对本文的阅读后能对Vue3的每个语法有一个简单的印象&#xff0c;至少要知…

Android 13 系统自定义安全水印

效果 源码实现 frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public final void showSafeModeOverlay() {View v LayoutInflater.from(mContext).inflate(com.android.internal.R.layout.safe_mode, null);WindowManager.Layout…

《C++学习笔记---初阶篇6》---string类 上

目录 1. 为什么要学习string类 1.1 C语言中的字符串 2. 标准库中的string类 2.1 string类(了解) 2.2 string类的常用接口说明 2.2.1. string类对象的常见构造 2.2.2. string类对象的容量操作 2.2.3.再次探讨reserve与resize 2.2.4.string类对象的访问及遍历操作 2.2.5…

宝塔面板怎么解决nginx跨域问题

1.找到宝塔的nginx配置文件 宝塔有一点不同&#xff0c;nginx配置文件不在nginx的安装目录中&#xff0c;应当去/www/server/panel/vhost/nginx找到 2.添加你要跨域的地址 location /api {proxy_pass http://localhost:8080;proxy_set_header Host $host;proxy_set_header X-…

爱普生推出5G基站可用耐高温高稳定性温补晶振

爱普生推出了六款新的温补晶振型号:TG7050CKN&#xff0c;TG7050SKNTG7050CMN&#xff0c;TG7050SMN&#xff0c;TG-5510CA&#xff0c;TG-5511CA。这几款的特点就是耐高温温度可达105℃C高温&#xff0c;而且都是高稳定性温补晶振&#xff0c;而且都是7050尺寸&#xff0c;这个…

map 和 set 的介绍和简单使用

目录 1. 序列式容器和关联式容器 2. 键值对 2.1. make_pair 3. 树形结构的关联式容器 3.1. set (Key 模型) 3.1.1. std::set::find 和 std::set::count 3.2. map (Key-Value 模型) 3.2.1. std::map::insert 3.2.2. std::map::operator[] 3.3. multiset 3.4.1. std::…

[Java EE] 文件IO(一):文件概念与文件系统操作

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …

vscode怎么设置背景图片?

vscode背景图片是可以自己设置的&#xff0c;软件安装后默认背景的颜色是黑色的&#xff0c;这是默认的设计&#xff0c;如果要修改背景为指定的图片&#xff0c;那么我们需要安装插件&#xff0c;然后再通过代码来设置背景图片的样式&#xff0c;下面我们就来看看详细的教程。…

大数据交通行政执法监测系统

交通行政执法监测系统应用系统按照监测主体可分为&#xff1a;出租车交通违法监测&#xff0c;客车交通违法监测&#xff0c;货车、危化品车辆交通违法监测&#xff0c;非法营运车辆监测。功能模块涵盖&#xff1a;特征识别、档案查询、预警分析等。 &#xff08;1&#xff09;…

java中EQ、NE、GE、GT、LE、LT

关系运算符 包括EQ、NE、GE、GT、LE、LT几个&#xff0c;关系运算符返回的是真“True”或假“False”。 eq&#xff08;Equal to&#xff09; 等 运算符 &#xff0c;如果运算符两边相同则返回真&#xff0c;否则返回假&#xff1b; ne&#xff08;Not Equal to&#xff09; 不…

力扣HOT100 - 55. 跳跃游戏

解题思路&#xff1a; class Solution {public boolean canJump(int[] nums) {int n nums.length;int maxReach 0;// 正常来说每次至少跳一格&#xff0c;所以最多循环n次for (int i 0; i < n; i) {if (i > maxReach) return false;// 这种情况代表遇到了0&#xff0…

使用train.py----yolov7

准备工作 在训练之前&#xff0c;数据集的工作和配置环境的工作要做好 数据集&#xff1a;看这里划分数据集&#xff0c;训练自己的数据集。_划分数据集后如何训练-CSDN博客 划分数据集2&#xff0c;详细说明-CSDN博客 配置环境看这里 从0开始配置环境-yolov7_gpu0是inter g…

11、关系运算符、逻辑运算符(讲解 和 的区别)、赋值表达式、三目表达式、运算符优先级(超详细版本)+结合性的分析

这里写目录标题 一、关系运算符&#xff08;比较运算符&#xff09;二、⭐逻辑运算符1、 && 和 &2、|| 或 |3、&#xff01;4、^ 三、赋值运算符四、三目运算符&#xff08;条件运算符&#xff09;五、运算符优先级 在讲之前先明确几个概念&#xff1a; 1、单目运算…

【Arduino】ESP32/ESP8266 JSON格式解析

目录 1、JSON 2、JSON语法格式 基本概念&#xff1a; 语法规则&#xff1a; 数据类型&#xff1a; 示例&#xff1a; 3、JSON解析 单一对象JSON解析&#xff08;无嵌套&#xff09; JSON数组解析 使用ArduinoJson官网在线工具解析JSON信息 ESP8266闪存存储的JSON解析…

VScode 修改 Markdown Preview Enhanced 主题与字体

VScode 修改 Markdown Preview Enhanced 主题与字体 1. 修改前后效果对比2. 修改主题2.1 更改默认主题2.2 修改背景色 3. 修改字体 VS Code基础入门使用可查看&#xff1a; VS Code 基础入门使用&#xff08;配置&#xff09;教程 其他Vs Code 配置可关注查看&#xff1a; Vs C…

ElasticSearch 与 OpenSearch:拉开性能差距

Elasticsearch 与 OpenSearch&#xff1a;扩大性能差距 对于任何依赖快速、准确搜索数据的组织来说&#xff0c;强大、快速且高效的搜索引擎是至关重要的元素。对于开发人员和架构师来说&#xff0c;选择正确的搜索平台可以极大地影响您的组织提供快速且相关结果的能力。在我们…

docker(二):Centos安装docker

文章目录 1、安装docker2、启动docker3、验证 官方文档&#xff1a;https://docs.docker.com/engine/install/centos/ 1、安装docker 下载依赖包 yum -y install gcc yum -y install gcc-c yum install -y yum-utils设置仓库 yum-config-manager --add-repo http://mirrors…

在xAnyLabeling中加载自己训练的yolov8s-obb模型进行半自动化标注

任务思路&#xff1a; 先使用xAnyLabeling标注一部分样本&#xff0c;训练出v1版本的yolov8-obb模型&#xff0c;然后加载yolov8-obb模型到xAnyLabeling中对其余样本进行半自动化标注。节省工作量。 任务流程&#xff1a; 1.准备xAnyLabeling标注工具 下载代码&#xff0c;…