嵌入式——寄存器映射原理与外设GPIO端口的初始化设置

一、STM32F103系列芯片的地址映射和寄存器映射原理

1.stm32系统构架

主系统由以下部分构成:

● 四个驱动单元:

Cortex™-M3 内核 ICode 总线(I-bus),DCode 总线(D-bus),和系统总线

(S-bus)

GP-DMA(通用 DMA)

·ICode总线

该总线将 Cortex™-M3 内核的指令总线与 Flash 指令接口相连接。指令预取在此总线上完成。

·DCode总线

该总线将 Cortex™-M3 内核的 DCode 总线与闪存存储器的数据接口相连接(常量加载和调试访问)。

·系统总线

此总线连接 Cortex™-M3 内核的系统总线(外设总线)到总线矩阵,总线矩阵协调着内核和 DMA 间的访问。

·DMA总线

此总线将 DMA 的 AHB 主控接口与总线矩阵相联,总线矩阵协调着 CPU 的DCode 和 DMA 到 SRAM、闪存和外设的访问。

·总线矩阵

此总线矩阵协调内核系统总线和 DMA 主控总线之间的访问仲裁。此仲裁利用轮换算法。此总线矩阵由三个驱动部件(CPU 的 DCode、系统总线和 DMA 总线)和三个被动部件(闪存存储器接口、SRAM 和 AHB2APB 桥)构成。AHB 外设通过总线矩阵与系统总线相连,允许 DMA 访问

● 三个被动单元

内部 SRAM

内部闪存存储器

AHB 到 APB 的桥(AHB2APBx),它连接所有的 APB 设备

内部FLASH
简单介绍在flash存储内容:我们写好的程序编译之后都是一条条指令(二进制代码),存放在 FLASH 中,我们常量或常变量C 语言中的 const 关键字修饰也存放在FLASH

内部SRAM
就是我们常说的电脑内存条,程序函数内部的局部变量和全局变量,堆(malloc分配)栈(局部变量)等的开销都是基于内部的SRAM。内核通过 DCode 总线来访问它

FSMC
FSMC 的英文全称是 Flexible static memory controller,叫灵活的静的存储器控制器,是 STM32F10xx 中一个很有特色的外设通过FSMC我们可以扩展内存,如外部的SRAM,NANDFLASH 和 NORFLASH。但有一点我们要注意的是,FSMC 只能扩展静态的内存,即名称里面的 S:static,不能是动态的内存,比如 SDRAM 就不能扩展。

AHB 到 APB 的桥
两个AHB/APB桥在AHB和2个APB总线间提供同步连接。APB1操作速度限于36MHz,APB2操作于全速(最高72MHz),上面挂载着 STM32 各种各样的特色外设。我们经常说的 GPIO、串口、I2C、SPI 这些外设就挂载在这两条总线上,这个是我们学习 STM32 的重点,就是要学会编程这些外设去驱动外部的各种设备。

这些都是通过一个多级的AHB总线构架相互连接的,如 图 1 所示:

系统结构

在这里插入图片描述

2.关于寄存器

寄存器是CPU内部用来存放数据的一些小型存储区域。用来暂时存放参与运算的数据和运算结果。其实寄存器就是一种常用的时序逻辑电路,但这种时序逻辑电路只包含存储电路。寄存器的存储电路是由锁存器或触发器构成的,因为一个锁存器或触发器能存储1位二进制数,所以由N个锁存器或触发器可以构成N位寄存器。寄存器是中央处理器内的组成部分。寄存器是有限存储容量的高速存储部件,它们可用来暂存指令、数据和位址。

·在计算机及其他计算系统中,寄存器是一种非常重要的、必不可少的数字电路构件,它通常由触发器(D触发器)组成,主要作用是用来暂时存放数码或指令。一个触发器可以存放一位二进制代码,若要存放N位二进制数码,则需用N个触发器。
·寄存器应具有接收数据、存放数据和输出数据的功能,它由触发器和门电路组成。只有得到“存入脉冲”(又称“存入指令”、“写入指令”)时,寄存器才能接收数据;在得到“读出”指令时,寄存器才将数据输出。
·寄存器存放数码的方式有并行和串行两种。并行方式是数码从各对应位输入端同时输入到寄存器中;串行方式是数码从一个输入端逐位输入到寄存器中。
·寄存器读出数码的方式也有并行和串行两种。在并行方式中,被读出的数码同时出现在各位的输出端上;在串行方式中,被读出的数码在一个输出端逐位出现。

3.地址映射和存储器映射原理

存储器本身没有地址,给存储器分配地址的过程叫存储器映射,那什么叫寄存器映射?寄存器到底是什么?

说到映射大家可能就会想到函数映射,脑海里会有一个画面:左边一个集合中的某个元素“射”出一条带箭头的直线指向右边的集合的某个元素。

其实外围设备的内存映射原理是一样的,只不过左边的集体变成了CPU,右边的集合变成了外围设备,那条带箭头的线就是连接CPU和外设地址引脚的地址总线。

存储器本身不具有地址信息,它的地址是由芯片厂商或用户分配,给存储器分配地址的过程就称为存储器映射
在这里插入图片描述

一般的外设为了加快处理速度都有自己的片内RAM(比如说显存,你也知道显存对显卡性能的重要性),分出去的地址空间也就与片内RAM物理连接起来,这样CPU就能像访问内存一样去访问外设的片内RAM,这也就是所谓的内存映射

在存储器的区域单元中,每一个单元对应不同的功能,当我们控制这些单元时就可以驱动外设工作。我们可以找到每个单元的起始地址,然后通过 C 语言指针的操作方式来访问这些单元,如果每次都是通过这种地址的方式来访问,不仅不好记忆还容易出错,这时我们可以根据每个单元功能的不同,以功能为名给这个内存单元取一个别名,这个别名就是我们经常说的寄存器,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。

二、GPIO端口的初始化设置的一般步骤

1.GPIO功能描述

每个 GPI/O 端口有两个 32 位配置寄存器(GPIOx_CRL,GPIOx_CRH),两个 32位数据寄存器(GPIOx_IDR,GPIOx_ODR),一个 32 位置位/复位寄存器(GPIOx_BSRR),一个 16 位复位寄存器(GPIOx_BRR)和一个 32 位锁定寄存器(GPIOx_LCKR)。
根据数据手册中列出的每个 I/O 端口的特定硬件特征, GPIO 端口的每个位可以由软件分别配置成多种模式。
− 输入浮空
− 输入上拉
− 输入下拉
− 模拟输入
− 开漏输出
− 推挽式输出
− 推挽式复用功能
− 开漏复用功能
每个 I/O 端口位可以自由编程,然而 I/0 端口寄存器必须按 32 位字被访问(不允许半字或字节访问)。GPIOx_BSRR 和 GPIOx_BRR 寄存器允许对任何 GPIO 寄存器的读/更改的独立访问;这样,在读和更改访问之间产生 IRQ 时不会发生危险。
一个I/O端口位的基本结构:

在这里插入图片描述

GPIO的八种工作模式

typedef enum
{
 GPIO_Mode_AIN = 0x0, // 模拟输入
 GPIO_Mode_IN_FLOATING = 0x04, // 浮空输入
 GPIO_Mode_IPD = 0x28, // 下拉输入
 GPIO_Mode_IPU = 0x48, // 上拉输入
 GPIO_Mode_Out_OD = 0x14, // 开漏输出
 GPIO_Mode_Out_PP = 0x10, // 推挽输出
 GPIO_Mode_AF_OD = 0x1C, // 复用开漏输出
 GPIO_Mode_AF_PP = 0x18 // 复用推挽输出
} GPIOMode_TypeDef;

2.初始化的一般步骤

第一步:使能GPIOx口的时钟
第二步:指明GPIOx口的哪一位,这一位的速度大小以及模式。
第三步:调用GPIOx口初始化函数,进行初始化。
第四步:调用GPIO-SetBits函数,进行相应为的置位。

3.实例

·对于单个GPIO口初始化

GPIO_InitTypeDef GPIO_InitStructure;
第一步:使能GPIOA的时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

第二步:设置GPIOA参数:输出OR输入,工作模式,端口翻转速率
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_6| GPIO_Pin_7| GPIO_Pin_8; //设定要操作的管脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置为推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // IO口速度为50MHz

第三步:调用GPIOA口初始化函数,进行初始化。
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA

第四步:调用GPIO-SetBits函数,进行相应为的置位。
GPIO_SetBits(GPIOA,GPIO_Pin_0); //输出高

·对于多个GPIO口初始化

GPIO_InitTypeDef GPIO_InitStructure;
第一步:使能GPIOA,GPIOE的时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);

第二步:设置GPIOA,GPIOE参数:输出OR输入,工作模式,端口翻转速率
第三步:调用GPIOA口初始化函数,进行初始化。
第四步:调用GPIO-SetBits函数,进行相应为的置位。

把第二、三、四步合并分别设置GPIOA和GPIOE
先设置GPIOA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 第四个口,PA4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置为推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // IO口速度为50MHz
GPIO_Init(GPIOA,&GPIO-InitST); //根据设定参数初始化GPIOA
GPIO_SetBits(GPIOA,GPIO_Pin_4); //输出高

再设置GPIOE
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; // 第三个口,PE3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置为推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // IO口速度为50MHz
GPIO_Init(GPIOE,&GPIO-InitST); //根据设定参数初始化GPIOE
GPIO_SetBits(GPIOE,GPIO_Pin_3); //输出高

三、总结

1.内部寄存器和外设寄存器的对比

内存:内存数据库将数据完全加载到内存中进行处理,不需要直接与外部数据源交互。数据存储在RAM中,提供了非常快速的读写操作。

高性能:由于数据直接存储在内存中,访问速度非常快。
较低的延迟:无需与外部数据源交互,数据直接在内存中进行操作,因此响应时间较短。
实时性:由于数据存储在内存中,可以实时处理和更新数据。

外设:外部数据指的是使用传统的文件、数据库或其他数据源进行存储和访问的数据。

持久性:外部数据存储在持久化介质(如磁盘)上,即使应用程序停止或计算机重新启动,数据也不会丢失。
可扩展性:外部数据通常可以更好地扩展到大规模数据集。
持久化:可以对数据进行备份和还原。

2.STM32与51单片机的对比

STM32单片机采用了Cortex-M系列的处理器架构,而51单片机则采用了传统的8位处理器架构。Cortex-M系列的处理器具有更高的性能和更低的功耗。

由于采用不同的处理器架构,STM32单片机具有更高的运行速度和更好的性能,可以运行更复杂的任务。而51单片机的性能较低,只适合一些简单的任务。

STM32单片机采用闪存来存储程序,而51单片机则使用EPROM或OTPROM。闪存具有更大的存储容量和更高的读写速度。

STM32单片机具有更多的外设接口,包括USB、CAN和以太网等。而51单片机的接口较少,只能支持一些基本的外设。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值