零基础自学STM32-野火——GPIO复习篇——使用绝对地址操作GPIO

今天主要是复习一下。
结合野火的《零基础开发指南》名字没记住大概是这个
先放一张结构图
在这里插入图片描述

存储器映射(初学重点):
我们的片内外设比如:Flash,Sram,Fsmc,以及挂在AHB 总线上的外设,我们都需要知道他的地址来操作这些器件。而这些外设的地址都被分配在一个4g的内存空间里(4g的存储器,下文中的)。
为什么是4g的?
2的32次方就是4g-byte。
存储器映射
存储器本身不具有地址信息,它的地址是由芯片厂商或用户分配,给存储器分配地址的过程就称为存储器映射,具体见图存储器映射。如果给存储器再分配一个地址就叫存储器重映射。
在这里插入图片描述
注意看4g的存储空间分位8个部分,每部分都给分配了各自的起始地址和末尾的地址信息。每块占用512MByte
显然8*512=4096MByte 4096MByte/1024=4g
拿其中几个举个例子:
在这里插入图片描述
第一部分就包含了Flash
在这里插入图片描述
第二部分就包含了Sram我的板子买的霸道,也就是F103zet6 64k的SRAM
第三部分就是FSMC
在这里插入图片描述
我是初学,咱时不管这部分(用到啥学啥,你没那么好的记性和时间)
其余的暂时不列出来。

重点来了!!!!!!!
我们操作的主要部分时在BLOCK2
在这里插入图片描述
我们首先得明白,分配的这些地址首先他是连续的。这一点很重要。
那么BLOCK2包含了哪些??
在这里插入图片描述
眼神好的自己看
《STMF103X英文数据手册》
在这里插入图片描述
简言之,这部分详细的描述了我们的外设及其分配到的地址信息。(有大用)
在这里插入图片描述
以端口举例,详细的描述了各端口的起始地址和终止地址,同样也是连续的。可以数数看。
在这里插入图片描述
对于这8个块,主要看三块就可以,BLOCK0对应的FLASH,BLOCK1对应的SRAM,BLOCK2对应的片上外设。
我们先直接看BLOCK2部分
BLOCK2上有两个总线,AHB和APB,这两个总线主要区别在于其速度不同。
在这里插入图片描述
APB又被分为APB1和APB2
而APB2和AHB被称为高速总线,挂高速外设,APB1是低速总线,挂低低速外设。
寄存器的映射
在存储器 Block2 这块区域,设计的是片上外设,它们以四个字节为一个单元,共 32bit,每一个单元对应不同的功能,当我们控制这些单元时就可以驱动外设工作(实际就是每32个位也就是4个字节为一个寄存器,而每一个寄存器负责一个具体的功能。巧了我们的单片机正好就是32位的,他正好能一次处理32位的数据)。
我们可以找到每个单元的起始地址,然后通过 C 语言指针的操作方式来访问这些单元,如果每次都是通过这种地址的方式来访问,不仅不好记忆还容易出错,这时我们可以根据每个单元功能的不同,以功能为名给这个
内存单元取一个别名,这个别名就是我们经常说的寄存器,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。(了解一下,后面在代码中一下就能明白)。
比如:
我们找到 GPIOB 端口的输出数据寄存器 ODR 的地址是 0x40010C0C(至于这个地址如何找到可以先跳过,后面我们会有详细的讲解),ODR 寄存器是 32bit,低 16bit 有效,对应着 16 个外部 IO,写 0/1 对应的的 IO 则输出低/高电平。现在我们通过 C 语言指针的操作方式,让 GPIOB的 16 个 IO 都输出高电平。

操作寄存器的方法一:通过绝对地址访问内存单元

// GPIOB 端口全部输出 高电平
 *(unsigned int*)(0x4001 0C0C) = 0xFFFF;

简单解释一下
0x4001 0C0C是GPIOB的ODR寄存器的地址,先别管他怎么来的。只需要知道我们操作这个地址就可以控制寄存器对应的GPIO输出
只不过对于单片机来说这个地址是一个变量,是一个立即数,而不是地址。(这里我没太明白。上网查了一下,我的理解就是说这个只是个数据而无实际意义,我们将他给Int变量那么这个就是int型数据,把他给指针变量那他就是地址,如果不赋值给一个具体的变量类型那他就啥也不是)。
我们需要强制转化为地址才行,所以使用了(unsigned int),也就是说这个地址是一个32位无符号整型的指针(指针就是地址)。*
对于这个地址空间其存储了一个数据0xFFFF。(一定要懂)
说明一下0xFFFF,我们知道对于一个16进制数 来说,一个F对应的4位。那么4个F对应的正好就是16位,而我们的ODR寄存器也正好能够操作的就只有16位。(后面针对ODR寄存器讲解的时候能用到)
而unsigned int 是32位的,对于0x4001 0C0C 是够用的!

那么使用绝对地址访问寄存器的方式缺点就很明显,地址不好记啊,也不好写啊。
操作寄存器的方法二:通过寄存器别名的方式访问寄存器

// GPIOB 端口全部输出 高电平
 #define GPIOB_ODR (unsigned int*)(GPIOB_BASE+0x0C)
* GPIOB_ODR = 0xFF;

使用宏定义#define 给寄存器的地址重新命名为GPIOB_ODR
然后使用* 号去操作ODR的值
这就是基本的指针操作,不做解释对于(GPIOB_BASE+0x0C)暂时不必纠结。只需要知道他是寄存器ODR的地址。

上面通过寄存器别名访问寄存器更换好的写法是

// GPIOB 端口全部输出 高电平
 #define GPIOB_ODR  *(unsigned int*)(GPIOB_BASE+0x0C)//将* 号也封装在//宏定义里
 GPIOB_ODR = 0xff;   //直接操作即可

下面介绍STM32的外设地址映射
片上外设区分为三条总线AHB总线和APB1,APB2(APB1和APB2共同构成APB总线),根据外设速度的不同,不同总线挂载着不同的外设,APB1 挂载低速外设,APB2 和 AHB 挂载高速外设。
相应总线的最低地址我们称为该总线的基地址,总线基地址也是挂载在该总线上的首个外设的地址。(这句就很有用,记住要考)
其中 APB1 总线的地址最低,片上外设从这里开始,也叫外设基地址。

在这里插入图片描述
表格总线基地址 的“相对外设基地址偏移”即该总线地址与“片上外设”基地址 0x4000 0000 的差值。(这个差值就是相对总线基地址的偏移量)
这里还不够直观我重新描述一下(对比以下三张图)

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
您好!对于STM32GPIO输出实验,点亮三色LED,您可以按照以下步骤进行操作: 1. 首先,您需要在STM32的开发环境中创建一个新的工程。 2. 在工程中,您需要包含相应的头文件,如"stm32f10x.h"。 3. 接下来,配置相应的引脚为输出模式。假设红色LED连接到GPIOA的Pin0引脚,绿色LED连接到GPIOA的Pin1引脚,蓝色LED连接到GPIOA的Pin2引脚,您可以使用以下代码进行配置: ``` GPIO_InitTypeDef GPIO_InitStructure; // 使能GPIOA的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 配置红色LED引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置绿色LED引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置蓝色LED引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); ``` 4. 现在,您可以使用相应的寄存器来控制LED的点亮和熄灭。例如,要点亮红色LED,可以使用以下代码: ``` GPIO_SetBits(GPIOA, GPIO_Pin_0); // 将Pin0引脚置高,点亮红色LED ``` 要熄灭红色LED,可以使用以下代码: ``` GPIO_ResetBits(GPIOA, GPIO_Pin_0); // 将Pin0引脚置低,熄灭红色LED ``` 同样的方法,您可以控制绿色和蓝色LED的点亮和熄灭。 这就是点亮三色LED的基本步骤。希望对您有所帮助!如果您有任何其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值