STM32_HAL库_外部中断

news2024/11/15 19:50:03

一、设置分组 

stm32f1xx_hal_cortex.c

查看分组

五个形参,分组0~4

stm32f1xx_hal.c

设置了分组为2, 此工程就不需要再设置了

再回到stm32f1xx_hal_cortex.c

查看NVIC_SetPriorityGrouping的定义,若无法跳转,先编译一下,

继续找定义

这段代码是用于设置 NVIC 的优先级分组的内联函数。关键部分:

  • SCB->AIRCR = reg_value;: 最后,将更新后的寄存器值写入 SCB_AIRCR 寄存器,完成对 NVIC 优先级分组的设置。

总的来说,这个函数的目的是安全地设置 NVIC 的优先级分组,确保在进行任何更改之前正确地处理了旧的配置值,并且将写入操作限制在允许的范围内。

二、设置优先级

stm32f1xx_hal_cortex.c

没有返回值,三个形参

这段代码是用于设置特定中断的优先级的函数。

  1. void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority): 这是一个函数声明,用于设置特定中断的优先级。它接受三个参数,分别是中断号 IRQn,抢占优先级 PreemptPriority,以及响应优先级 SubPriority

  2. uint32_t prioritygroup = 0x00U;: 这一行定义了一个变量 prioritygroup 并初始化为 0x00U,该变量用于存储当前 NVIC 的优先级分组。

  3. assert_param(IS_NVIC_SUB_PRIORITY(SubPriority));assert_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority));: 这两行是参数检查,确保传递给函数的 SubPriorityPreemptPriority 在有效范围内。如果参数不在有效范围内,这些断言将会触发。

  4. prioritygroup = NVIC_GetPriorityGrouping();: 这一行调用了 NVIC_GetPriorityGrouping() 函数,获取当前 NVIC 的优先级分组。

  5. NVIC_SetPriority(IRQn, NVIC_EncodePriority(prioritygroup, PreemptPriority, SubPriority));: 这一行调用了 NVIC_SetPriority() 函数,设置指定中断的优先级。它使用了 NVIC_EncodePriority() 函数将抢占优先级和子优先级编码为一个优先级值,并将其传递给 NVIC_SetPriority() 函数来设置中断的优先级。

这个函数的目的是设置特定中断的优先级,确保传递给函数的优先级参数在有效范围内,并将优先级值编码后传递给 NVIC。

查看IRQn_Type定义

跳转到stm32f103xe.h

举个例子

RTC_IRQn

中断号是3

NVIC_SetPriority

看定义 

跳转到这里,再去看定义

 跳转到:

用于设置特定中断的优先级的内联函数。每个部分的作用:

  1. __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority): 这是一个内联函数的声明,用于设置特定中断的优先级。它接受两个参数,一个是中断号 IRQn,另一个是优先级 priority

  2. if ((int32_t)(IRQn) >= 0): 这个条件语句检查中断号是否为非负值,如果是非负值,则说明是可编程中断,需要设置 NVIC->IP 寄存器的相应位置;如果是负值,则说明是固定优先级中断,需要设置 SCB->SHP 寄存器的相应位置。

  3. NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);: 如果是可编程中断,就将优先级值左移以便正确放置到 NVIC->IP 寄存器相应位置。这里通过移位来确保优先级值的正确性,同时保留了 __NVIC_PRIO_BITS 指定的位数,这是由硬件定义的。

  4. SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);: 如果是固定优先级中断,则将优先级值左移并设置到 SCB->SHP 寄存器的相应位置。由于固定优先级中断的索引不是从零开始的,因此需要进行一些偏移和掩码操作。

这个函数的目的是根据中断类型设置对应中断的优先级,确保优先级值在正确的范围内,并将其正确地写入到相应的寄存器中。

stm32f1xx_hal_cortex.c对cortex_cm3.h文件里的函数进行了封装

这段代码是一个内联函数,用于检查特定中断是否已经被使能。让我们逐步解释每个部分的作用:

  1. __STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn): 这是一个内联函数的声明,用于获取特定中断是否已经被使能。它接受一个参数,即中断号 IRQn

  2. if ((int32_t)(IRQn) >= 0): 这个条件语句检查中断号是否为非负值,如果是非负值,则说明是可编程中断,需要检查 NVIC->ISER 寄存器的相应位;如果是负值,则说明是固定优先级中断,这些中断无法被使能,直接返回 0。

  3. return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));: 如果是可编程中断,则检查 NVIC->ISER 寄存器中相应位是否被置位,如果被置位则返回 1,否则返回 0。这里通过对中断号进行移位和掩码操作来确定具体的位位置。

  4. return(0U);: 如果是固定优先级中断,则直接返回 0,表示该中断无法被使能。

这个函数的目的是根据中断类型检查特定中断是否已经被使能,并返回相应的结果。

三、EXTI

p60

P61

两种中断

四、GPIO外部中断

复制跑马灯实验,BSP新建EXTI文件夹,keil5中新建exti.c与exti.h并添加到EXTI文件夹,添加到工程里

复制拿过来用

 若无法跳转定义,参考这份博客

http://t.csdnimg.cn/RCJyL

重新编译程序

再次执行Go To Definition of ''的操作,可以了

参考

需选用外部中断下降沿触发,且输入上拉

#define  GPIO_MODE_IT_RISING                    0x10110000u   /*!< External Interrupt Mode with Rising edge trigger detection          */
#define  GPIO_MODE_IT_FALLING                   0x10210000u   /*!< External Interrupt Mode with Falling edge trigger detection         */
#define  GPIO_MODE_IT_RISING_FALLING            0x10310000u   /*!< External Interrupt Mode with Rising/Falling edge trigger detection  */

#define  GPIO_MODE_EVT_RISING                   0x10120000u   /*!< External Event Mode with Rising edge trigger detection               */
#define  GPIO_MODE_EVT_FALLING                  0x10220000u   /*!< External Event Mode with Falling edge trigger detection              */
#define  GPIO_MODE_EVT_RISING_FALLING           0x10320000u   /*!< External Event Mode with Rising/Falling edge trigger detection       */

这些宏定义了用于 GPIO(通用输入/输出)引脚的不同模式,用于处理外部中断和事件,根据触发边沿的不同来触发。具体而言:

  • GPIO_MODE_IT_RISING:表示外部中断模式,检测上升沿触发。
  • GPIO_MODE_IT_FALLING:表示外部中断模式,检测下降沿触发。
  • GPIO_MODE_IT_RISING_FALLING:表示外部中断模式,同时检测上升沿和下降沿触发。

类似地:

  • GPIO_MODE_EVT_RISING:表示外部事件模式,检测上升沿触发。
  • GPIO_MODE_EVT_FALLING:表示外部事件模式,检测下降沿触发。
  • GPIO_MODE_EVT_RISING_FALLING:表示外部事件模式,同时检测上升沿和下降沿触发。

这些宏通常与 GPIO 配置函数一起使用,以设置 GPIO 引脚的所需模式,以便根据特定边沿触发来处理外部中断或事件。

上下拉配置

#define  GPIO_NOPULL        0x00000000u   /*!< No Pull-up or Pull-down activation  */
#define  GPIO_PULLUP        0x00000001u   /*!< Pull-up activation                  */
#define  GPIO_PULLDOWN      0x00000002u   /*!< Pull-down activation                */

这些宏定义了用于 GPIO 引脚的不同上拉和下拉配置选项。具体来说:

  • GPIO_NOPULL:表示不启用上拉或下拉。
  • GPIO_PULLUP:表示启用上拉。
  • GPIO_PULLDOWN:表示启用下拉。

这些选项通常用于配置 GPIO 引脚的电气特性,以确保引脚在特定条件下的正确操作,如减少干扰、提高信号质量等。

选择输入上拉

中断优先级:HAL_NVIC_SetPriority()

go to definition

选择中断号

笔者选用的是B1,选择EXTI1_IRQn

设置抢断优先级与响应优先级

笔者设置的是2和0

使能中断:HAL_NVIC_EnableIRQ()

笔者的是EXTI1_IRQn

设计中断服务函数:

去到配置文件查找

选择EXTI1_IRQHandler

 

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  /* EXTI line interrupt detected */
  if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
  }
}

这段代码是一个 HAL(Hardware Abstraction Layer,硬件抽象层)的 GPIO(通用输入/输出)外部中断处理函数。让我来解释它:

  • HAL_GPIO_EXTI_IRQHandler 是一个函数,用于处理外部中断事件。它接收一个参数 GPIO_Pin,表示触发了外部中断的 GPIO 引脚。

  • 在函数内部,首先检测是否检测到了 EXTI(外部中断)线的中断事件。

  • 如果 GPIO_Pin 对应的 EXTI 中断事件标志被置位(不为 0),则说明该 GPIO 引脚触发了外部中断。

  • 接着,通过 __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin) 清除相应的中断标志。

  • 最后,调用 HAL_GPIO_EXTI_Callback(GPIO_Pin),这是一个回调函数,用于在外部中断触发时执行用户定义的操作。这个函数的实现应该由用户在程序的其他地方提供。

用于在外部中断事件发生时执行相应的操作,如清除中断标志并调用用户定义的回调函数。

回调函数

__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(GPIO_Pin);
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_GPIO_EXTI_Callback could be implemented in the user file
   */
}

用于处理 GPIO 外部中断回调的弱定义函数 HAL_GPIO_EXTI_Callback

  • __weak 关键字表示这是一个弱定义的函数,它可以被用户在程序的其他地方重新定义以满足特定需求。

  • 这个函数的目的是处理 GPIO 外部中断事件。它接收一个参数 GPIO_Pin,表示触发了外部中断的 GPIO 引脚。

  • 函数内部通过调用 UNUSED(GPIO_Pin) 来避免编译器产生未使用参数的警告。这是因为在某些情况下,用户可能不需要使用该参数。

  • 注释部分指出,如果需要在外部中断发生时执行特定的操作,用户应该在自己的代码文件中实现 HAL_GPIO_EXTI_Callback 函数,并在其中编写所需的处理逻辑。

这个函数提供了一个默认的外部中断处理回调函数,并允许用户根据需要进行修改或扩展。

中断信号到来,去翻转led引脚的信号,在led.h中查看引脚是B5

4.1使能GPIO时钟

__HAL_RCC_GPIOB_CLK_ENABLE();

4.2 HAL_GPIO_init

	GPIO_InitTypeDef gpio_init_struct;
	__HAL_RCC_GPIOB_CLK_ENABLE();

    gpio_init_struct.Pin = LED0_GPI1_PIN;                   /* 引脚B1 */
    gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;            /* 推挽输出 */
    gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* 高速 */
    HAL_GPIO_Init(GPIOB, &gpio_init_struct);       /* 初始化 */
		

4.3 设置中断分组

配置文件已设置分组为2 

4.4 设置中断优先级

HAL_NVIC_SetPriority(EXTI1_IRQn,2,0);

4.5 使能中断

HAL_NVIC_EnableIRQ(EXTI1_IRQn);

4.6 设计中断服务函数

void EXTI1_IRQHandler(void)
{
	HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);

}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	delay_ms(20);
	if(GPIO_Pin=GPIO_Pin_1)
	{
		if(HAL_GPIO_ReadPin(GPIOB,GPIO_Pin_1) ==0)
		{
			HAL_GPIO_TogglePin(GPIOB,GPIO_Pin_5);
		
		}
	}

}

exti.h

函数声明

void exti_init(void);

EXTI1_IRQHandler与HAL_GPIO_EXTI_Callback已经在配置文件里声明过

startup_stm32f103xe.s

stm32f1xx_hal_gpio.h

五、源码

exti.h

#ifndef _EXTI_H
#define _EXTI_H
#include "./SYSTEM/sys/sys.h"


void exti_init(void);



#endif

exit.c

#include "./BSP/EXTI/exti.h"


void exti_init(void)
{

	GPIO_InitTypeDef gpio_init_struct;
	__HAL_RCC_GPIOB_CLK_ENABLE();

    gpio_init_struct.Pin = GPIO_PIN_1;                   /* 引脚B1 */
    gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;            /* 推挽输出 */
    gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* 高速 */
    HAL_GPIO_Init(GPIOB, &gpio_init_struct);       /* 初始化 */
		

	HAL_NVIC_SetPriority(EXTI1_IRQn,2,0);
	HAL_NVIC_EnableIRQ(EXTI1_IRQn);
}

void EXTI1_IRQHandler(void)
{
	HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);

}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	delay_ms(20);
	if(GPIO_Pin == GPIO_PIN_1)
	{
		if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) ==0)
		{
			HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);
		
		}
	
	}

}

main.c


#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/EXTI/exti.h"


int main(void)
{
    HAL_Init();                                 /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟,72M */
    delay_init(72);                             /* 初始化延时函数 */
    led_init();                                 /* 初始化LED */
    exti_init();
	
	
    while(1)
    {
		HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);
		delay_ms(5000);
		
    }
}

参考

【【正点原子】手把手教你学STM32 HAL库开发全集【真人出镜】STM32入门教学视频教程 单片机 嵌入式】https://www.bilibili.com/video/BV1bv4y1R7dp?p=56&vd_source=be33b1553b08cc7b94afdd6c8a50dc5a

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

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

相关文章

【数据结构】穿梭在二叉树的时间隧道:顺序存储的实现

专栏引入 哈喽大家好&#xff0c;我是野生的编程萌新&#xff0c;首先感谢大家的观看。数据结构的学习者大多有这样的想法&#xff1a;数据结构很重要&#xff0c;一定要学好&#xff0c;但数据结构比较抽象&#xff0c;有些算法理解起来很困难&#xff0c;学的很累。我想让大家…

Apple开发者应用商店(AppStore)描述文件及ADHOC描述文件生成

创建AD HOC描述文件 1.选中Profiles,然后点击加号创建 2.创建已注册设备可安装描述文件 3.选择要注册的id 4.选择证书 5.选择设备 6.输入文件名,点击生成 7.生成成功,点击下载

重新ysyx

一、克隆仓库 1.创建ssh key ssh-keygen -t rsa cd ~/.ssh ls 查看里面是否有id_rsa id_rsa.pub ssh-keygen -t rsa -C "xiantong15834753336outlook.com" cat id_rsa.pub***********查看里面的内容&#xff0c;复制到下图中绿色的按钮 git init ssh -T g…

Alsa UCM

Alsa Use Case Manager&#xff08;用例管理器&#xff09;描述如何为某些用例&#xff08;如 “播放音频”、“通话”&#xff09;设置 mixer 混频器。它还描述如何修改 mixer 混频器状态以将音频路由到某些输出和输入&#xff0c;以及如何控制这些设备。 这基本上涵盖了 Pul…

胶南代理记账,为您提供专业、便捷的会计服务

欢迎来到胶南代理记账服务站&#xff0c;这里我们专注于为企业提供专业的会计服务&#xff0c;无论您是初创企业还是已经在业界有一定规模的企业&#xff0c;我们都将以最专业的态度和最高效的服务为您量身定制合适的记账方案。 我们的目标不仅是帮助您完成财务报告的制作&…

奥威BI零售数据分析方案的优缺点一览

奥威BI零售数据分析方案是一套基于BI大数据智能可视化分析系统&#xff0c;根据零售企业数据分析共性需求、业务特殊性量身打造&#xff0c;点击下载应用&#xff0c;立即将零售数据情况分析清楚&#xff0c;直观呈现。很多企业都是直接在该零售数据分析方案的基础上实现了智能…

Windows系统中好用的闪迪U盘修复工具

本文向你介绍了一款简单好用的闪迪U盘修复工具&#xff0c;它可以帮助你轻松修复闪迪U盘的各种问题。该工具操作简单&#xff0c;能帮用户节省大量的时间和精力。 闪迪U盘损坏可以修复吗&#xff1f; “我有一只32GB的闪迪U盘出现了问题&#xff0c;可能是因为我在关机前将它强…

【CS.CN】深入解析HTTP中的Expect: 100-continue头:性能优化的利器还是鸡肋?

目录 0 序言 0.1 由来0.2 使用场景0.3 现在还需要吗&#xff1f; 1 Expect: 100-continue的机制2 语法 && 通过重新设置空的Expect头优化性能3 实例分析&#xff1a;长连接中的Expect问题解决4 总结 0 序言 0.1 由来 Expect: 100-continue头部字段最早在HTTP/1.1规…

国产操作系统上给麒麟虚拟机安装virtualbox增强工具 _ 统信 _ 麒麟 _ 中科方德

原文链接&#xff1a;国产操作系统上给麒麟虚拟机安装virtualbox增强工具 | 统信 | 麒麟 | 中科方德 Hello&#xff0c;大家好啊&#xff01;昨天给大家带来了一篇在国产操作系统上给VirtualBox中的Win7虚拟机安装增强工具的文章&#xff0c;今天我们将继续深入&#xff0c;介绍…

Interview preparation--RabbitMQ

AMQP AMQP(Advanced Message Queueing protocol). 高级消息队列协议&#xff0c;是进程之间床底一步新消息的网络协议AMQP工作原理如下&#xff1a; 发布者&#xff08;Publisher&#xff09;发布消息&#xff08;Message&#xff09;经过交换机&#xff08;Exchange&#xff…

【Python】认识 Python

一、计算机基础概念 1、什么是计算机 很多老一辈的人&#xff0c;管下面这个叫做计算机。然而&#xff0c;它只是 “计算器”&#xff0c;和计算机是有很大区别的。 现在我们所说的计算机&#xff0c;不光能进行算术运算&#xff0c;还能进行逻辑判断、数据存储、网络通信等…

uniapp原生插件开发实战——集成Android端的Twitter登陆

Android集成Twitter登陆的官方教程:https://github.com/twitter-archive/twitter-kit-android/wiki 项目创建 首先可以先看下uniapp原生插件开发教程 uniapp原生插件类型分为两种: Module模式:能力扩展,无嵌入窗体的UI控件,类似于功能插件。Component模式:在窗体中内嵌…

websocket php workerman 服务器nginx配置wss协议

首先 Nginx的版本要高&#xff0c;尽量用当前最新稳定版本。 其次 WSS协议&#xff0c;是在HTTPS协议的基础上&#xff0c;进行协议升级&#xff0c;进行通讯的&#xff0c;所以先要保证你有一个 HTTPS正常的WEB站点。 所以&#xff0c;通过Nginx -V 请保证 一定有 --with-ht…

监控摄像机接入GB28181平台如何获取监控视频

各种型号监控摄像头或硬盘录像机接入 GB28181平台配置过程非常简单明了&#xff0c;但有些细节需要注意&#xff0c;避免走弯路。 1、基本要求 &#xff08;1&#xff09;网络要求 总的来说&#xff0c;只要监控设备和GB28181平台的网络是连通的&#xff0c;设备可以主动访问…

Linux 35.5 + JetPack v5.1.3@FC-Planner编译安装

Linux 35.5 JetPack v5.1.3FC-Planner编译安装 1. 源由2. 编译&安装Step 1&#xff1a;依赖库安装Step 2&#xff1a;克隆工程Step 3&#xff1a;编译工程Step 4&#xff1a;LKH编译Step 5&#xff1a;安装工程 3. 问题汇总3.1 Killed signal terminated program cc1plus3…

跟着小白学linux的基础命令

小白学习记录&#xff1a; 前情提要&#xff1a;Linux命令基础格式!查看 lsLinux 的7种文件类型及各颜色代表含义 进入指定目录 cd查看当前工作目录 pwd创建一个新的目录(文件夹&#xff09; mkdir创建文件 touch查看文件内容 cat、more操作文件、文件夹- 复制 cp- 移动 mv- 删…

Vxe UI vxe-form 实现折叠表单,当表单很多时实现自动收起与展开

Vxe UI vue vxe-form 实现折叠表单&#xff0c;当表单很多时实现自动收起与展开 代码 folding 用于将当前表单项设置为默认隐藏 collapse-node 设置折叠按钮&#xff0c;加上之后会自动在该表单项的右侧显示一个折叠按钮 <template><div><vxe-formtitle-colo…

windows 系统通过 cmd 命令终止进程

windows 系统通过 cmd 命令终止进程 1、使用 netstat 命令查看特定端口的占用情况 例如&#xff0c;要查看端口号为 8015 的情况&#xff0c;可以执行以下命令&#xff1a; netstat -ano | findstr 8105此命令会显示所有占用端口 8105 的网络连接&#xff0c;并列出 PID&…

24.Labview移位寄存器的使用及数据流解析

本文讲解移位寄存器的常用场景及其数据流的方向解析。 在Labview中移位寄存器是存在于循环结构中的&#xff0c;也就是说for循环和while循环中&#xff0c;在了解移位寄存器之前首先要了解一下for循环和while循环的原理及其数据流的流动方向&#xff0c;题主之前讲过for循环的文…

Redis的事务与关系型数据库事务有何不同?

引言&#xff1a;关于 Redis 的事务很多人可能都是一知半解&#xff0c;大多数人只了解数据库的事务&#xff0c;并且是单体事务&#xff0c;对于 Redis 事务和常见关系型数据库的事务的区别还没有去了解过&#xff0c;本文就来详细进行介绍。 题目 Redis的事务与关系型数据库…