stm32位带操作

要点:找到需要带操作的寄存器的地址,并把它转换为位带别名区地址。

1. 什么是位带?

通过普通的加载、存储指令来对单一的比特进行读写。例如下面就可以对P0^1口进行置位和复位。

P0^1 = 1;
P0^1 = 0;

在stm32开发过程中,如果使用库函数开发可以不使用位带操作。可以使用如下代码:

GPIO_SetBits(GPIO_IIC,IIC_SCL_Pin);
GPIO_SetBits(GPIO_IIC,IIC_SDA_Pin);
2. 位带别名区

在CM3中有两个区实现了位带。一个是SRAM区的最低1MB范围(0x2000_0000‐0x200F_FFFF ),第二个则是片内外设区的最低1MB范围(0x4000_0000‐0x400F_FFFF)。
这两个区中的地址除了可以像普通的RAM一样使用外,它们还有自己的“位带别名区”,位带别名区把每个比特膨胀成一个32位的字。
当通过位带别名区访问这些字的时候,就可以达到访问原始比特的目的。
(此处详见《Cortex-M3权威指南》)

1 Byte = 8 bit
1 KB   = 1024 Byte
1 MB   = 1024 KB

位带区(1MB): 支持位带操作的地址区
位带别名区(32MB): 对别名地址的访问最终作用到位带区的访问上(注:这中途有一个地址映射过程 )

LSB:最低有效位
在位带区中,每个比特都映射到别名地址区的一个字(一个字包含4个字节,也就是32比特,32位)——这是只有LSB有效的字。
当一个别名地址被访问时,会先把该地址变换成位带地址。对于读操作,读取位带地址中的一个字,再把需要的位右移到LSB,并把LSB返回。对于写操作,把需要写的位左移至对应的位序号处,然后执行一个原子的“读-改-写”过程。

对 SRAM 位带区的某个比特,记它所在字节地址为 A,位序号为n(0<=n<=7),则该比特在别名区的地址为:

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

对于片上外设位带区:

AliasAddr = 0x42000000+((A-0x40000000)*8+n)*4 = 0x42000000+(A-0x20000000)*32+n*4

SRAM区中的位带地址映射

位带区等效的别名地址
0x20000000.00x22000000.0
0x20000000.10x22000004.0
0x20000000.20x22000008.0
0x20000000.310x2200007C.0
0x20000004.00x22000080.0

download

3. 工程实例
//将位带地址+序号转换为别名地址的宏。
//此处左移5就等价于乘于32,左移2就等价于乘于2.
#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))

#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C

#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808

#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出

#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入

//设置输入输出方向寄存器后给GPIOA的1口置位和复位只需要如下代码所示,这样再对IO操作是不是就很简单了。

PAout(1)=1;
PAout(1)=0;
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值