STM32位带操作

 还记得51独有位操作,以一位(BIT)为数据对象的操作?可以简单的将P1口的第2位独立操作。P1.2=0;P1.2=1 ; 既可以把P1口的第三个脚(BIT2)置0置1。

而现在STM32的位段、位带别名区就为了实现这样的功能。

1、 支持的对象有:SRAM 和 I/O外设空间。实现对这些地方的某一位的操作。  

     支持位带操作的两个内存区的范围是: // 0x2000_0000‐0x200F_FFFF(SRAM 区中的最低1MB) // 0x4000_0000‐0x400F_FFFF(片上外设区中的最低1MB

 

2、原理:在寻址空间(32位地址是 4GB )另一地方,取个别名区空间,从这地址开始处,每一个字(32BIT) 就对应SRAM或I/O的一位(BIT),1MB SRAM就 可以有32MB的对应别名区空间。

32位来表示1位?其实这样做作用是,我们对这个别名区空间开始某一字操作,置0或置1,就等于它对应的SRAM或I/O的地址的位的操作。这样的好处是一般操作要6条指令,而使用位带别名区只要

4条指令。并且它更小更快更安全。

 

3、举个栗子0X200000000对应的位带区就是 0X220000000;0X200000001对应的0X220000004 ;

 

4、实用性:这样是好可是实际中我们如果每一个操作都用这样来位带,那我写得写多久的宏定义。我们需要站在巨人的头上干点事,我们直接使用库文件来配合我们的定义

    对SRAM 位带区的某个比特,记它所在字节地址为A,位序号为位序号为n(0<=n<=7) 在别名区的地址为: 
        AliasAddr= 0x22000000 +((A‐0x20000000)*8+n)*4 =0x22000000+ (A‐0x20000000)*32 + n*4 

    对于片上外设位带区的某个比特,记它所在字节的地址为A,位序号为n(0<=n<=7),则该比特 在别名区的地址为: 
        AliasAddr= 0x42000000+((A‐0x40000000)*8+n)*4 =0x42000000+ (A‐0x40000000)*32 + n*4 
    上式中,“*4”表示一个字为4 个字节,“*8”表示一个字节中有8 个比特。

有了这东西是不是直接AliasAddr = 0;AliasAddr=1;就可以进行操作了;我们需要做的就是把SRAM 和 I/O外设空间的基地址A和这个地址开始的第几个位(n)就可以了,别的使用

 5、 比如STM32你需要像51一样操作IO,做三步:(STM32F103)

      第一步: 复制这段

#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))

    第二步:使用BIT_ADDR并实现基地址的宏定义

#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
#define GPIOA_IDR_Addr  (GPIOA_BASE+8)   //0x40010808

//这里面的GPIOA_BASE是库里面的调用就是GPIOA的地址0x40010800,则输入寄存器是在0x40010808,输出寄存器是在0x4001080C 

 

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

    第三步:使用它吧!!!

PAout(3) = 1;PAout(3) = 0;PAout(3) = ~PAout(3);

if(PAin(3)){....};

6、 正点原子STM32F407 在LED里的位带操作

posted @ 2021-04-21 15:19  温柔的熊  阅读(750)  评论(0编辑  收藏  举报