STM32 寄存器操作 GPIO 与下降沿中断

 一、如何使用stm32寄存器点灯?

1.1 寄存器映射表

寄存器本质就是一个开关,当我们把芯片寄存器配置指定的状态时即可使用芯片的硬件能力。

寄存器映射表则是开关的地址说明。对于我们希望点亮 GPIO_B 的一个灯来说,需要关注以下的两个寄存器:

 

1.2 配置时钟

对于我们实现希望点亮一个灯的需求来说,不仅需要配置配置 GPIO_B 的时钟,首先需要配置 GPIO_B 的时钟。

为什么需要先配置时钟呢?

STM32 外设通常都是给了时钟后才能设置它的寄存器(即才能使用这个外设)。STM32、LPC1XXX 等等都是这样,这么做的目的是为了省电,使用了所谓时钟门控的技术。寄存器是基于触发器的,触发器的赋值是一定需要时钟的,而寄存器的时钟是由总线时钟提供的,就是说没有总线时钟的话,你给寄存器值它是不会读入的。

对于下图中的系统框图来看,GPIO_B 挂载在 AHB 总线下 APB2 时钟。所以我们需要开启 APB2 的总线时钟。

STM32F10xxx 参考手册 6.3.7 告诉我们怎么使能 GPIO_B 的时钟。

由 1.1 的寄存器映射表图片来看,寄存器映射表可知

0x40000000(片上外设基地址) + 0x20000(AHB总线基地址) + 0x1000 (RCC外设基地址)

最后我们再加上 RCC_APBENR 的地址 0x18 即可成功访问这个寄存器。

对这个寄存器使用左移三位进行置位 IOPB 操作,这样就成功开启了 GPIO_B 时钟。

int main(void)
{//片上外设基地址+AHB总线基地址+RCC外设基地址+RCC的AHB1时钟使能寄存器地址*(unsigned int*)(0x40000000+0x20000+0x1000+0x18) |= ((1)<<3);while(1);
}// 函数为空,目的是为了骗过编译器不报错
void SystemInit(void)
{}

 值得注意的是这种写法,相当于向地址 0XFF 写入 0XFE。

*(unsigned int*)0xFE = 0XFF;
//等价于
unsigned int *p = 0xFE;    //无符号 uint32_t 指针类型指向 0XFE 这个地址
*p = 0xFF;                 //解地址符 向这个地址写入0XFF

1.3 配置 GPIOB_0 模式

根据芯片手册提示 如果我们需要把 GPIOB_0 配置为输出高电平,只需要将 GPIO_CRL 第四位寄存器配置成 0001 即可,这代表了通用开漏输出模式,最大输出10MHz。

//片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOB_CRL地址
*(unsigned int*)(0x40000000+0x10000+0x0C00+0x00) &= ~( (0xFF)<<(4*0) );    //低四位清零
*(unsigned int*)(0x40000000+0x10000+0x0C00+0x00) |=  ( (1) << (4*0) );    //第四位搞成0001

 1.4 配置 GPIOB_0 使其输出低电平

//片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOx_ODR地址
*(unsigned int*)(0x40000000+0x10000+0x0C00+0x0C) &= ~(1<<0);

经过以上我们配置了 RCC_APB2ENR、GPIOB_CRL、GPIOB_ODR寄存器后。GPIOB_0 被配置成了开漏输出低电平。这样就可以点亮我们的灯泡了。

 全部代码如下:

#include "stm32f10x.h"int main(void)
{//片上外设基地址+AHB总线基地址+RCC外设基地址+RCC的AHB1时钟使能寄存器地址*(unsigned int*)(0x40000000+0x20000+0x1000+0x18) |= ((1)<<3);//片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOB_CRL地址*(unsigned int*)(0x40000000+0x10000+0x0C00+0x00) &= ~( (0xFF)<<(4*0) );*(unsigned int*)(0x40000000+0x10000+0x0C00+0x00) |=  ( (1) << (4*0) );//片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOx_ODR地址*(unsigned int*)(0x40000000+0x10000+0x0C00+0x0C) &= ~(1<<0);while(1);
}// 函数为空,目的是为了骗过编译器不报错
void SystemInit(void)
{}

二、配置输入模式

 

 我们希望将 GPIOA_0 配置成浮空输入,根据上表来配置寄存器。

/* PA0 key1引脚 */
//片上外设基地址+AHB总线基地址+RCC外设基地址+RCC的AHB1时钟使能PA寄存器地址
*(unsigned int*)(0x40000000+0x20000+0x1000+0x18) |= ((1)<<2);//片上外设基地址+APB2总线基地址+GPIOA外设基地址+GPIOA_CRL地址
*(unsigned int*)(0x40000000+0x10000+0x0800+0x00) &= ~( (0xFF) << (4*0) );
*(unsigned int*)(0x40000000+0x10000+0x0800+0x00) |=  ( (0X04) << (4*0) );

在最后一行,我们将GPIOA_CRL 寄存器低四位配置成 0100 是浮空输入。

全部代码如下:

#include "stm32f10x.h"int main(void)
{/* PB1 点灯引脚  *///片上外设基地址+AHB总线基地址+RCC外设基地址+RCC的AHB1时钟使能PB寄存器地址//打开PB时钟*(unsigned int*)(0x40000000+0x20000+0x1000+0x18) |= ((1)<<3);//片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOB_CRL地址//配置成PB1开漏输出*(unsigned int*)(0x40000000+0x10000+0x0C00+0x00) &= ~( (0xFF)<<(4*0) );*(unsigned int*)(0x40000000+0x10000+0x0C00+0x00) |=  ( (1) << (4*0) );//片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOx_ODR地址//默认给一个PB1高电平 灯灭*(unsigned int*)(0x40000000+0x10000+0x0C00+0x0C) = 1;/* PA0 key1引脚 *///片上外设基地址+AHB总线基地址+RCC外设基地址+RCC的AHB1时钟使能PA寄存器地址//打开PA时钟*(unsigned int*)(0x40000000+0x20000+0x1000+0x18) |= ((1)<<2);//片上外设基地址+APB2总线基地址+GPIOA外设基地址+GPIOA_CRL地址//配置成PA0浮空输入*(unsigned int*)(0x40000000+0x10000+0x0800+0x00) &= ~( (0xFF) << (4*0) );*(unsigned int*)(0x40000000+0x10000+0x0800+0x00) |=  ( (0X04) << (4*0) );while(1){//片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOB_IDR地址//读取是否按下按钮if(*(unsigned int*)(0x40000000+0x10000+0x0800+0x08) & 1 != 0)//片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOx_ODR地址//低电平 灯灭*(unsigned int*)(0x40000000+0x10000+0x0C00+0x0C) &= ~(1<<0);else//片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOx_ODR地址//高电平 灯灭*(unsigned int*)(0x40000000+0x10000+0x0C00+0x0C) = 1;}
}// 函数为空,目的是为了骗过编译器不报错
void SystemInit(void)
{}

这样我们就实现了按下按钮点灯的操作。

本质上是等待 PA0 低电平后就把 PB1 拉低的程序。

三、中断

在图 EXTI功能框图 可以看到很多在信号线上打一个斜杠并标注“20”字样,这个表示在控制器内部类似的信号线路有20个, 这与EXTI总共有20个中断/事件线是吻合的。所以我们只要明白其中一个的原理,那其他19个线路原理也就知道了。

红色虚线指示的电路流程。它是一个产生中断的线路,最终信号流入到NVIC控制器内。这也是本篇中 GPIO 下降沿中断的线路。值得注意的是,图中的中断屏蔽/软件中断/下降沿等...是外设的寄存器,其最后需要传给 Cortex-M3 内核的 NVIC 寄存器进行中断优先级裁决,之后他会帮我们进行回调函数的操作。

绿色虚线指示的电路流程。它是一个产生事件的线路,最终输出一个脉冲信号。定时器等电机控制等使用的很多。在此不做描述。

3.1 中断线

EXTI有20个中断/事件线,每个GPIO都可以被设置为输入线,占用EXTI0至EXTI15, 还有另外七根用于特定的外设事件。

 

EXTI0 至 EXTI15 用于 GPIO,通过编程控制可以实现任意一个 GPIO 作为 EXTI 的输入源。 

 

3.2 配置外设的寄存器

3.2.1 外部中断配置寄存器 1(AFIO_EXTICR1)

我们首先需要配置 AFIO_EXTICR 外部中断配置寄存器。使能 GPIOA_0 按钮引脚这条中断线的外部中断复用。因为我们是 GPIOA_0 所以自然配置 EXTIO[3:0] 这个寄存器就可以了。

如果我们还想让 GPIOB_0 也有中断能力呢?因为我们已经给GPIOA 用了,所以就不能做到了。

//片上外设基地址+APB2总线基地址+AFIO基地址+外部中断配置寄存器1(AFIO_EXTICR1) *(unsigned int*)(0x40000000+0x10000+0x0000+0x08) = 0x00;

3.2.2 中断屏蔽寄存器(EXTI_IMR)

中断屏蔽器复位值是 0x0000 0000,也就是屏蔽所有中断,我们需要打开 MR0 的中断,使能 0 线的开启。

  //片上外设基地址+APB2总线基地址+EXTI基地址+中断屏蔽寄存器(EXTI_IMR) *(unsigned int*)(0x40000000+0x10000+0x0400+0x00) = 0x01;

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

  //片上外设基地址+APB2总线基地址+EXTI基地址+上升沿触发选择寄存器(EXTI_RTSR) *(unsigned int*)(0x40000000+0x10000+0x0400+0x08) = 0x01;

3.3 NVIC 配置

根据我们中断框图来看,在经过中断屏蔽等寄存器处理后,中断信号会传入到 NVIC 内。

在配置 Cortex-M3 内核的 NVIC 我们不再使用寄存器,为了方便而是使用 core_cm3.h 的库函数配置。

// 使用NVIC_EncodePriority函数编码中断优先级,并将结果存储在变量pri中  
uint32_t pri = NVIC_EncodePriority(5, 0, 2);  // 设置EXTI0_IRQn(外部中断0)的中断优先级为之前编码的pri值  
NVIC_SetPriority(EXTI0_IRQn, pri);  // 使能(启用)EXTI0_IRQn(外部中断0),使其能够在发生时被微控制器响应  
NVIC_EnableIRQ(EXTI0_IRQn);

上述代码中我们使用 2 位抢占,2 位相应的配置方式。最后我们将 EXTI0 中短线配置为 0 级抢占 2级优先级方案。

四、全部代码

#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_exti.h" int main(void)
{/* PB1 点灯引脚  *///片上外设基地址+AHB总线基地址+RCC外设基地址+RCC的AHB1时钟使能PB寄存器地址//打开PB时钟*(unsigned int*)(0x40000000+0x20000+0x1000+0x18) |= ((1)<<3);//片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOB_CRL地址//配置成PB1开漏输出*(unsigned int*)(0x40000000+0x10000+0x0C00+0x00) &= ~( (0xFF)<<(4*0) );*(unsigned int*)(0x40000000+0x10000+0x0C00+0x00) |=  ( (1) << (4*0) );//片上外设基地址+APB2总线基地址+GPIOB外设基地址+GPIOx_ODR地址//默认给一个PB1高电平 灯灭*(unsigned int*)(0x40000000+0x10000+0x0C00+0x0C) = 1;/* PA0 key1引脚 *///片上外设基地址+AHB总线基地址+RCC外设基地址+RCC的AHB1时钟使能PA寄存器地址//打开PA时钟*(unsigned int*)(0x40000000+0x20000+0x1000+0x18) |= ((1)<<2);//片上外设基地址+APB2总线基地址+GPIOA外设基地址+GPIOA_CRL地址//配置成PA0浮空输入*(unsigned int*)(0x40000000+0x10000+0x0800+0x00) &= ~( (0xFF) << (4*0) );*(unsigned int*)(0x40000000+0x10000+0x0800+0x00) |=  ( (0X04) << (4*0) );//片上外设基地址+APB2总线基地址+AFIO基地址+外部中断配置寄存器1(AFIO_EXTICR1) *(unsigned int*)(0x40000000+0x10000+0x0000+0x08) = 0x00;//片上外设基地址+APB2总线基地址+EXTI基地址+中断屏蔽寄存器(EXTI_IMR) *(unsigned int*)(0x40000000+0x10000+0x0400+0x00) = 0x01;//片上外设基地址+APB2总线基地址+EXTI基地址+上升沿触发选择寄存器(EXTI_RTSR) *(unsigned int*)(0x40000000+0x10000+0x0400+0x08) = 0x01;uint32_t pri=NVIC_EncodePriority(5,0,2);NVIC_SetPriority(EXTI0_IRQn,pri);NVIC_EnableIRQ(EXTI0_IRQn);/* 等待中断,由于使用中断方式,CPU不用轮询按键 */while(1)                            {}
}void KEY1_IRQHandler(void)
{//uint32_t a = *(unsigned int*)(0x40000000+0x10000+0x0C00+0x0C) ~= 1;*(unsigned int*)(0x40000000+0x10000+0x0C00+0x0C) ^= 1;EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);
}
/*********************************************END OF FILE**********************/

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

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

相关文章

Ps:创建调色观察图层组

人们往往受图像内容、所用显示器、自身对色彩敏感程度等的影响&#xff0c;无法准确地把握一张照片的明暗关系或色彩关系&#xff0c;因此导致修图时无方向、不精准。 如果通过数字化的方式建立观察图层&#xff08;组&#xff09;来辅助我们客观地分析照片&#xff0c;从而可以…

ARM编译器5.06下载安装

ARM编译器5.06下载安装 1.官网下载 进入官方网站ARM Complier v5.06官网下载页面 进入后的界面为 往下翻&#xff0c;找到如图位置的5.06 for windows的文件&#xff0c;点击下载&#xff0c;下载时需要登录账号 2.安装 先解压下载的压缩文件&#xff0c;在installer文件夹里…

react中render阶段做了什么

首先说明一个概念&#xff1a; render阶段对应的是Reconciler&#xff08;协调器&#xff09;&#xff0c; commit阶段对应的的是Renderer&#xff08;渲染器&#xff09; render阶段开始于performSyncWorkOnRoot或performConcurrentWorkOnRoot方法的调用。这取决于本次更新是…

解线性方程组(一)——克拉默法则求解(C++)

克拉默法则 解线性方程组最基础的方法就是使用克拉默法则&#xff0c;需要注意的是&#xff0c;该方程组必须是线性方程组。 假设有方程组如下&#xff1a; { a 11 x 1 a 12 x 2 ⋯ a 1 n x n b 1 a 21 x 1 a 22 x 2 ⋯ a 2 n x n b 2 ⋯ ⋯ ⋯ a n 1 x 1 a n 2 x 2…

[前端开发] CSS基础知识 [下]

上篇:CSS 基础知识 [上] CSS基础知识 [下] CSS 新特性媒体查询雪碧图字体图标 CSS 新特性 圆角 (border-radius) 通过 border-radius 属性为元素添加圆角。类型: border-radius: a b c d: 四个值分别为左上|右上|右下|左下角border-radius: a b c : 三个值分别为左上|右上和左下…

re:从0开始的CSS之旅 18. z-index

1. z-index z-index 属性用于设置元素的叠放层次&#xff0c;属性值可以为一个整数&#xff0c;整数值越大越优先显示 注意&#xff1a;z-index只对开启了定位的元素有效 示例如下&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta…

洛谷C++简单题小练习day13—文字处理软件

day13--文字处理软件--2.16 习题概述 题目描述 你需要开发一款文字处理软件。最开始时输入一个字符串作为初始文档。可以认为文档开头是第 0 个字符。需要支持以下操作&#xff1a; 1 str&#xff1a;后接插入&#xff0c;在文档后面插入字符串 str&#xff0c;并输出文档的…

ubuntu20修改xorg.conf实现双屏幕输出

如果显卡工作正常是不需要自己手动编写xorg.conf的&#xff08;这个文件一般不存在或者是空的&#xff09;&#xff0c;系统会根据xorg.conf的缺省自动设置屏幕。 但有时候有的屏幕输出不对&#xff0c;想手动固定一下配置。比如我的ROG想设置内屏用intel驱动&#xff08;集显…

HTTP请求的构造方式

前言&#xff1a; 在详解完HTTP协议的请求和响应格式以后&#xff0c;对HTTP协议就会有更深层次的了解。接下来就要了解HTTP协议的具体的一些用法基础。 在HTTP协议中有两个核心的作用&#xff1a;&#xff08;1&#xff09;如何让客户端构造一个HTTP请求&#xff1b;&#xff…

macOS 安装 conda

macOS 安装 conda 安装 conda参考 Conda是一个开源的软件包管理系统和环境管理系统&#xff0c;用于安装和管理软件包和其依赖项。 安装 conda mkdir miniconda3 cd miniconda3 bash Miniconda3-latest-MacOSX-x86_64.sh$ conda list参考 macOS 安装 conda开始使用conda

OpenAI Sora是世界模型?

初见Sora&#xff0c;我被OpenAI的野心震撼了。 他们不仅想教会AI理解视频&#xff0c;还要让它模拟整个物理世界&#xff01;这简直是通用人工智能的一大飞跃。 但当我深入了解后&#xff0c;我发现Sora比我想象的更复杂、更强大。 Sora不是简单的创意工具&#xff0c;而是…

8086指令小结

所有指令 &#xff08; 1 &#xff09;立即数不能作为目的操作数。 &#xff08; 2 &#xff09;不能在 2 个存储单元之间直接进行操作&#xff08;串操作除外&#xff09; 。 &#xff08; 3 &#xff09; MOV 指令和堆栈指令是惟一能对段寄存器进行操作的指令。 &…

【图像分割 2023】BRAU-Net++

【图像分割 2023】BRAU-Net 论文题目&#xff1a;BRAU-Net: U-Shaped Hybrid CNN-Transformer Network for Medical Image Segmentation 中文题目&#xff1a; 论文链接&#xff1a;[2401.00722] BRAU-Net: U-Shaped Hybrid CNN-Transformer Network for Medical Image Segment…

人工智能专题:通过AI转变保险(英译中)

今天分享的是人工智能系列深度研究报告&#xff1a;《人工智能专题&#xff1a;通过AI转变保险&#xff08;英译中&#xff09;》。 &#xff08;报告出品方&#xff1a;VIEWPOINT&#xff09; 在新时代释放数据的力量 在数据和人工智能 &#xff08; AI &#xff09; 融合的…

Leetcode 42. 接雨水

题意理解&#xff1a; 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 左边的柱子和右边的柱子形成围栏&#xff0c;可以使中间能够积水 求最大的积水面积。h*w 解题思路&#xff1a; 1.横向求解 这里的单…

vscode写MATLAB配置

vscode写MATLAB python下载 官网说明Versions of Python Compatible with MATLAB Products by Release - MATLAB & Simulink 不确定这三列都表示什么意思&#xff0c;尽量安装这三列都有的python版本吧&#xff0c;我安装的 MATLAB R2023b,python选择的是3.11.5 …

政安晨:【示例演绎】【Python】【Numpy数据处理】快速入门(三)—— 数组的操作

准备 这是Numpy数据处理的示例演绎系列文章的第三篇&#xff0c;我的前两篇文章为&#xff1a; 政安晨&#xff1a;【示例演绎】【Python】【Numpy数据处理】快速入门&#xff08;一&#xff09;https://blog.csdn.net/snowdenkeke/article/details/136125773 政安晨&#x…

【前端工程化面试题目】webpack 的热更新原理

可以在顺便学习一下 vite 的热更新原理&#xff0c;请参考这篇文章。 首先有几个知识点需要明确 热更新是针对开发过程中的开发服务器的&#xff0c;也就是 webpack-dev-serverwebpack 的热更新不需要额外的插件&#xff0c;但是需要在配置文件中 devServer属性中配置&#x…

计算机设计大赛 深度学习YOLO安检管制物品识别与检测 - python opencv

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络4 Yolov55 模型训练6 实现效果7 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习YOLO安检管制误判识别与检测 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&…

17.3.1.5 二值化(黑白)

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 二值化的算法主要有以下两种&#xff1a; 1、彩色图像灰度化后&#xff0c;根据灰度和阈值来确定颜色是黑色还是白色。通常情况下使…