【N32L40X】学习笔记04-gpio中断库

gpio中断

  1. 该函数库的目的就是在统一的地方配置,将配置的不同项放置在一个结构体内部
  2. 使用一个枚举来定义一个的别名

NVIC 寄存器

NVIC 相关的寄存器定义了可以在 core_cm4.h 文件中找到。我们直接通过程序的定义来分

析 NVIC 相关的寄存器,其定义如下:

typedef struct{__IOM uint32_t ISER[8U]; /* 中断使能寄存器 */uint32_t RESERVED0[24U];__IOM uint32_t ICER[8U]; /* 中断清除使能寄存器 */uint32_t RSERVED1[24U];__IOM uint32_t ISPR[8U]; /* 中断使能挂起寄存器 */uint32_t RESERVED2[24U];__IOM uint32_t ICPR[8U]; /* 中断解挂寄存器 */uint32_t RESERVED3[24U];__IOM uint32_t IABR[8U]; /* 中断有效位寄存器 */uint32_t RESERVED4[56U];__IOM uint8_t IP[240U]; /* 中断优先级寄存器(8Bit 位宽) */uint32_t RESERVED5[644U];__OM uint32_t STIR; /* 中断触发中断寄存器 */} NVIC_Type;

下面重点介绍这几个寄存器:

ISER[8]:ISER 全称是:Interrupt Set Enable Registers,这是一个中断使能寄存器组。上面说了 CM4 内核支持 256 个中断,这里用 8 个 32 位寄存器来控制,每个位控制一个中断。但是STM32F407 的可屏蔽中断最多只有 82 个,所以对我们来说,有用的就是两个(ISER[0~3]),总共可以表示 128 个中断。而 STM32F407 只用了其中的 82 个。ISER[0]的 bit0~31 分别对应中断031;ISER[1]的bit031 对应中断 32~63; ISER[2]的 bit0~16 对应中断 64~81,这样总共 82 个中断就可以分别对应上了。你要使能某个中断,必须设置相应的 ISER 位为 1,使该中断被使能(这里仅仅是使能,还要配合中断分组、屏蔽、IO 口映射等设置才算是一个完整的中断设置)。

ICER[8]:全称是:Interrupt Clear Enable Registers,是一个中断除能寄存器组。该寄存器组与 ISER 的作用恰好相反,是用来清除某个中断的使能的。其对应位的功能,也和 ISER 一样。这里要专门设置一个 ICER 来清除中断位,而不是向 ISER 写 0 来清除,是因为 NVIC 的这些寄存器都是写 1 有效的,写 0 是无效的。

ISPR[8]:全称是:Interrupt Set Pending Registers,是一个中断使能挂起控制寄存器组。每个位对应的中断和 ISER 是一样的。通过置 1,可以将正在进行的中断挂起,而执行同级或更高级别的中断。写 0 是无效的。

ICPR[8]:全称是:Interrupt Clear Pending Registers,是一个中断解挂控制寄存器组。其作用与 ISPR 相反,对应位也和 ISER 是一样的。通过设置 1,可以将挂起的中断解挂。写 0 无效。

IABR[8]:全称是:Interrupt Active Bit Registers,是一个中断激活标志位寄存器组。对应位所代表的中断和 ISER 一样,如果为 1,则表示该位所对应的中断正在被执行。这是一个只读寄存器,通过它可以知道当前在执行的中断是哪一个。在中断执行完了由硬件自动清零。

IP [240]:全称是:Interrupt Priority Registers,是一个中断优先级控制的寄存器组。这个寄存器组相当重要!STM32F407 的中断分组与这个寄存器组密切相关。IP 寄存器组由 240 个 8bit的寄存器组成,每个可屏蔽中断占用 8bit,这样总共可以表示 240 个可屏蔽中断。而 STM32F407只用到了其中的 82 个。IP[81]~IP[0]分别对应中断 81~0。而每个可屏蔽中断占用的 8bit 并没有全部使用,而是只用了高 4 位。这 4 位,又分为抢占优先级和子优先级。抢占优先级在前,子优先级在后。

中断优先级

STM32 中的中断优先级可以分为:抢占式优先级和响应优先级

每个中断源都需要被指定这两种优先级。抢占式优先级和响应优先级的区别:

抢占优先级:抢占优先级高的中断可以打断正在执行的抢占优先级低的中断。

响应优先级:抢占优先级相同,响应优先级高的中断不能打断响应优先级低的中断。

还有一种情况就是当两个或者多个中断的抢占式优先级和响应优先级相同时,那么就遵循自然优先级,看中断向量表的中断排序,数值越小,优先级越高。在 NVIC 中由寄存器 NVIC_IPR0-NVIC_IPR59 共 60 个寄存器控制中断优先级,每个寄存器的每 8 位又分为一组,可以分 4 组,所以就有了 240 组宽度为 8bit 的中断优先级控制寄存器,原则上每个外部中断可配置的优先级为 0~255,数值越小,优先级越高。但是实际上 M3 /M4/M7 芯片为了精简设计,只使用了高四位[7:4],低四位取零,这样以至于最多只有 16 级中断嵌套,即 2^4=16。对于 NVCI 的中断优先级分组:STM32F407 将中断分为 5 个组,组 0~4。该分组的设置是由 SCB->AIRCR 寄存器的 bit10~8 来定义的。具体的分配关系如表 16.1.1.2.1 所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wqd7jon9-1689952083562)(./picture/image-20230718172957119.png)]

通过这个表,我们就可以清楚的看到组 0~4 对应的配置关系,例如优先级分组设置为 3,那么此时所有的 82 个中断,每个中断的中断优先寄存器的高四位中的最高 3 位是抢占优先级,低 1 位是响应优先级。每个中断,你可以设置抢占优先级为 0~7,响应优先级为 1 或 0。抢占优先级的级别高于响应优先级。而数值越小所代表的优先级就越高。

结合实例说明一下:假定设置中断优先级分组为 2,然后设置中断 3(RTC_WKUP 中断)的抢占优先级为 2,响应优先级为 1。中断 6(外部中断 0)的抢占优先级为 3,响应优先级为 0。中断 7(外部中断 1)的抢占优先级为 2,响应优先级为 0。那么这 3 个中断的优先级顺序为:

中断 7>中断 3>中断 6。

上面例子中的中断 3 和中断 7 都可以打断中断 6 的中断。而中断 7 和中断 3 却不可以相互打断

exit.c

#include "bsp_include.h"#include "exti/bsp_exti.h"//中断触发回调函数
void call_back_exti_handler (int id)
{//  led_on_blink(LED1);led_on_blink(LED0);
}static exti_t s_extis[EXTI_NUM]= {{GPIOA,GPIO_PIN_0,RCC_APB2_PERIPH_GPIOA,EXTI_LINE0,GPIOA_PORT_SOURCE,GPIO_PIN_SOURCE0,EXTI0_IRQn,call_back_exti_handler},{GPIOA,GPIO_PIN_1,RCC_APB2_PERIPH_GPIOA,EXTI_LINE1,GPIOA_PORT_SOURCE,GPIO_PIN_SOURCE1,EXTI1_IRQn,call_back_exti_handler},{GPIOA,GPIO_PIN_2,RCC_APB2_PERIPH_GPIOA,EXTI_LINE2,GPIOA_PORT_SOURCE,GPIO_PIN_SOURCE2,EXTI2_IRQn,call_back_exti_handler},};static void bsp_exti_rcc_config(exti_t *pexti)
{RCC_EnableAPB2PeriphClk(pexti->gpio_rcc | RCC_APB2_PERIPH_AFIO, ENABLE);}
static void bsp_exti_init(exti_t *pexti)
{GPIO_InitType GPIO_InitStructure;EXTI_InitType EXTI_InitStructure;NVIC_InitType NVIC_InitStructure;/* 时钟配置 */bsp_exti_rcc_config(pexti);/*配置gpio*/if (pexti->pin <= GPIO_PIN_ALL){GPIO_InitStruct(&GPIO_InitStructure);GPIO_InitStructure.Pin        = pexti->pin;GPIO_InitStructure.GPIO_Pull  = GPIO_Pull_Down;GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Input;GPIO_InitPeripheral(pexti->gpiox, &GPIO_InitStructure);}/*配置外部中断源*/GPIO_ConfigEXTILine(pexti->source_port, pexti->source_pin);/*外部中断配置*/EXTI_InitStructure.EXTI_Line    = pexti->exti_line;EXTI_InitStructure.EXTI_Mode    = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // EXTI_Trigger_Rising;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_InitPeripheral(&EXTI_InitStructure);/*设置中断优先级*/NVIC_InitStructure.NVIC_IRQChannel                   = pexti->irq;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x07;NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0x00;NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;NVIC_Init(&NVIC_InitStructure);//经过测试NVIC_Init函数设置的优先级无效,需要使用NVIC_SetPriority(puartx->irqx,7);NVIC_SetPriority(puartx->irqx,7);
}//一键初始化所有中断线
void bsp_extis_init(void)
{for(int i=0; i<EXTI_NUM; i++){bsp_exti_init(s_extis+i);}
}/*
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
EXTI9_5_IRQHandler
EXTI15_10_IRQHandler
*/
//中断集中处理位置
static void bsp_exti_irq_handler()
{for(int i=0; i<EXTI_NUM; i++){exti_t *pexti = s_extis+i;if (RESET != EXTI_GetITStatus(pexti->exti_line)){EXTI_ClrITPendBit(pexti->exti_line);if(pexti->call_back){pexti->call_back(i);pexti->pulse_cnt++;}}}
}//重置脉冲计数
void bsp_exti_reset_pulse_cnt(void)
{for(int i=0; i<EXTI_NUM; i++){exti_t *pexti = s_extis+i;pexti->pulse_cnt=0;}
}
//获取脉冲计数
uint32_t  bsp_exti_get_pulse_cnt(EM_EXTI_ID id)
{if(EXTI_NUM>id){return s_extis[id].pulse_cnt;}return 0;}
void EXTI0_IRQHandler(void)
{bsp_exti_irq_handler();
}
void EXTI1_IRQHandler(void)
{bsp_exti_irq_handler();
}
void EXTI2_IRQHandler(void)
{bsp_exti_irq_handler();
}

exit.h

#ifndef _BSP_EXTI_H_
#define _BSP_EXTI_H_#include <stdint.h>
#include "n32l40x.h"typedef enum
{EXTI_1,EXTI_2,EXTI_3,EXTI_NUM//EXTI数量
}EM_EXTI_ID;typedef void (*call_back_exti_fun)(int id);
typedef struct
{GPIO_Module* gpiox;uint16_t pin;uint32_t gpio_rcc;uint32_t exti_line;uint32_t source_port;//中断源分组uint32_t source_pin;//中断pinuint32_t irq;call_back_exti_fun call_back;uint32_t pulse_cnt;}exti_t;	//一键初始化所有中断线
void bsp_extis_init(void);
//重置脉冲计数
void bsp_exti_reset_pulse_cnt(void);
//获取脉冲计数
uint32_t  bsp_exti_get_pulse_cnt(EM_EXTI_ID id);
#endif

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RocketMQ(1.NameServer源码)

NameServer功能简述 主要功能如下 服务注册与发现&#xff1a;Nameserver扮演了RocketMQ集群中服务注册中心的角色。当RocketMQ中的Broker、Producer和Consumer启动时&#xff0c;它们会向Nameserver注册自己的网络地址和角色信息。Nameserver维护着集群中所有活跃实例的信息…

openfeign调用文件服务的文件上传接口报错:Current request is not a multipart request

解决办法&#xff1a; Api 接口 Api(tags "文件上接口") RestController public class FileController {Autowiredprivate FileFeignService fileFeignService;ApiOperation("上传文件")PostMapping(value "/uploadFile")public ResData<…

python常用数据类型区别

1.set集合和dict字典的区别 set没有对应的value值&#xff0c;两者都是可变类型&#xff0c;即不可哈希;两者的内部元素是不可变类型&#xff0c;即可哈希&#xff0c;都无索引&#xff0c;不可进行切片和根据索引进行的操作。 2.set集合和list列表的区别 相同点 都是可变类…

zookeeper学习(一) Standalone模式(单机模式)安装

安装准备 centos7环境jdk1.8环境zookeeper安装包 安装jdk 上传jdk安装包解压安装包到目录中 tar -zxvf jdk-8u361-linux-x64.tar.gz如果需要指定目录可以在后面加上 -C&#xff0c;如 tar -zxvf jdk-8u361-linux-x64.tar.gz -C 目录配置jdk环境变量 vim /etc/profile打开…

Dijkstra 算法——求解最短路径问题

迪杰斯特拉算法&#xff08;Dijkstra’s algorithm&#xff09;是一种用于解决单源最短路径问题的贪心算法。它可以找到从一个起始顶点到其他所有顶点的最短路径&#xff0c;并且适用于边的权重非负的图。 算法步骤如下&#xff1a; 创建一个数组 dist&#xff0c;用于保存起…

react当我们有两个完全不相关的组件想要通信时,就可以利用这种模式,其中一个组件负责订阅某个消息,而另一个元素则负责发送这个消息。使用Context配合

在nextjs项目中&#xff0c;发现两个组件没啥关系&#xff0c;例如一个是一直存在的头部组件&#xff0c;另一个是页面中的组件&#xff0c;当我点击头部组件中的特定按钮时&#xff0c;把数据传递到页面组件中&#xff0c;页面组件接受到canshu数据后在做其他操作&#xff0c;…

入门前端监控

背景 前端监控是指通过一系列手段对Web页面或应用程序进行实时监控和数据采集&#xff0c;以了解页面或应用程序的性能状况、用户行为等等&#xff0c;并及时发现和解决潜在的问题。一个完整的前端监控平台可以包括&#xff1a;数据收集与上报、数据整理与存储、数据展示这里仅…

redis---持久化和数据类型的基本操作

目录 1.redis持久化 2.redis数据类型 1.redis持久化 【1】RDB 启用rdb&#xff0c;查看是否有对应文件生成 1.进入配置文件&#xff0c;修改配置 [rootclient ~]# vim /etc/redis.conf save 60 5 # 自动出发机制&#xff08;60秒内进行5次操…

Java连锁门诊医院HIS信息管理系统源码

Java连锁门诊医院HIS信息管理系统源码&#xff1a;SaaS运维平台多医院多机构多门诊入驻强大的电子病历完整开发文档 一、系统概述 ❉采用主流成熟技术&#xff0c;软件结构简洁、代码规范易阅读&#xff0c;SaaS应用&#xff0c;全浏览器访问前后端分离&#xff0c;多服务协同…

通过两种实现方式理解CANoe TC8 demo是如何判断接收的以太网报文里的字段的

假设有一个测试用例,需求是:编写一个测试用例,发送一条icmpv4 echo request报文给DUT,identifier字段设置为10。判断DUT能够回复icmpv4 echo reply报文,且identifier字段值为10。 实现:在canoe的simulation setup界面插入一个test节点,ip地址为:192.168.0.1,mac地址为…

具身智能,是机器人的“冷饭热炒”吗?

大模型正如火如荼&#xff0c;下一个AI风口就来了。 如果你关注2023世界人工智能大会等行业峰会&#xff0c;以及英伟达、微软、谷歌、特斯拉和国內科技大厂的最新发布会&#xff0c;除了“大模型”&#xff0c;应该会听到另一个高频词——具身智能。 所谓具身智能Embodied AI …

IRIS搭建docker

之前把web实现了docker&#xff0c;开发或测试环境可能需要开发自己搭数据库&#xff0c;为了方便使用&#xff0c;把数据库也做一个docker。 由于原生的CentOS我还有改yum仓库&#xff0c;所以这次从之前lis搞的改好yum的镜像开始&#xff08;从改好yum的lisnew的镜像创建lis…

【Linux】Ubuntu基本使用与配置, 以及常见问题汇总(一)

前言 大学期间&#xff0c;感觉很多时候学习课外知识都是被推着往前走&#xff0c;很多内容并没有深入去学习&#xff0c;知识的记录受限于所学比较片面&#xff0c;如今渐渐意识到似乎并没有建立起相关知识的体系架构&#xff0c;缺乏一个系统学习并整理的过程。本文将以Ubunt…

【LangChain】检索器之MultiQueryRetriever

MultiQueryRetriever 概要内容总结 概要 基于距离的向量数据库检索在高维空间中嵌入查询&#xff0c;并根据“距离”查找相似的嵌入文档。 但是&#xff0c;如果查询措辞发生细微变化&#xff0c;或者嵌入不能很好地捕获数据的语义&#xff0c;检索可能会产生不同的结果。有时…

grid map学习笔记1之Ubuntu18.04+ROS-melodic编译安装grid_map栅格地图及示例运行

文章目录 0 引言1 安装依赖和编译1.1 安装依赖1.2 下载编译 2 运行示例2.1 simple_demo2.2 tutorial_demo2.3 iterators_demo2.4 image_to_gridmap_demo2.5 grid_map_to_image_demo2.6 opencv_demo2.7 resolution_change_demo2.8 filters_demo2.9 interpolation_demo 0 引言 苏…

labview 多线程同步

所谓通讯的同步是指多个线程同时进行或严格按照顺序执行&#xff0c;数据的严格性是指发送多少数据接收多少数据&#xff0c;不能出现数据丢失或重复接收的现象。 labview的同步机制有事件发生、集合点、通知器、信号量。 可以这么来记忆&#xff1a;事急&#xff08;集&…

JavaScript |(一)JavaScript简介及基本语法 | 尚硅谷JavaScript基础实战

学习来源&#xff1a;尚硅谷JavaScript基础&实战丨JS入门到精通全套完整版 文章目录 &#x1f4da;JavaScript简介&#x1f407; 实现&#x1f407;JavaScript的特点 &#x1f4da;基本知识&#x1f407;编写位置&#x1f525;方式一&#xff1a;在标签中写&#xff08;不推…

独立游戏《黑夜狩猎者》

做独立游戏已经4个月了&#xff0c;在下作品黑夜狩猎者已经上线TapTap平台。目前正加入薪火计划&#xff0c; 如果你也想加入&#xff0c;下方链接 TapTap 薪火计划

【超全面】Linux嵌入式干货学习系列教程

文章目录 一、前言二、Linux基础篇三、数据结构与算法基础三、Linux应用篇四、Linux网络篇五、ARM篇六、Linux系统移植篇七、Linux驱动篇八、Linux特别篇九、Linux项目篇 一、前言 博主学习Linux也有几个月了&#xff0c;在这里为广大朋友整理出嵌入式linux的学习知识&#xff…

zookeeper-3.7.1集群

1.下载&解压安装包apache-zookeeper-3.7.1-bin.tar.gz 解压到/app/ &改名zookeeper-3.7.1 [rootnode1 app]# tar -zxvf apache-zookeeper-3.7.1-bin.tar.gz -C /app/ [rootnode1 app]# mv apache-zookeeper-3.7.1-bin zookeeper-3.7.1 ---- 删除docs [rootnode1…