STM32F103_LL库+寄存器学习笔记05 - GPIO输入模式,捕获上升沿进入中断回调

导言


GPIO设置输入模式后,一般会用轮询的方式去查看GPIO的电平状态。比如,最常用的案例是用于检测按钮的当前状态(是按下还是没按下)。中断的使用一般用于计算脉冲的频率与计算脉冲的数量。

项目地址:https://github.com/q164129345/MCU_Develop/tree/main/stm32f103_ll_library05_gpio_input_interrupt

一、代码(LL库)


1.1、main.c

在这里插入图片描述
如上所示,函数EXTI_Configure()完成PB4的上升沿触发中断的设置。
在这里插入图片描述
如上所示,一定要在GPIO设置完输入模式后,才能设置中断。

1.2、stm32f1xx_it.c

在这里插入图片描述
如上所示,编写EXTI4中断回调函数EXTI4_IRQHandler()的内容,在函数EXTI4_IRQHandler()里一定要清除中断标志,否则下一次中断将不会被执行。
为什么EXTI4的中断函数的名字是EXTI4_IRQHandler()? 在启动文件startup_stm32f103xb.s的中断向量表里有定义,当发现EXTI4中断时,调用函数EXTI4_IRQHandler()。如下所示:
在这里插入图片描述
回到EXTI4中断回调函数EXTI4_IRQHandler(),既然EXTI4捕获到中断时,会调用函数EXTI4_IRQHandler()。但是,为什么EXTI4_IRQHandler()里需要用if (LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_4) != RESET)再一次确认是EXTI4的中断标志位?
我认为主要有两个原因:

  1. 规范中断回调函数的一致性(都要再一次通过中断标志位确认)
    • 在 STM32 中,并非所有 EXTI 线路都有独立的中断处理函数。例如,EXTI5 到 EXTI9 共享一个处理函数 EXTI9_5_IRQHandler(),在这种情况下,必须通过检查标志位来判断具体是哪条线路触发了中断。所以,不管是EXTI1(有独立的中断回调函数EXTI41_IRQHandler)还是EXTI9都要在中断回调函数里再一次检查中断标志位。
  2. 确保中断源的准确性
    • 尽管 EXTI4_IRQHandler() 通常只由 EXTI4 触发,但在某些异常情况下(例如软件配置错误、中断控制器异常等),其他因素可能导致误触发。检查 LL_EXTI_LINE_4 的标志位可以确认中断确实是由 EXTI4 引发的,从而避免执行错误的处理逻辑。这种额外的验证提高了代码的健壮性。
      在这里插入图片描述

二、寄存器的梳理


2.1、中断向量表

《STM32F1参考手册》的章节9.1.2-中断与异常向量看到,EXTI中断一共有如下:
在这里插入图片描述
在这里插入图片描述
如上所示,只有EXTI1~4有单独的中断地址,EXTI5~EXTI9共享一个中断地址,EXTI10~EXTI15共享一个中断地址。所以,弄明白中断回调函数EXTI4_IRQHandler()里为什么再一次使用代码if (LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_4) != RESET)去判断中断标志位了。从中断向量表里看到,EXTI5~EXTI9确认共享一个中断地址(函数指针)。

2.2、为什么PB4的中断对应EXTI4?

在这里插入图片描述
如上所示,根据《STM32F1参考手册》的章节9.2.5看到GPIO跟EXTI中断线的对应关系,PB4对应EXTI4。

2.3、外部中断配置寄存器x (AFIO_EXTICRx)

在这里插入图片描述
在这里插入图片描述
如上所示,《STM32F1参考手册》的章节8.4.4,寄存器AFIO_EXTICR2的段EXTI4 = 0001时,相当于将PB4映射到EXTI4。

MODIFY_REG(AFIO->EXTICR[1], 0xF << 0UL, 0x01 << 0UL); // 配置EXTI4线路映射到PB4引脚

2.4、上升沿触发选择寄存器(EXTI_RTSR)

在这里插入图片描述
寄存器EXTI_PTSR的作用设置上升沿是否触发EXTI线中断。比如,位TR4 = 1相当于EXTI4启动上升沿触发中断。

EXTI->RTSR |= 0x01UL << 4UL;  // EXTI4开启上升沿触发中断
EXTI->RTSR |= 0x01UL << 10UL; // EXTI10开启上升沿触发中断EXTI->RTSR &= ~(0x01UL << 4UL);  // EXTI4关闭上升沿触发中断
EXTI->RTSR &= ~(0x01UL << 10UL); // EXTI10关闭上升沿触发中断

2.5、下降沿触发选择寄存器(EXTI_FTSR)

在这里插入图片描述
寄存器EXTI_FTSR的作用设置下降沿是否触发EXTI线中断。比如,为TR4 = 1相当于EXTI4启动下降沿触发中断。

EXTI->FTSR |= 0x01UL << 4UL; // 开启EXTI4下降沿中断
EXTI->FTSR &= ~(0x01UL << 4UL); // 关闭EXTI4下降沿中断

2.6、挂起寄存器(EXTI_PR)

在这里插入图片描述
当寄存器EXTI_PR的位PR4置1时,代表触发EXTI4中断。 往里写‘1’可以清除它。

if (EXTI->PR & (0x01UL << 4UL)) { // 判断是不是EXTI4中断EXTI->PR |= 0x01UL << 4UL; // 清除EXTI4的中断标志
}if (EXTI->PR & (0x01UL << 10UL)) { 判断是不是EXTI10中断EXTI->PR |= 0x01 << 10UL; // 清除EXTI10的中断标志
}

三、代码(寄存器方式)


3.1、main.c

在这里插入图片描述
如上所示,使用寄存器方式真的简洁。

3.2、stm32f1xx_it.c

在这里插入图片描述
如上所示,通过寄存器EXTI_PR的bit4判断是否是EXTI4中断。然后往bit4写入‘1’就能清除中断标志。
在这里插入图片描述
如上所示,在debug模式看到,当PB4从低电平->高电平时,进入中断回调函数EXTI4_IRQHandler(),且寄存器EXTI_PR的bit4被置1。

四、细节补充


4.1、EXTI4支持同时检测PB4与PA4吗??

在这里插入图片描述
根据《STM32F1参考手册》的章节9.2.5,根据PA0~PG0映射到EXTI0上,所以PA4~PG4是映射到EXTI4上。有一个疑问,STM32F1支持PA4、PB4一起映射到EXTI4上吗??抱着这个疑问,我尝试用CubeMX试试,看看ST官方工具允许不允许这样做。
在这里插入图片描述
如上图所示,CubeMX不支持PA4与PB4一起映射到EXTI4。PA4映射到EXTI4后,如果将PAB4映射到EXTI4的话,PA4就会自动失效。所以,每一个EXTIx只能映射某一个PAx。

4.2、STM32F103一共支持多少路EXTI中断?

在这里插入图片描述
如上所示,参考《STM32F1参考手册》的章节9.2.5,在STM32F103引脚资源足够的情况下,最多支持16个GPIO口映射到EXTI外部中断(EXTI0~EXTI15)。 另外EXTI16~EXTI19不能映射到普通GPIO,只能用于处理特定内部事件或外设的中断/事件,比如EXTI18的USB唤醒事件。

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

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

相关文章

【C++进阶二】string的模拟实现

【C进阶二】string的模拟实现 1.构造函数和C_strC_str: 2.operator[]3.拷贝构造3.1浅拷贝3.2深拷贝 4.赋值5.迭代器6.比较ascll码值的大小7.reverse扩容8.push_back尾插和append尾插9.10.insert10.1在pos位置前插入字符ch10.2在pos位置前插入字符串str 11.resize12.erase12.1从…

wokwi arduino mega 2560 - 点亮LED案例

截图&#xff1a; 点亮LED案例仿真截图 代码&#xff1a; unsigned long t[20]; // 定义一个数组t&#xff0c;用于存储20个LED的上次状态切换时间&#xff08;单位&#xff1a;毫秒&#xff09;void setup() {pinMode(13, OUTPUT); // 将引脚13设置为输出模式&#xff08;此…

vue3项目使用 python +flask 打包成桌面应用

server.py import os import sys from flask import Flask, send_from_directory# 获取静态文件路径 if getattr(sys, "frozen", False):# 如果是打包后的可执行文件base_dir sys._MEIPASS else:# 如果是开发环境base_dir os.path.dirname(os.path.abspath(__file…

后端学习day1-Spring(八股)--还剩9个没看

一、Spring 1.请你说说Spring的核心是什么 参考答案 Spring框架包含众多模块&#xff0c;如Core、Testing、Data Access、Web Servlet等&#xff0c;其中Core是整个Spring框架的核心模块。Core模块提供了IoC容器、AOP功能、数据绑定、类型转换等一系列的基础功能&#xff0c;…

LeetCode 第34、35题

LeetCode 第34题&#xff1a;在排序数组中查找元素的第一个和最后一个位置 题目描述 给你一个按照非递减顺序排列的整数数组nums&#xff0c;和一个目标值target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值target&#xff0c;返回[-1,1]。你必须…

告别分库分表,时序数据库 TDengine 解锁燃气监控新可能

达成效果&#xff1a; 从 MySQL 迁移至 TDengine 后&#xff0c;设备数据自动分片&#xff0c;运维更简单。 列式存储可减少 50% 的存储占用&#xff0c;单服务器即可支撑全量业务。 毫秒级漏气报警响应时间控制在 500ms 以内&#xff0c;提升应急管理效率。 新架构支持未来…

第十四届蓝桥杯真题

一.LED 先配置LED的八个引脚为GPIO_OutPut,锁存器PD2也是,然后都设置为起始高电平,生成代码时还要去解决引脚冲突问题 二.按键 按键配置,由原理图按键所对引脚要GPIO_Input 生成代码,在文件夹中添加code文件夹,code中添加fun.c、fun.h、headfile.h文件,去资源包中把lc…

《基于机器学习发电数据电量预测》开题报告

个人主页&#xff1a;大数据蟒行探索者 目录 一、选题背景、研究意义及文献综述 &#xff08;一&#xff09;选题背景 &#xff08;二&#xff09;选题意义 &#xff08;三&#xff09;文献综述 1. 国内外研究现状 2. 未来方向展望 二、研究的基本内容&#xff0c;拟解…

UWP程序用多页面实现应用实例多开

Windows 10 IoT ARM64平台下&#xff0c;UWP应用和MFC程序不一样&#xff0c;同时只能打开一个应用实例。以串口程序为例&#xff0c;如果用户希望同时打开多个应用实例&#xff0c;一个应用实例打开串口1&#xff0c;一个应用实例打开串口2&#xff0c;那么我们可以加载多个页…

Springboot整合Netty简单实现1对1聊天(vx小程序服务端)

本文功能实现较为简陋&#xff0c;demo内容仅供参考&#xff0c;有不足之处还请指正。 背景 一个小项目&#xff0c;用于微信小程序的服务端&#xff0c;需要实现小程序端可以和他人1对1聊天 实现功能 Websocket、心跳检测、消息持久化、离线消息存储 Netty配置类 /*** au…

GitLab 中文版17.10正式发布,27项重点功能解读【二】

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料&#xff1a; 极狐GitLab 官网极狐…

好消息!软航文档控件(NTKO WebOffice)在Chrome 133版本上提示扩展已停用的解决方案

软航文档控件现有版本依赖Manifest V2扩展技术支持才能正常运行&#xff0c;然而这个扩展技术到2025年6月在Chrome高版本上就彻底不支持了&#xff0c;现在Chrome 133开始的版本已经开始弹出警告&#xff0c;必须手工开启扩展支持才能正常运行。那么如何解决这个技术难题呢&…

字典树与01trie

字典树简介 当我们通过字典查一个字或单词的时候&#xff0c;我们会通过前缀或关键字的来快速定位一个字的位置&#xff0c;进行快速查找。 字典树就是类似字典中索引表的一种数据结构&#xff0c;能够帮助我们快速定位一个字符串的位置。 字典树是一种存储字符串的数据结构…

二十五、实战开发 uni-app x 项目(仿京东)- 前后端轮播图

定义了一个名为 Swiper 的Java类,用于表示一个轮播图实体。它使用了 Jakarta Persistence API (JPA) 来映射数据库表,并使用了 Lombok 库来简化代码。以下是对代码的详细讲解: 1. 包声明 package com.jd.jdmall.model; 这行代码声明了该类所在的包路径为 com.jd.jdmall.mode…

游戏摇杆开发:利用 Windows API 实现摇杆输入捕获

在现代游戏开发中&#xff0c;游戏摇杆&#xff08;Joystick&#xff09;作为一种重要的输入设备&#xff0c;能够为玩家提供更加沉浸式的游戏体验。Windows 操作系统提供了一系列 API 函数&#xff0c;允许开发者轻松地捕获和处理游戏摇杆的输入。本文将介绍如何使用 Windows …

Ceph集群2025(Squid版)快速对接K8S cephFS文件存储

ceph的块存储太简单了。所以不做演示 查看集群 创建一个 CephFS 文件系统 # ceph fs volume create cephfs01 需要创建一个子卷# ceph fs subvolume create cephfs01 my-subvol -----------------#以下全部自动创建好 # ceph fs ls name: cephfs01, metadata pool: c…

Python中数据结构元组详解

在Python中&#xff0c;元组&#xff08;Tuple&#xff09;是一种不可变的序列类型&#xff0c;常用于存储一组有序的数据。与列表&#xff08;List&#xff09;不同&#xff0c;元组一旦创建&#xff0c;其内容无法修改。本文将详细介绍元组的基本操作、常见运算、内置函数以及…

游戏引擎学习第183天

回顾和今天的计划 我对接下来的进展感到非常兴奋。虽然我们可能会遇到一些问题&#xff0c;但昨天我们差不多完成了将所有内容迁移到新的日志系统的工作&#xff0c;我们正在把一些内容整合进来&#xff0c;甚至是之前通过不同方式记录时间戳的旧平台层部分&#xff0c;现在也…

Spring 如何处理循环依赖

在 Spring 框架里&#xff0c;循环依赖指的是多个 Bean 之间相互依赖&#xff0c;从而形成一个闭环。例如&#xff0c;Bean A 依赖 Bean B&#xff0c;而 Bean B 又依赖 Bean A。Spring 主要通过三级缓存机制来处理循环依赖&#xff0c;下面详细介绍相关内容。 1. 三级缓存的定…

Android开发layer-list

Android开发layer-list 它的用处可以在drawable上进行多图拼接&#xff0c;比如启动页&#xff0c;不想图片被拉伸就这么做。还有做某些线突出来。 示例代码&#xff1a; <?xml version"1.0" encoding"utf-8"?> <layer-list xmlns:android&q…