【STM32存储器映射-寄存器基地址-偏移】
前言
在学习STM32的时候,我们看到很多的寄存器编程,
比方说LED灯:
//GPIOB.5端口输出高电平GPIOB->ODR|=1<<5; //PB.5 输出高GPIOE->ODR|=1<<5; //PE.5输出高 //GPIOB端口全部输出高电平*(unsigned int*)(0x4001 0C0C) = 0xFFFF;
就用到了寄存器,为什么对(0x4001 0C0C) 这个地址写0xFFFF,GPIOB就能输出高电平呢,这些寄存器的本质是什么,比方说GPIO,我们查看下GPIOB
和GPIOE
的定义
在stm32f10x.h里面,可以看到GPIOx
都是由GPIOX_BASE
,宏定义组成
再来看下GPIOX_BASE
分别代表什么:
可以看到GPIOX_BASE
都是由APB2PERIPH_BASE
这个定义加上一定的值组成,APB2我们知道是总线,学过STM32的应该都知道初始化一个外设之前,要先使能外设对应总线的时钟,通过这里我们知道GPIO是在APB2总线上的
再来看一下APB2PERIPH_BASE
是由PERIPH_BASE
加上0x10000 的宏定义,而PERIPH_BASE
的宏定义是0x40000000 也就是说,我们所操作的寄存器,本质就是对不同的地址写值,就可以实现想要的功能。
那么这些地址定义都是代表这什么呢,都是怎么来的呢,这就引出了我们今天的问题----STM32外设寄存器地址-基地址-偏移
STM32F1架构
STM32芯片基于ARM公司的Cortex-M3内核由ST公司设计生产,ARM公司并不生产芯片,而是出售其芯片技术授权。芯片生产厂商(SOC)如ST、TI、Freescale,负责在内核之外设计部件并生产整个芯片,这些内核之外的部件被称为核外外设或片上外设。内核与总线矩阵之间有ICode System (系统) 、DCode (数据) 三条信号线。内核通过总线矩阵与FLASH、SRAM、外设连接。而外设包括GPIO、USART、12C、SPI等。
内核
STM32F的内核CPU是cortex-M3
三大总线
指令总线、数据总线、系统总线
ICode 着重传输指令,DCode(Data 数据) 和 System 着重传输数据,至于更详细的区分,不用关心。实际上 ICode、DCode 和 System 内部都包含三个部分,即地址总线、控制总线、数据总线。
DMA总线
DMA Direct Memory Access缩写 直接存储器访问,可将数据从一个地址空间传输到另外一个地址空间,地址空间可以是外设到寄存器或者寄存器到寄存器。访问的数据可以是寄存器,也可以是SRAM,亦可是FLASH;数据可以被DCode和DMA同时访问到,因此为了避免访问冲突,需要总线来仲裁来决定哪个总线访问。
FLASH连接总线
内部的闪存存取器,即FLASH,程序存储在FLASH中,内核通过ICode读取指令。
SRAM 连接总线
内部的SRAM,即数据存储器RAM,程序的变量和堆栈开销在SRAM中。
高速外设连接总线AHB和APB桥
AHB和APB桥:AHB是高性能的系统总线,APB是外设总线。二者分别适用于高速和低速的设备连接。
AHB总线:全称Advanved High Performance Bus 高级高性能系统总线 简写:AHB
APB总线:全称Adanvced Peripheral Bus 高级外设总线 简写:APB
F1分为APB1和APB2 APB1=36MHZ APB2=72MHZ
Cortex-M3内存映射
我们这里以M3内核为例,STM32F1系列以Cortex-M3作为内核, 由于STM32系列芯片地址总线有32根,也就是一次最大可以访问00000000 00000000 00000000 00000000 — 11111111 11111111 11111111 11111111的2^32个地址,范围刚好为4G,可寻址空间为2^32=4GB;
也就是STM32系列最大有4GB的使用空间,下面我们先来看下M3内核的内存映射图。
如图这是M3内核的存储器映射图,从0x00000000到0xFFFFFFFF,一共4G的空间
这个图是ARM官方给出的M3内核图,所有使用Cortex-M3内核的芯片,内部的地址空间基本都是这样用的(ARM官方推荐厂商根据这个设计,厂商也可以自己设计。当然基本上芯片厂商是根据这个设计的)。
再来看下中文的图:
cortex-m3内核把4G空间分成了各个部分
Code代码区
用于存放和运行代码,存储用户下载的代码,还有出厂时固化的一些底层代码
SRAM
SRAM是运行时临时存放代码的地方。不同类型的STM32单片机的SRAM大小是不一样的,但是他们的起始地址都是0x2000 0000,终止地址都是0x2000 0000+其固定的容量大小。SRAM的理解比较简单,其作用是用来存取各种动态的输入输出数据、中间计算结果以及与外部存储器交换的数据和暂存数据,用于程序运行的堆栈开销。设备断电后,SRAM中存储的数据就会丢失。
Peripherals
用于设计片内外设,根据总线速度的不同,被分为了APB和AHB。在stm32中,有三大总线,AHB总线,APB1总线以及APB2总线。不同的外设挂载在不同的总线上边。比如GPIO,串口1,ADC以及部分定时器挂载在APB2总线上。我们通过操作这些外设对应的地址,便能控制这些外设寄存器。
下面看一下STM32官方给出的内存映射图,这个图可以详细的看出来STM32各个部分的映射,注意这个图是STM32F4的图,也就是M4内核的图
什么是存储器映射
可以看到各个部分详细的分类,
映射其实就是对应的意思。事实上存储器本身不具备地址,所以把芯片内核所预先设定好的地址分配给寄存器,就是存储器映射。因为stm32把这个4G的虚拟存储空间和芯片内部外设进行一一对应,每个外设和其对应的寄存器都有一个确定的地址,也就是给存储器分配地址,即存储器映射。
也就是说,ARM给M3内核的使用空间,设计了一个规范,而其本身就是一个4GB的空间,然后其中的一部分用于存储数据(RAM) ,一部分用来运行代码(code)还有一部分被赋予了某种意义(Peripherals),比方说GPIO,TIM定时器,ADC,IIC等等,就成为了片上外设,也就是寄存器 只是理论上的4G范围远远大与实际的存储器空间,也就说实际的存储器空间并没有4G。
寄存器的实际地址
我们可以看到在M4内核中,片上外设分配的地址是0x40000000-0x5FFFFFFF 而在上面的例子中,可以看到STM32官方的外设基地址PERIPH_BASE
的宏定义就是是0x40000000,在这部分空间中,不同的外设对应不同的地址。
STM32F10x.h这个头文件正是吧STM32的所有寄存器进行地址映射,此文件通过宏定义的方式,将各个寄存器的地址转换为相应的符号名称,
寄存器以四个字节为一个单元,也就是32bit,每一个单元对应不同的功能,当我们控制这些单元时就可以驱动外设工作。我们可以找到每个单元的起始地址,然后通过C语言指针
的操作方式来访问这些地址单元,对这些地址写入数据,就是对寄存器所对应的外设进行操作。
但是如果每次都是通过这种地址的方式来访问,不仅不好记忆还容易出错,你可以想象一下一个项目几千行地址赋值调用,这时我们可以根据每个单元功能的不同,以功能为名给这个内存单元取一个别名,这个别名就是我们经常说的寄存器,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。
而我们正常使用的寄存器的地址 = 基地址+偏移地址
(1)总线基地址
片上外设区分为四条总线,根据外设速度的不同,不同总线挂载着不同的外设, APB1 挂载低速外设,APB2 和 AHB 挂载高速外设。相应总线的最低地址我们称为该总线的基地址,总线基地址也是挂载在该总线上的首个外设的地址。APB1 总线的地址最低,因此片上外设就从这这个地址开始,也称外设基地址。
从上图可以看到 APB1 总线基地址是 0x4000 0000,相对外设基地址的偏移量是 0,所以此总线也是外设的基地址。
(2)外设基地址
每条总线上都会挂接着很多的外设,这些外设也会有自己的地址范围, 外设的最低地址就是外设的基地址,也称作边界地址。以 GPIO 外设来讲解外设基地址。其他的外设也是同样分析。
从图可以知道,外设 GPIOx 都是挂接在 APB2 总线上,属于高速的外设,而 APB2 总线的基地址是 0x4001 0000,故 GPIOA 的相对 APB2 总线的地址偏移是 800。
(3)外设寄存器地址
外设的寄存器就分布在其对应的外设地址范围内。这里我们以 GPIO 外设为例,GPIO 有很多个寄存器,每一个都有特定的功能。每个寄存器为 32bit,占四个字节,这些寄存器都是按顺序依次排列在外设的基地址上。寄存器的位置都以相对该外设基地址的偏移地址来描述。这里我们以 GPIOB 端口为例,来说明 GPIOB都有哪些寄存器,如所示。
这个就回到了我们一开始的那个问题:
```c //GPIOB.5端口输出高电平GPIOB->ODR|=1<<5; //PB.5 输出高//GPIOB端口全部输出高电平*(unsigned int*)(0x4001 0C0C) = 0xFFFF;
``0x4001 0C0C 也就是GPIOB 端口ODR寄存器,一共32位,其中低16位控制这端口的输出(output data) 所以我们对这个地址写FFFF 也就是 1111 1111 1111 1111 就是让GPIOB的所有端口输出高电平
总结
每个寄存器都有一个访问地址,每个外设中的所有寄存器的位置都是固定的,每组寄存器的起始地址在《STM32参考手册》的表1中列明;
寄存器的地址 = 基地址+偏移地址 比如:
整个外设的基地址 = AHB1 的偏移+GPIOB 寄存器组的偏移+GPIOB_OSPEEDR 寄存器的偏移
0x4002 0410 = 0x4000 0000 + 0x0002 0000 + 0x0C00 + 0x10
相关文章:

【STM32存储器映射-寄存器基地址-偏移】
前言 在学习STM32的时候,我们看到很多的寄存器编程, 比方说LED灯: //GPIOB.5端口输出高电平GPIOB->ODR|1<<5; //PB.5 输出高GPIOE->ODR|1<<5; //PE.5输出高 //GPIOB端口全部输出高电平*(unsigned int*)(0x4001 …...
【华为OD机试2023】最多颜色的车辆 C++ Java Python
【华为OD机试2023】最多颜色的车辆 C++ Java Python 前言 如果您在准备华为的面试,期间有想了解的可以私信我,我会尽可能帮您解答,也可以给您一些建议! 本文解法非最优解(即非性能最优),不能保证通过率。 Tips1:机试为ACM 模式 你的代码需要处理输入输出,input/cin接收…...
特斯拉后端面试(部分)
HR告知如果面试通过要转.net-_- round1 有没有用过Java新版本,知道有哪些特性吗?A:没有。Q:我们基本在用JDK11,有的新项目用到JDK17了。参考答案1: ZGC: A Scalable Low-Latency Garbage Collector Epsi…...

【python】使用python将360个文件夹里的照片,全部复制到指定的文件夹中,并且按照顺序重新命名
最近要做一个图像生成的课题,在网上找了一个混合的数据集。这个数据集中一共有360个文件夹,然后文件夹中有6-9张不等的照片,我的目标就是编写python代码将所有的照片取出来,放到一个指定的文件夹里,并且从1开始按照顺序…...

【C语言】3天速刷C语言(初识)
【声明】本篇博客只用于对与刚学习C语言的同学的一个初始了解,具体内容请继续关注本专栏后续内容。什么是C语言C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及…...

如何搞定MySQL锁(全局锁、表级锁、行级锁)?这篇文章告诉你答案!太TMD详细了!!!
概述 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、RAM、I/O)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题&…...

云计算生态该怎么做?阿里云计算巢打了个样
2023 年 2 月 23 日至 24 日,由阿里云主办的「阿里云计算巢加速器」于杭州阿里云谷园区集结。 阿里云计算巢加速器于 2022 年 8 月正式启动招募,最终百奥利盟、极智嘉、EMQ、KodeRover、MemVerge 等 30 家创新企业入选计算加速器,覆盖了人工智…...

小樽C++ 多章⑧ (贰) 指针与数组
目录 1.C中数组变量名某些情况可以看成是指针 2.C语言的scanf 输入语句,printf 输出语句 3.用指针来当动态数组 小樽C 多章⑧ (壹) 指针变量https://blog.csdn.net/weixin_44775255/article/details/129031168 小樽C 多章⑧ (叁) 指针与字符串、(肆) 函数与指针…...

MXNet的机器翻译实践《编码器-解码器(seq2seq)和注意力机制》
机器翻译就是将一种语言翻译成另外一种语言,输入和输出的长度都是不定长的,所以这里会主要介绍两种应用,编码器-解码器以及注意力机制。编码器是用来分析输入序列,解码器用来生成输出序列。其中在训练时,我们会使用一些…...

RK3588平台开发系列讲解(同步与互斥篇)自旋锁介绍
平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、自旋锁介绍二、自旋锁相关的函数1、普通场景2、进程上下文和下半部3、中断相关三、相关结构体四、函数实现1、初始化2、获取自旋锁沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇介绍自旋锁的使用和基…...

Linux系统CPU占用率较高问题排查思路
作为工程师,在日常工作中我们会遇到 Linux服务器上出现CPU负载达到100%居高不下的情况,如果CPU 持续跑高,则会影响业务系统的正常运行,带来企业损失。对于CPU过载问题通常使用以下两种方式即可快速定位:方法一第一步&a…...

源码解析——HashMap
源码解析——HashMap1. 什么 是HashMap2. 为什么要使用HashMap3. HashMap的使用4. 源码解析4.1 关键问题4.1 存储结构4.2 HashMap 的容量和负载因子4.3 初始化过程4.3 put() 方法实现原理4.3.1 hash()4.3.2 resize()4.4 get() 方法实现原理5. 面试题总结6. ConcurrentHashmap(J…...

Elasticsearch 核心技术(六):内置的 8 种分词器详解 + 代码示例
❤️ 博客主页:水滴技术 🚀 支持水滴:点赞👍 收藏⭐ 留言💬 🌸 订阅专栏:大数据核心技术从入门到精通 文章目录一、内置分词器1. Standard(标准分词器)英文示例中文示例…...

Mysql8.0的特性
Mysql8.0的特性 建议使用8.0.17及之后的版本,更新的内容比较多。 新增降序索引 -- 如下所示,我们可以在创建索引时 在字段名后面指定desc进行降序排序 create table t1(c1 int,c2 int,index idx_c1_c2(c1,c2 desc));group by 不再隐式排序 mysql5.7的版…...

JDK动态代理(tedu)(内含源代码)
JDK动态代理(tedu)(内含源代码) 源代码下载链接地址:https://download.csdn.net/download/weixin_46411355/87546187 目录JDK动态代理(tedu)(内含源代码)源代码下载链接…...

【数据结构】二叉搜索树
1、什么是二叉搜索树二叉搜索树又称为二叉排序树,二叉也就说明它跟二叉树一样最多只能有两个度,它可以是棵空树,也可以不是棵空树,当它不是棵空树的时候需要具备以下的性质:若它的左树不为空,那么它的左树上…...

抢跑数字中国建设,青岛市统计系统考察团赴实在智能调研统计数字员工
当前,数据要素价值不断显现,数字经济正引领着政企业加快数字技术的应用,融通创新工作机制,推进高质量转型。近日,中共中央、国务院印发了《数字中国建设整体布局规划》。《规划》指出,到2025年,…...

深浅拷贝——利用模拟实现basic_string深入理解
深浅拷贝——利用模拟实现basic_string深入理解 一、深浅拷贝的基本概念 深拷贝和浅拷贝都是指在对象复制时,复制对象的内存空间的方式。 1.1 深浅拷贝的不同之处 浅拷贝是指将一个对象的所有成员变量都直接拷贝给另一个对象,包括指针成员变量&#…...

大模型分布式系统
背景:模型越来越大,训练复杂度越来越高,需要训练的时间也是越来越长。那么我们该如何在现有的硬件基础上对模型做训练呢。模型规模的扩大,对硬件(算力、内存)的发展提出要求。然而,因为 内存墙 …...
【时序】时序预测任务模型选择如何选择?
时间序列是什么时间序列是一种特殊类型的数据集,其中一个或多个变量随着时间的推移被测量。 在时间序列中,观测值是随着时间的推移而测量的。你的数据集中的每个数据点都对应着一个时间点。这意味着你的数据集的不同数据点之间存在着一种关系。这对可以应用于时间序列数据集的…...

2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关
在水泥厂的生产流程中,工业自动化网关起着至关重要的作用,尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关,为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多,其中不少设备采用Devicenet协议。Devicen…...

Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...