历史上的今天
返回首页

历史上的今天

今天是:2024年09月29日(星期日)

正在发生

2019年09月29日 | 再造STM32---第三部分:什么是寄存器?

2019-09-29 来源:eefocus

本系列是基于STM32F429野火库进行学习。


3.1 STM32 长啥样?

STM32F429IGT6芯片实物图

1、学会看丝印;

2、懂得如何辨别正方向。

在这里插入图片描述
在这里插入图片描述

3.2 芯片里面有什么?

      我们看到的 STM32 芯片已经是已经封装好的成品,主要由内核和片上外设组成。若与电脑类比,内核与外设就如同电脑上的 CPU 与主板、内存、显卡、硬盘的关系。

      STM32F429 采用的是 Cortex-M4 内核,内核即 CPU,由 ARM 公司设计。 ARM 公司并不生产芯片,而是出售其芯片技术授权。芯片生产厂商(SOC)如 ST、 TI、 Freescale,负责在内核之外设计部件并生产整个芯片,这些内核之外的部件被称为核外外设或片上外设。如 GPIO、 USART(串口)、 I2C、 SPI 等都叫做片上外设。

在这里插入图片描述

      芯片和外设之间通过各种总线连接,其中主控总线有 8 条,被控总线有 7 条,具体见图 3-4。主控总线通过一个总线矩阵来连接被控总线, 总线矩阵用于主控总线之间的访问仲裁管理,仲裁采用循环调度算法。总线之间交叉的时候如果有个圆圈则表示可以通信,没有圆圈则表示不可以通信。比如 S0: I 总线只有跟 M0、 M2 和 M6 这三根被控总线交叉的时候才有圆圈,就表示 S0 只能跟这三根被控总线通信。从功能上来理解, I 总线是指令总线,用来取指,指令指的是编译好的程序指令。我们知道 STM32 有三种启动方式, 从 FLASH 启动(包含系统存储器),从内部 SRAM 启动,从外部 RAM 启动, 这三种存储器刚好对应的就是 M0、 M2 和M6 这三条总线。

在这里插入图片描述

图 3-4 STM32F42xxx 和 STM32F43xxx 器件的总线接口


3.3 存储器映射

在图 3-4 中, 连接被控总线的是 FLASH, RAM 和片上外设,这些功能部件共同排列在一个 4GB 的地址空间内。我们在编程的时候,操作的也正是这些功能部件。


3.3.1 存储器映射

存储器本身不具有地址信息,它的地址是由芯片厂商或用户分配,给存储器分配地址的过程就称为存储器映射。 如果给存储器再分配一个地址就叫存储器重映射。

在这里插入图片描述
在这里插入图片描述

下面内容非常重要,务必注意!

3.3.2 寄存器映射:

让GPIOH端口的16个引脚输出高电平,要怎么实现?

通过绝对地址访问内存单元

在这里插入图片描述

1、 0X40021C14 是GPIOH输出数据寄存器ODR的地址,如何找到?

2、 (unsigned int*)的作用是什么?

()—类型强制转换;unsigned int—32位; * 表示指针类型。即32位指针类型。

3、 学会使用C语言的 * 号

通过寄存器别名方式访问内存单元

在这里插入图片描述

为了方便操作,我们干脆把指针操作 * 也定义到寄存器别名里面

在这里插入图片描述

3.3.3 什么是寄存器?

什么是寄存器?

给有特定功能的内存单元取一个别名,这个别名就是我们经常说的寄存器,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。

什么叫存储器映射?

给存储器分配地址的过程叫存储器映射,再分配一个地址叫重映射。


3.4.1 STM32 的外设地址映射:(内存<----->寄存器<----->结构体)

      片上外设区分为四条总线,根据外设速度的不同,不同总线挂载着不同的外设, APB挂载低速外设, AHB 挂载高速外设。相应总线的最低地址我们称为该总线的基地址,总线基地址也是挂载在该总线上的首个外设的地址。其中 APB1 总线的地址最低,片上外设从这里开始,也叫外设基地址。

1. 总线基地址

表格 3-5 总线基地址:

在这里插入图片描述

      表格 5-5 的“相对外设基地址偏移”即该总线地址与“片上外设”基地址 0x4000 0000的差值。关于地址的偏移我们后面还会讲到。

2. 外设基地址

      总线上挂载着各种外设,这些外设也有自己的地址范围,特定外设的首个地址称为“XX 外设基地址”,也叫 XX 外设的边界地址。具体有关 STM32F4xx 外设的边界地址请参考《STM32F4xx 参考手册》的 2.3 小节的存储器映射的表 2: STM32F4xx 寄存器边界地址。或者参考《STM32F4xx 参考手册》的存储器映射章节,这两个手册都有详细的讲解。

      这里面我们以 GPIO 这个外设来讲解外设的基地址,具体见表格 3-6。

表格 3-6 外设 GPIO 基地址

在这里插入图片描述

      从表格 3-6 看到, GPIOA 的基址相对于 AHB1 总线的地址偏移为 0,我们应该就可以猜到, AHB1 总线的第一个外设就是 GPIOA。

3. 外设寄存器

      在 XX 外设的地址范围内,分布着的就是该外设的寄存器。以 GPIO 外设为例, GPIO是通用输入输出端口的简称,简单来说就是 STM32 可控制的引脚,基本功能是控制引脚输出高电平或者低电平。最简单的应用就是把 GPIO 的引脚连接到 LED 灯的阴极, LED 灯的阳极接电源,然后通过 STM32 控制该引脚的电平,从而实现控制 LED 灯的亮灭。GPIO 有很多个寄存器,每一个都有特定的功能。每个寄存器为 32bit,占四个字节,在该外设的基地址上按照顺序排列,寄存器的位置都以相对该外设基地址的偏移地址来描述。这里我们以 GPIOH 端口为例,来说明 GPIO 都有哪些寄存器,具体见表格 3-7。

      表格 3-7 GPIOH 端口的 寄存器地址列表

在这里插入图片描述

      有关外设的寄存器说明可参考《STM32F4xx 参考手册》中具体章节的寄存器描述部分,在编程的时候我们需要反复的查阅外设的寄存器说明。这里我们以“GPIO 端口置位/复位寄存器”为例,教大家如何理解寄存器的说明,具体见图 3-6。

在这里插入图片描述

图 3-6 GPIO 端口置位/复位寄存器说明

 ①名称

      寄存器说明中首先列出了该寄存器中的名称,“(GPIOx_BSRR)(x=A…I)”这段的意思是该寄存器名为“GPIOx_BSRR”其中的“x”可以为 A-I,也就是说这个寄存器说明适用于 GPIOA、 GPIOB 至 GPIOI,这些 GPIO 端口都有这样的一个寄存器。

 ②偏移地址

      偏移地址是指本寄存器相对于这个外设的基地址的偏移。本寄存器的偏移地址是 0x18,从参考手册中我们可以查到 GPIOA 外设的基地址为 0x4002 0000 ,我们就可以算出GPIOA 的这个 GPIOA_BSRR 寄存器的地址为: 0x4002 0000+0x18 ;同理,由于 GPIOB 的外设基地址为 0x4002 0400,可算出 GPIOB_BSRR 寄存器的地址为: 0x4002 0400+0x18 。其他 GPIO 端口以此类推即可。

 ③寄存器位表

      紧接着的是本寄存器的位表,表中列出它的 0-31 位的名称及权限。表上方的数字为位编号,中间为位名称,最下方为读写权限,其中 w 表示只写, r 表示只读, rw 表示可读写。本寄存器中的位权限都是 w,所以只能写,如果读本寄存器,是无法保证读取到它真正内容的。而有的寄存器位只读,一般是用于表示 STM32 外设的某种工作状态的,由 STM32硬件自动更改,程序通过读取那些寄存器位来判断外设的工作状态。

 ④位功能说明

      位功能是寄存器说明中最重要的部分,它详细介绍了寄存器每一个位的功能。例如本寄存器中有两种寄存器位,分别为 BRy 及 BSy,其中的 y 数值可以是 0-15,这里的 0-15表示端口的引脚号,如 BR0、 BS0 用于控制 GPIOx 的第 0 个引脚,若 x 表示 GPIOA,那就是控制 GPIOA 的第 0 引脚,而 BR1、 BS1 就是控制 GPIOA 第 1 个引脚。其中 BRy 引脚的说明是“0:不会对相应的 ODRx 位执行任何操作; 1:对相应 ODRx位进行复位”。这里的“复位”是将该位设置为 0 的意思,而“置位”表示将该位设置为1;说明中的 ODRx 是另一个寄存器的寄存器位,我们只需要知道 ODRx 位为 1 的时候,对应的引脚 x 输出高电平,为 0 的时候对应的引脚输出低电平即可(感兴趣的读者可以查询

      该寄存器 GPIOx_ODR 的说明了解)。所以,如果对 BR0 写入“1”的话,那么 GPIOx 的第0 个引脚就会输出“低电平”,但是对 BR0 写入“0”的话,却不会影响 ODR0 位,所以引脚电平不会改变。要想该引脚输出“高电平”,就需要对“BS0”位写入“1”,寄存器位BSy 与 BRy 是相反的操作。


3.4.2 C 语言对寄存器的封装:

      以上所有的关于存储器映射的内容,最终都是为大家更好地理解如何用 C 语言控制读写外设寄存器做准备,此处是本章的重点内容。

1. 封装总线和外设基地址

      在编程上为了方便理解和记忆,我们把总线基地址和外设基地址都以相应的宏定义起来,总线或者外设都以他们的名字作为宏名,具体见代码 3-4。

      代码 3-4 总线和外设基址宏定义

在这里插入图片描述

以下为解释: 

第1~3行的依据:

在这里插入图片描述

第4~9行的依据:

在这里插入图片描述

第10~19行依据:

在这里插入图片描述

第20~30行依据:

在这里插入图片描述

      代码 3-4 首先定义了 “片上外设”基地址 PERIPH_BASE,接着在 PERIPH_BASE 上加入各个总线的地址偏移,得到 APB1、 APB2 等总线的地址 APB1PERIPH_BASE、APB2PERIPH_BASE,在其之上加入外设地址的偏移,得到 GPIOA、 GPIOH 的外设地址,最后在外设地址上加入各寄存器的地址偏移,得到特定寄存器的地址。一旦有了具体地址,就可以用指针操作读写了,具体见代码 3-5。

      代码 3-5 使用指针控制 BSRR 寄存器

在这里插入图片描述

      该代码使用 (unsigned int * ) 把 GPIOH_BSRR 宏的数值强制转换成了地址,然后再用“ * ”号做取指针操作,对该地址的赋值,从而实现了写寄存器的功能。同样,读寄存器也是用取指针操作,把寄存器中的数据取到变量里,从而获取 STM32 外设的状态。

以下为GPIOH_BSRR和GPIOH_IDR寄存器的说明:

在这里插入图片描述
在这里插入图片描述

2. 封装寄存器列表

      用上面的方法去定义地址,还是稍显繁琐,例如 GPIOA-GPIOH 都各有一组功能相同的寄存器,如 GPIOA_MODER/GPIOB_MODER/GPIOC_MODER 等等,它们只是地址不一样,但却要为每个寄存器都定义它的地址。为了更方便地访问寄存器,我们引入 C 语言中的结构体语法对寄存器进行封装,具体见代码 3-6。

      代码 3-6 使用结构体对 GPIO 寄存器组的封装

在这里插入图片描述

      这段代码用 typedef 关键字声明了名为 GPIO_TypeDef 的结构体类型,结构体内有 8 个成员变量,变量名正好对应寄存器的名字。 C 语言的语法规定,结构体内变量的存储空间是连续的,其中 32 位的变量占用 4 个字节, 16 位的变量占用 2 个字节,具体见图 3-7。

在这里插入图片描述

图 3-7 GPIO_TypeDef 结构体成员的地址偏移

      也就是说,我们定义的这个 GPIO_TypeDef , 假如这个结构体的首地址为 0x40021C00(这也是第一个成员变量 MODER 的地址) , 那么结构体中第二个成员变量OTYPER 的地址即为 0x4002 1C00 +0x04 , 加上的这个 0x04 ,正是表 MODER 所占用的4 个字节地址的偏移量,其它成员变量相对于结构体首地址的偏移,在上述代码右侧注释已给出,其中的 BSRR 寄存器分成了低 16 位 BSRRL 和高 16 位 BSRRH, BSRRL 置 1 引脚输出高电平, BSRRH 置 1 引脚输出低电平,这里分开只是为了方便操作。

      这样的地址偏移与 STM32 GPIO 外设定义的寄存器地址偏移一一对应,只要给结构体设置好首地址,就能把结构体内成员的地址确定下来,然后就能以结构体的形式访问寄存器了,具体见代码 3-7。

      代码 3-7 通过结构体指针访问寄存器

在这里插入图片描述

      这段代码先用 GPIO_TypeDef 类型定义一个结构体指针 GPIOx,并让指针指向地址GPIOH_BASE(0x4002 1C00),使用地址确定下来,然后根据 C 语言访问结构体的语法,用GPIOx->BSRRL、 GPIOx->MODER 及 GPIOx->IDR 等方式读写寄存器。

      最后,我们更进一步,直接使用宏定义好 GPIO_TypeDef 类型的指针,而且指针指向各个 GPIO 端口的首地址,使用时我们直接用该宏访问寄存器即可,具体代码 3-8。

      代码 3-8 定义好 GPIO 端口首地址址针

在这里插入图片描述
在这里插入图片描述

      这里我们仅是以 GPIO 这个外设为例,给大家讲解了 C 语言对寄存器的封装。以此类推,其他外设也同样可以用这种方法来封装。好消息是,这部分工作都由固件库帮我们完成了,这里我们只是分析了下这个封装的过程,让大家知其然,也只其所以然。


3.4.3 修改寄存器的位操作方法:(!!!重要!!!)

      使用 C 语言对寄存器赋值时,我们常常要求只修改该寄存器的某几位的值,且其它的寄存器位不变,这个时候我们就需要用到 C 语言的位操作方法了。

1. 把变量的某位清零

      此处我们以变量 a 代表寄存器,并假设寄存器中本来已有数值,此时我们需要把变量a 的某一位清零,且其它位不变,方法见代码清单 3-1。

      代码清单 3-1 对某位清零

在这里插入图片描述

2. 把变量的某几个连续位清零

      由于寄存器中有时会有连续几个寄存器位用于控制某个功能,现假设我们需要把寄存器的某几个连续位清零,且其它位不变,方法见代码清单 3-2。

      代码清单 3-2 对某几个连续位清零

在这里插入图片描述

3. 对变量的某几位进行赋值。

      寄存器位经过上面的清零操作后,接下来就可以方便地对某几位写入所需要的数值了,且其它位不变,方法见代码清单 3-3,这时候写入的数值一般就是需要设置寄存器的位参数。

      代码清单 3-3 对某几位进行赋值

在这里插入图片描述

4. 对变量的某位取反

      某些情况下,我们需要对寄存器的某个位进行取反操作,即 1 变 0 , 0 变 1,这可以直接用如下操作,其它位不变,见代码清单 3-4。

      代码清单 3-4 对某位进行取反操作

在这里插入图片描述

      关于修改寄存器位的这些操作,在下一章中有应用实例代码,可配合阅读。


推荐阅读

史海拾趣

EPIC公司的发展小趣事

随着公司的发展,Epic Games开始通过收购和投资来扩展其业务范围。2007年8月20日,Epic Games收购了一家位于波兰的游戏开发商People Can Fly,并成为其第一大股东。这次收购不仅为Epic Games带来了更多的开发资源,也使其在游戏开发领域的实力得到了进一步提升。此外,Epic Games还积极投资其他有潜力的游戏开发商和团队,以推动整个游戏行业的创新和发展。

Everspin Technologies公司的发展小趣事

Everspin Technologies公司的起源可以追溯到飞思卡尔半导体公司。在2004年,摩托罗拉将其半导体业务剥离,创建了飞思卡尔半导体。这家公司在磁阻随机存取存储器(MRAM)领域进行了大量研究和开发工作。随着MRAM技术的成熟,飞思卡尔半导体决定将其MRAM部门独立出来,于是在2008年,Everspin Technologies公司正式成立,专注于MRAM的设计、制造和销售。

Harvatek Corporation公司的发展小趣事

背景:随着电子技术的飞速发展,Hantronix始终站在技术创新的前沿。公司不断投入研发资源,致力于开发具有自主知识产权的新产品和技术。

发展:Hantronix成功推出了一系列创新产品,如液晶显示器、图形模块、触摸屏等,这些产品不仅性能卓越,而且设计独特,满足了市场多样化的需求。同时,公司还积极申请专利保护,确保其技术成果得到法律的有效保障。

意普(ESPE)公司的发展小趣事

作为一家有社会责任感的企业,意普(ESPE)公司始终关注环保和可持续发展。公司采用环保材料和生产工艺,减少了对环境的污染。同时,公司还积极参与社会公益活动,为社会做出了积极贡献。这些举措不仅提升了公司的社会形象,也为企业的长期发展奠定了良好的社会基础。

Big-Sun Electronics Co Ltd公司的发展小趣事

随着国内市场的逐步饱和,Big-Sun Electronics Co Ltd公司开始将目光投向国际市场。公司积极参与国际电子展会,与海外客户建立起了良好的合作关系。同时,Big-Sun还与国际知名电子企业开展技术合作,共同研发新产品,进一步提升了公司的国际竞争力。

EEMB Co Ltd公司的发展小趣事

随着技术的不断进步和市场需求的日益增长,EEMB集团开始加大研发投入,力求在锂电池技术上实现更大的突破。经过不懈努力,公司成功研发出多款具有高性能、高安全性和长寿命特点的锂电池产品,并获得了多项国家专利。这些技术成果不仅提升了公司的市场竞争力,也为公司赢得了更多客户的青睐。同时,公司也积极开拓国际市场,产品逐渐出口到美国、日本、俄罗斯等国家。

问答坊 | AI 解惑

中国IC产业销售收入规模及增长趋势

中国IC产业销售收入规模及增长趋势 2006-7-11     2006年第一季度,我国集成电路产业全行业共实现销售收入总额214.88亿元,同比增长54.8%。 …

查看全部问答>

基于PXA255的ARM Linux操作系统移植

摘要: Linux在嵌入式领域中应用越来越广泛,已成为最有潜力的嵌入式操作系统。操作系统的移植是进行嵌入式应用开发的前提和基础。ARM Linux是一种针对ARM体系结构的Linux操作系统。本文以新一代高端嵌入式处理器PXA255为例,进行ARM Linux的移植, ...…

查看全部问答>

请教各位前辈!!!

我是一名在校大学生,想问一下,现在Multisim 8这个电路设计软件怎么样?在实际工作中运用的多不多?本人想好好学一学!是否有这个必要?也请各位推荐下好的教程!!!…

查看全部问答>

CPES-IBM未来通信电源功率架构

CPES-IBM未来通信电源功率架构…

查看全部问答>

小车控制算法研究 高手大牛 来说说思路

车图 跑道 现在  要控制车子速度 通过一个舵机控制车头转动方向 转动的方向由前面的红外传感器检测到跑道的识别码得到 但是检测的识别码只可能尽量的和实际吻合但仍会有几度的误差 有时甚至会更多 程序会不停的扫描道路得到识 ...…

查看全部问答>

下载wince5.0内核液晶不亮,但wince4.2正常

我用的是QQ2440板子,液晶屏是FriendlyARM 8.4\'\'LCD,我将光盘自带的wince4.2的nk.bin下载后,液晶屏正常显示,但是换成wince5.0的nk.bin液晶屏却是黑屏,刚开机时能隐约看到5.0的界面,但慢慢就变黑了,哪位知道原因。对液晶屏的供电是3.3V和5V ...…

查看全部问答>

嵌入式问题

题目如下: 设计一个针对某一具体应用的嵌入式系统 要求:1有完整的系统设计方案 2对系统方案有完整说明 3有相应的印制版图 4有完整的系统调试方案 5软件流程及其说明 急 麻烦高手指点迷津 谢谢…

查看全部问答>

双网卡热备份(双网卡冗余备份)如何设计与实现呢(2)?

你好?WIN2000下,以太网网络,双网卡热备份,也就是一个网卡坏了,另一个冗余网卡热切换,两个网卡同一个IP地址,实现方案是什么?使用哪些工具,技术?代码是什么?请问做双网卡热备份,是不是在ndis的例子PASSTHRU的代码基础上,修改即可?怎么修改?希望不 ...…

查看全部问答>

求助:USB HID设备无法访问题

我在做一块usb声卡,这是一个USB Composite Device,Firmware写完了,现在想做pc host的app,要对HID的endpoint4写数据,打开设备的时候能得到设备路径,但是无法读写,部分代码如下。     //Open the USB device     char c ...…

查看全部问答>

类CPdd16550中m_dwWaterMark是用来干什么的?

类CPdd16550中m_dwWaterMark是用来干什么的? 是波特率的mark呢还是安全相关的mark? 有劳各位!…

查看全部问答>