STM32位带区和位带别名区的浅谈

1.首先谈下为什么要使用位带?

在学习51单片机时就已经使用过位操作,比如使用sbit对单片机IO口的定义,但是STM32中并没有这类关键字,而是通过访问位带别名区来实现,即通过将每个比特位膨胀成一个32位字,当访问这些字的时候就达到了访问比特的目的。比方说BSRR寄存器有32个位,那么可以映射到32个地址上,当我们去访问这32个地址就达到访问32个比特的目的,也就是说我们可以通过位带轻松的去控制某一位。

2.存储单元和存储地址的相关概念

在计算机中最小的信息单位是bit,也就是一个二进制位,8个bit组成一个Byte,也就是字节。一个存储单元可以存储一个字节,也就是8个二进制位。计算机的存储器容量是以字节为最小单位来计算的,对于一个有128个存储单元的存储器,可以说它的容量为128字节。如果有一个1KB的存储器则它有1024个存储单元,它的编号为从0-1023。存储器被划分成了若干个存储单元,每个存储单元都是从0开始顺序编号,如一个存储器有128个存储单元,则它的编号就是从0-127。

存储地址一般用十六进制数表示,而每一个存储器地址中又存放着一组二进制(或十六进制)表示的数,通常称为该地址的内容。值得注意的是,内储单元的地址和地址中的内容两者是不一样的。前者是存储单元的编号,表示存储器总的一个位置,而后者表示这个位置里存放的数据。正如一个是房间号码,一个是房间里住的人一样。

存放一个机器字的存储单元,通常称为字存储单元,相应的单元地址叫字地址。而存放一个字节的单元,称为字节存储单元,相应的地址称为字节地址。如果计算机中可以编址的最小单元是字存储单元,则该计算机称为按字寻址的计算机。如果计算机中可编址的最小单位是字节,则该计算机称为按字节寻址的计算机。如果机器字长等于存储器单元的位数,一个机器字可以包含数个字节,所以一个存储单元也可以包含数个能够单独编址的字节地址。例如一个16位二进制的字存储单元可存放两个字节,可以按字地址寻址,也可以按字节地址寻址。当用字节地址寻址时,16位的存储单元占两个字节地址。(摘自百度百科)

以STM32来说,STM32是一个32位的微控制器,它是按字存储单元;每一个寄存器都是占用4个字节即32位,这点将在下面位带和位带别名地址换算的时候用到

3.Cortex-M3位带区和位带映射区对应关系

STM32位带及位带别名区域支持位带操作的区域是SRAM 区的最低1MB 范围(APB1/2,AHB1外设)和片内外设区的最低1MB范围。
图一
对于SRAM/GPIO位带区的某个比特(bit),记它所在的字节地址为A,位序号为n(0<=n<=7)(如果是GPIO则n<=16),则该比特在位带别名区中的地址为:

AliasAddr=0x22000000+((A-0x20000000)*8+n)*4

上式中‘8’表示每个字节中有8个比特,‘4’表示4个字节(因为CM3是32位机,机器字为4个字节)。

(A-0x20000000)表示一共用这么多个字节,(A-0x20000000)*8+n表示一共有这么多位,在别名区中,每个位占4个字节地址,故((A-0x20000000)*8+n)*4表示该位在别名区中的偏移字节地址。偏移地址加上基地址就是该比特在位带别名区中的地址
在这里插入图片描述

4.最后附上STM32F103的实现代码
#ifndef _BIT_BIND_H_
#define _BIT_BIND_H_

#include "stm32f10x.h"

 
//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C 
#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C 
#define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C 
#define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C 
#define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C 
#define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C    
#define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C    

#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 
#define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08 
#define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008 
#define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408 
#define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808 
#define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08 
#define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08 
 
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入



#endif

  • 11
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
STM32F407的位操作是指通过位别名域来对特定的位进行操作,以提高代码的执行效率和简化编程过程。 在STM32F407中,位别名域是一段特殊的内存域,用来映射特定位的地址,以此来实现对这些位的直接访问和修改。通过位操作,我们可以通过直接读取和写入一个位的别名地址来实现对该位的操作,而不需要进行位运算或移位操作。 位别名域的地址在内存映射中通常是高于SRAM的地址范围,所以它不会和其他数据冲突。在使用位操作时,首先需要确定要操作的位在内存中的位置,并计算其别名地址。然后,可以通过读取或写入该别名地址来操作这个位。 位操作的主要优势是提高代码的执行效率。因为在执行位操作时,可以直接换位别名地址的读写操作,从而避免了对位进行逐位运算的过程,大大节省了时间。此外,位操作还可以简化代码的书写,使代码更加清晰和易读。 需要注意的是,位操作只能在位可选操作的寄存器或内存位置上进行。对于不支持位操作的寄存器或内存位置,仍然需要使用位运算或移位操作。另外,由于位别名域的映射地址与SRAM相隔较远,所以在使用位操作时需要额外的地址计算,这也可能增加了代码的复杂性。 总而言之,STM32F407的位操作是一种通过位别名域来对特定位进行操作的方法。它可以提高代码执行效率和简化编程过程,但需要在位可选操作的寄存器或内存位置上进行,并需要进行额外的地址计算。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值