STM32(二):STM32工作原理

这里写目录标题

    • 0、参考
    • 1、寄存器和存储器基本概念
        • (1)基本概念
        • (2)主要区别
        • (3)联系
        • (4)实际应用中的案例
        • (5)总结
        • (6)一些名词解释
    • 2、STM32指南者板子-存储器区域
        • 总划分
        • Block0
        • Block1
        • Block2
    • 3、STM32指南者板子-寄存器区域(片子上是存储器的BLOCK2这块区域)
        • (1)片上外设基地址
        • (2)总线基地址
        • (3)GPIO外设基地址
        • (4)GPIO外设寄存器地址
        • 总结
    • 4、C语言使用封装寄存器
        • (1)定义结构体GPIO_TypeDef
        • (2)定义外设基地址
        • (3)使用GPIO_TypeDef把地址强制转换成指针
        • (4)则访问任意端口的某个寄存器
    • 5、C语言常用位操作
        • 对某一位清零a &= ~(1<<2)
        • 对某一位取反a ^=(1<<6)
        • 对某几位清零a &= ~(3<<2*1)
        • 对某几位进行赋值a |= (1<<2*2)

0、参考

  • https://doc.embedfire.com/mcu/stm32/f103zhinanzhe/std/zh/latest/book/register.html
  • https://blog.csdn.net/m0_74091159/article/details/139794521

1、寄存器和存储器基本概念

在计算机系统中,寄存器和存储器是两个重要的概念,它们在数据存储和处理过程中扮演着不同但互补的角色。本文将详细讨论寄存器和存储器的区别与联系。

(1)基本概念

寄存器(Register)是一种速度极快的小容量存储单元,通常集成在CPU内部,用于暂存数据和指令。寄存器可以在一个CPU时钟周期内被读取或写入。

存储器(Memory)通常指随机存取存储器(RAM),是一种速度较慢但容量较大的存储设备,用于存储正在执行的程序和数据。存储器分为主存储器(如DRAM)和辅助存储器(如硬盘、SSD)。

(2)主要区别

速度

寄存器:速度最快,通常是计算机中最快的存储设备,因为它们直接集成在CPU内部,能够在一个时钟周期内进行读写操作。
存储器:速度相对较慢,即使是快速的DRAM,其访问速度也比寄存器慢一个数量级以上。

容量

寄存器:容量非常小,通常在几个字节到几百字节之间。这是因为寄存器的制造成本高,且CPU内部空间有限。
存储器:容量较大,现代计算机的RAM通常在几GB到几十GB之间,而辅助存储器则可达到TB级别。

位置和功能

寄存器:位于CPU内部,主要用于临时存储指令和数据,参与运算操作。例如,累加器(Accumulator)、程序计数器(Program Counter)和状态寄存器(Status Register)。
存储器:位于CPU外部,通过系统总线与CPU连接。用于存储当前运行的程序和数据,是操作系统和应用程序的运行空间。

功能与用途

寄存器:用于快速存取需要立即处理的数据,是CPU执行指令的关键组成部分。例如,寄存器用于存储操作数、结果、地址和控制信息。
存储器:用于存储大量数据和程序,是计算机系统的主要数据存储设备。例如,操作系统、应用程序以及用户数据都存储在存储器中。
(3)联系

虽然寄存器和存储器在性能和用途上有显著区别,但它们之间存在密切的联系:

数据交换

寄存器和存储器之间需要频繁的数据交换。CPU从存储器中读取指令和数据到寄存器,进行处理后,再将结果存回存储器。这种数据交换是通过系统总线和高速缓存(Cache)实现的。

层次结构

寄存器、缓存、主存储器(RAM)和辅助存储器(如硬盘、SSD)构成了计算机的存储层次结构。寄存器在最上层,速度最快但容量最小;辅助存储器在最底层,速度最慢但容量最大。这种层次结构保证了在成本和性能之间的平衡。

性能优化

现代计算机系统通过多级缓存(L1、L2、L3)来优化寄存器和存储器之间的数据交换,从而提升整体性能。缓存存储器介于寄存器和主存储器之间,存储经常使用的数据和指令,减少对较慢存储器的访问次数。
(4)实际应用中的案例

CPU指令执行过程

在执行一条指令时,CPU首先从存储器中取出指令(Fetch),将其存入指令寄存器(Instruction Register)。然后,指令译码器(Decoder)将指令译码,并根据指令类型从存储器或其他寄存器中获取操作数。接下来,执行单元(如算术逻辑单元ALU)对操作数进行运算,并将结果存入目标寄存器或存储器中。

高性能计算

在高性能计算(HPC)中,寄存器和存储器的有效利用对于提高计算效率至关重要。通过优化寄存器分配和存储器访问模式,可以显著提升计算速度。例如,使用寄存器重命名技术可以避免寄存器资源冲突,从而提高指令级并行性。
(5)总结

寄存器和存储器在计算机系统中扮演着不同但互补的角色。寄存器负责快速数据存取和处理,而存储器则提供大量数据和程序的存储空间。通过高效的数据交换和存储层次结构,计算机系统在性能和成本之间找到了平衡。这种分工和协作是现代计算机系统高效运行的基础。

(6)一些名词解释

存储器:

  • FLASH:闪存存储器,我们编写好的程序就放在这个地方;
  • SRAM:即我们通常说的RAM,程序的变量,堆栈等的开销都是基于内部的SRAM;
  • ROM:只读存储器;

2、STM32指南者板子-存储器区域

总划分

在这里插入图片描述

Block0

在这里插入图片描述

Block1

在这里插入图片描述

Block2

在这里插入图片描述

3、STM32指南者板子-寄存器区域(片子上是存储器的BLOCK2这块区域)

在存储器Block2这块区域,设计的是片子的外设,它们以四个字节为一个单元,共32bit,每一个单元对应不同的功能, 当我们控制这些单元时就可以驱动外设工作。(使用板子的时候就是用这一块来控制外设)

我们可以找到每个单元的起始地址,然后通过C语言指针的操作方式来访问这些单元, 如果每次都是通过这种地址的方式来访问,不仅不好记忆还容易出错,这时我们可以根据每个单元功能的不同,以功能为名给这个内存单元取一个别名, 这个别名就是我们经常说的寄存器,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。
在这里插入图片描述

(1)片上外设基地址

即存储器Block2的首地址

0x40000000
(2)总线基地址

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

(3)GPIO外设基地址

总线上挂载着各种外设,这些外设也有自己的地址范围,特定外设的首个地址称为“XX外设基地址”,也叫XX外设的边界地址。

以GPIO这个外设来讲解外设的基地址,GPIO属于高速的外设 ,挂载到APB2总线上
在这里插入图片描述

(4)GPIO外设寄存器地址

GPIO有很多个寄存器,每一个都有特定的功能。每个寄存器为32bit,占四个字节,在该外设的基地址上按照顺序排列, 寄存器的位置都以相对该外设基地址的偏移地址来描述。

以GPIOB端口为例,说明GPIO都有哪些寄存器
在这里插入图片描述有关外设的寄存器说明可参考《STM32F10xx参考手册》中具体章节的寄存器描述部分,在编程的时候我们需要反复的查阅外设的寄存器说明。

总结
/* 外设基地址 */
#define PERIPH_BASE           ((unsigned int)0x40000000)

/* 总线基地址 */
#define APB1PERIPH_BASE       PERIPH_BASE
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x00010000)
#define AHBPERIPH_BASE        (PERIPH_BASE + 0x00020000)


/* GPIO外设基地址 */
#define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800)
#define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00)
#define GPIOC_BASE            (APB2PERIPH_BASE + 0x1000)
#define GPIOD_BASE            (APB2PERIPH_BASE + 0x1400)
#define GPIOE_BASE            (APB2PERIPH_BASE + 0x1800)
#define GPIOF_BASE            (APB2PERIPH_BASE + 0x1C00)
#define GPIOG_BASE            (APB2PERIPH_BASE + 0x2000)


/* 寄存器基地址,以GPIOB为例 */
#define GPIOB_CRL             (GPIOB_BASE+0x00)
#define GPIOB_CRH             (GPIOB_BASE+0x04)
#define GPIOB_IDR             (GPIOB_BASE+0x08)
#define GPIOB_ODR             (GPIOB_BASE+0x0C)
#define GPIOB_BSRR            (GPIOB_BASE+0x10)
#define GPIOB_BRR             (GPIOB_BASE+0x14)
#define GPIOB_LCKR            (GPIOB_BASE+0x18)

4、C语言使用封装寄存器

因为GPIOA ~ GPIOG每一个都有GPIOXXX_CRL ~ GPIOXXX_LCKR,因此在C语言使用定义的时候可以用结构体封装好:

(1)定义结构体GPIO_TypeDef
typedef unsigned           int uint32_t; /*无符号32位,4个字节变量*/
typedef unsigned short     int uint16_t; /*无符号16位,2个字节变量*/

/* GPIO寄存器列表(变量,不是地址) */
typedef struct {
    uint32_t CRL;     /*GPIO端口配置低寄存器    地址偏移: 0x00 */
    uint32_t CRH;     /*GPIO端口配置高寄存器    地址偏移: 0x04 */
    uint32_t IDR;     /*GPIO数据输入寄存器      地址偏移: 0x08 */
    uint32_t ODR;     /*GPIO数据输出寄存器      地址偏移: 0x0C */
    uint32_t BSRR;    /*GPIO位设置/清除寄存器   地址偏移: 0x10 */
    uint32_t BRR;     /*GPIO端口位清除寄存器     地址偏移: 0x14 */
    uint16_t LCKR;    /*GPIO端口配置锁定寄存器   地址偏移: 0x18 */
} GPIO_TypeDef;
(2)定义外设基地址
/* 外设基地址 */
#define PERIPH_BASE           ((unsigned int)0x40000000)

/* 总线基地址 */
#define APB1PERIPH_BASE       PERIPH_BASE
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x00010000)
#define AHBPERIPH_BASE        (PERIPH_BASE + 0x00020000)


/* GPIO外设基地址 */
#define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800)
#define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00)
#define GPIOC_BASE            (APB2PERIPH_BASE + 0x1000)
#define GPIOD_BASE            (APB2PERIPH_BASE + 0x1400)
#define GPIOE_BASE            (APB2PERIPH_BASE + 0x1800)
#define GPIOF_BASE            (APB2PERIPH_BASE + 0x1C00)
#define GPIOG_BASE            (APB2PERIPH_BASE + 0x2000)
(3)使用GPIO_TypeDef把地址强制转换成指针
#define GPIOA               ((GPIO_TypeDef *) GPIOA_BASE)
#define GPIOB               ((GPIO_TypeDef *) GPIOB_BASE)
#define GPIOC               ((GPIO_TypeDef *) GPIOC_BASE)
#define GPIOD               ((GPIO_TypeDef *) GPIOD_BASE)
#define GPIOE               ((GPIO_TypeDef *) GPIOE_BASE)
#define GPIOF               ((GPIO_TypeDef *) GPIOF_BASE)
#define GPIOG               ((GPIO_TypeDef *) GPIOG_BASE)
#define GPIOH               ((GPIO_TypeDef *) GPIOH_BASE)
(4)则访问任意端口的某个寄存器
/*使用定义好的宏直接访问*/
/*访问GPIOB端口的寄存器*/
GPIOB->BSRR = 0xFFFF;       //通过指针访问并修改GPIOB_BSRR寄存器
GPIOB->CRL = 0xFFFF;        //修改GPIOB_CRL寄存器
GPIOB->ODR =0xFFFF;         //修改GPIOB_ODR寄存器

uint32_t temp;
temp = GPIOB->IDR;          //读取GPIOB_IDR寄存器的值到变量temp中

/*访问GPIOA端口的寄存器*/
GPIOA->BSRR = 0xFFFF;
GPIOA->CRL = 0xFFFF;
GPIOA->ODR =0xFFFF;

uint32_t temp;
temp = GPIOA->IDR;          //读取GPIOA_IDR寄存器的值到变量temp中

5、C语言常用位操作

对某一位清零a &= ~(1<<2)

以变量a代表寄存器,并假设寄存器中本来已有数值,此时我们需要把变量a的某一位清零,且其它位不变

//定义一个变量a = 1001 1111 b (二进制数)
unsigned char a = 0x9f;

//对bit2 清零

a &= ~(1<<2);

//括号中的1左移两位,(1<<2)得二进制数:0000 0100 b
//按位取反,~(1<<2)得1111 1011 b
//假如a中原来的值为二进制数: a = 1001 1111 b
//所得的数与a作”位与&”运算,a = (1001 1111 b)&(1111 1011 b),
//经过运算后,a的值 a=1001 1011 b
// a的bit2 位被清零,而其它位不变。
对某一位取反a ^=(1<<6)

对寄存器的某个位进行取反操作,即 1变0 ,0变1,这可以直接用如下操作,其它位不变

//a = 1001 0011 b
//把bit6取反,其它位不变

a ^=(1<<6);
//a = 1101 0011 b
对某几位清零a &= ~(3<<2*1)
//定义一个变量a = 1001 1111 b (二进制数)
unsigned char a = 0x9f;
//1、分组
//若把a中的二进制位分成2个一组
//即bit0、bit1为第0组,bit2、bit3为第1组,
//  bit4、bit5为第2组,bit6、bit7为第3组
//  同理,第4~15的高位由于a=0x009f,所以都为0,也是按此方法排列
//2、对第1组的bit2、bit3清零
a &= ~(3<<2*1);//!!!2:以2个为一组,1:第1组,3:清零工具11(二进制)!!!
//括号中的3左移两位,(3<<2*1)得二进制数:0000 1100 b
//按位取反,~(3<<2*1)得1111 0011 b
//假如a中原来的值为二进制数: a = 1001 1111 b
//所得的数与a作”位与&”运算,a = (1001 1111 b)&(1111 0011 b),
//经过运算后,a的值 a=1001 0011 b
// a的第1组的bit2、bit3被清零,而其它位不变。

//上述(~(3<<2*1))中的(1)即为组编号;如清零第3组bit6、bit7此处应为3
//括号中的(2)为每组的位数,每组有2个二进制位;若分成4个一组,此处即为4
//括号中的(3)是组内所有位都为1时的值;若分成4个一组,此处即为二进制数“1111 b”

//例如对第2组bit4、bit5清零
a &= ~(3<<2*2);
对某几位进行赋值a |= (1<<2*2)

寄存器位先经过上面的清零操作后,再对某几位写入所需要的数值,且其它位不变

//先清零
//a = 1000 0011 b
//此时对清零后的第2组bit4、bit5设置成二进制数“01 b ”

a |= (1<<2*2);//1:赋值工具“01 b ”,2:以2个为一组,1:第1组
//a = 1001 0011 b,成功设置了第2组的值,其它组不变

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

实时监测、智能预警:电缆光纤测温系统|原理、应用与前景

实时监测、智能预警&#xff1a;电缆光纤测温系统|原理、应用与前景 电缆光纤测温系统&#xff0c;作为现代电力系统中不可或缺的一部分&#xff0c;以其独特的优势在电缆安全监控领域发挥着日益重要的作用。该系统利用光纤传感技术&#xff0c;实时监测电缆的运行温度&#x…

Qt常用基础控件总结—带边框的部件(QFrame和QLabel)

带边框的部件 框架控件QFrame类 QFrame类介绍 QFrame 类是带有边框的部件的基类,带边框部件的特点是有一个明显的边框,QFrame类就是用来实现边框的不同效果的(把这种效果称为边框样式),所有继承自 QFrame 的子类都可以使用 QFrame 类实现的效果。 部件通常是矩形的(其他…

Kithara和OpenCV (一)

Kithara使用 OpenCV 目录 Kithara使用 OpenCV简介需求和支持的环境构建 OpenCV 库使用 CMake 进行配置以与 Kithara 一起工作 使用 OpenCV 库设置项目运行 OpenCV 代码图像采集和 OpenCV自动并行化限制和局限性1.系统建议2.实时限制3.不支持的功能和缺失的功能4.显示 OpenCV 对…

【Perforce】QAC-分析时如何不应用某些规则

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 解决扫描项目时如何不应用某些规则进行分析。 2、 问题场景 对于一些建议性的MISRA规则&#xff0c;不想用于项目扫描&#xff0c;如何处理&#xff1f; 3、软硬件环境 1、软件版本&#xff1a;HelixQAC23.04 2…

中国科学院院士丁汉:人形机器人——机器人与人工智能结合的爆发点

工业制造是国民经济的重要支柱&#xff0c;是实现发展升级的国之重器。早在 2002 年&#xff0c;党的十六大就曾提出&#xff0c;坚持以信息化带动工业化&#xff0c;以工业化促进信息化&#xff0c;走出一条科技含量高、经济效益好、资源消耗低、环境污染少、人力资源优势得到…

24年,计算机仍然是最热门的专业?!

大家好&#xff0c;我是程序员鱼皮。最近很多高考完的朋友开始进入了填志愿选专业的时期。出于好奇&#xff0c;我也在网上了解了一下今年的热门专业和就业情况&#xff0c;结果并没有出乎我的意料&#xff0c;对于很多省份&#xff0c;计算机科学与技术依然是最热门的专业&…

fastadmin 各种开发技巧,问题总合集,持续跟新中....

使用 搜索的使用 自定义按钮 需改后的代码 {field: operate, title: __(Operate), table: table,buttons: [{name: detail, text: 详情, title: 详情, icon: fa fa-list, classname: btn btn-xs btn-primary btn-dialog, url: version/detail},{name: edit, text: 编辑我, …

班级录取查询系统如何制作

在教育的长河中&#xff0c;我们每位老师都曾面临过这样一个问题&#xff1a;如何高效、准确地完成班级录取查询的任务&#xff1f;记得在以往&#xff0c;每当新学期伊始&#xff0c;我们不得不手忙脚乱地整理学生名单&#xff0c;然后逐一通知他们所在的班级。这个过程不仅耗…

【机器学习】特征选择:精炼数据,提升模型效能

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 特征选择&#xff1a;精炼数据&#xff0c;提升模型效能引言为何进行特征选择&a…

windows server安全设置,多次登录密码错误锁定

河北瑾航科技有限公司推荐&#xff0c;www.jinhangsmart.top 按快捷键【winr】&#xff0c;在【运行】框中输入“gpedit.msc”后回车。 进入【本地组策略编辑器】后&#xff0c;展开至&#xff1a;计算机配置—Windows设置—安全设置—帐户策略—帐户锁定策略。 双击右侧…

一次性语音芯片——智能家居的新兴技术

一次性语音芯片&#xff0c;作为现代智能家居技术&#xff0c;正以其魅力和性能&#xff0c;逐渐渗透到我们日常生活的每一个角落。这些小巧而强大的芯片&#xff0c;不仅为智能家居设备赋予了“说话”的能力&#xff0c;更在提升用户体验、增强设备交互性方面发挥了举足轻重的…

GITLAB配置CI教程

一、gitlab runner下载安装 1、研发网下载安装包【172.20.191.53已经安装过了&#xff0c;不用再安装了&#xff0c;可以直接到第三步】 下载gitlab安装包 wget https://packages.gitlab.com/runner/gitlab-runner/packages/fedora/32/gitlab-runner-12.1.0-1.x86_64.rpm​ …

数字力量助西部职教全面提升——唯众品牌大数据、人工智能系列产品中标甘肃庆阳职院数字经济人才培养基地!

近日&#xff0c;唯众品牌凭借在大数据和人工智能领域深耕多年的技术积累和卓越产品&#xff0c;成功中标庆阳职业技术学院全国一体化算力网络国家枢纽节点数字经济人才培养基地项目&#xff0c;标志着唯众在助力西部职业教育与数字经济融合发展的新征程上迈出了坚实的一步。 …

线程交互现象

线程交互现象 小明对自家的狗子有个规定&#xff0c;就是在狗狗还没吃完的时候&#xff0c;可以继续给他加饭 不好的解决方式 狗狗感觉一千年没吃饭了&#xff0c;狼吞虎咽起来&#xff0c;最后饭只剩下最后一点点&#xff0c;吃饭线程中使用while循环判断是否是1&#xff0c;…

ST Smart Things Sentinel:一款针对复杂IoT协议的威胁检测工具

关于ST Smart Things Sentinel ST Smart Things Sentinel&#xff0c;简称ST&#xff0c;是一款功能强大的安全工具&#xff0c;广大研究人员可以使用该工具检测物联网 (IoT) 设备使用的复杂协议中的安全威胁。 在不断发展的联网设备领域&#xff0c;ST Smart Things Sentinel…

轮转数组(反转数组)的实现,看这篇就够了!!

一&#xff1a;题目 本题用数组为1 2 3 4 5 6 7 k3 来进行举例 理想结果为&#xff1a;5 6 7 1 2 3 4 二&#xff1a;思路 第一种方法&#xff1a; 用memcpy函数来实现 第一步&#xff1a;用malloc开辟一个新数组 第二步&#xff1a;将5 6 7 放进新数组 第三步&…

【JS|第21期】JavaScript模块化:深入解析三种文件暴露方式

日期:2024年7月6日 作者:Commas 签名:(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释:如果您觉得有所帮助,帮忙点个赞,也可以关注我,我们一起成长;如果有不对的地方,还望各位大佬不吝赐教,谢谢^ - ^ 1.01365 = 37.7834;0.99365 = 0.0255 1.02365 = 1377.4083…

台灯护眼是真的吗?台灯怎么选对眼睛好?一文带你读懂!

近视问题&#xff0c;这一现代社会的“视力杀手”&#xff0c;正悄然影响着越来越多的人群&#xff0c;尤其是青少年群体。长时间面对电子屏幕和书本&#xff0c;加上不正确的用眼习惯&#xff0c;使得视力下降成为普遍现象。在此背景下&#xff0c;一款优质的护眼台灯显得尤为…

【机器学习】Exam3

线性可分logistic逻辑回归 数据集点被分为了两边&#xff0c;根据课程学会归一化函数以及梯度下降即可。 使用线性模型。 import copyimport numpy as np import pandas as pd from matplotlib import pyplot as plt#归一化函数 def sigmoid(x):return 1 / (1 np.exp(-x))# …

基于Python的51job招聘数据采集与可视化项目实践

项目背景与目标 在当今竞争激烈的就业市场中&#xff0c;深入分析招聘信息对于求职者和企业都具有重要意义。基于Python的51job招聘数据采集与可视化项目旨在通过自动化手段高效获取大量招聘信息&#xff0c;并对这些数据进行深度分析和展示。 51job作为中国领先的招聘网站&…