一、概念性
什么是位带操作
位带操作就是可以单独对一个比特位读和写。在51单片机中,通过sbit
关键字来实现位定义。
对于STM32位带区和位带别名区的理解
STM32里没有这样的关键字,但可以通过位带别名区来实现。
图解 想要控制这些bit,就可以通过访问和控制位带别名区
的一个32bit的字(因为stm32单片机以32bit为单位操作最为高效),来控制位带区内的任意一位。
一个位带区的位对应位带别名区的四个字节(32bit)。
SRAM存储代码的区域。
二 、位带区和位带别名区的地址转换
- 地址关系
地址名称 | 地址 |
---|---|
外设位带区地址 | 0x4000 0000 ~ 0x4010 0000 |
外设位带别名区地址 | 0x4200 0000 ~ 0x43ff ffff |
SRAM 位带区地址 | 0x2000 0000 ~ 0x2010 0000 |
SRAM 位带别名区地址 | 0x2200 0000 ~ 0x23ff fff |
外设位带区和外设位带别名区同属于
片上外设
(一) 外设位带区和位带别名区
AliasAddr = 0x4200 0000 + (Addr-0x4000 0000)*8*4 + n*4
-
公式的解释
(Addr-0x4000 0000)得到的是相差几个字节
*8是因为一个字节8个位
*4是因为一个位在位带别名区内要膨胀成4个位
+ n*4 是因为某一个位号在位带别名区内要膨胀成4个位
(二) SRAM位带区和SRAM位带别名区
AliasAddr = 0x2200 0000 + (Addr-0x2000 0000)*8*4 + n*4
(三) 外设和SRAM统一转化处理公式
((addr & 0xF000 0000)+0X0200 0000 + ((addr&0x00FF FFFF)<<5)+(bitnum<<2))
- addr 要操作的位所在寄存器地址
- bit num 寄存器的第几位
三、实操
(一) 代码分析
#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_key.h"
#define GPIOB_ODR_Addr (GPIOB_BASE+0x0C)
#define PBout(n) *(unsigned int *)((GPIOB_ODR_Addr & 0xF0000000)+0X02000000+((GPIOB_ODR_Addr&0x00FFFFFF)<<5)+(n<<2))
int main(void)
{
LED_GPIO_Config(LED_R_GPIO_PIN);
while(1)
{
PBout(5) = 1;
//GPIO_ResetBits(LED_GPIO_PORT,LED_R_GPIO_PIN);
Delay(0xFFFFF);
PBout(5) = 0;
//GPIO_SetBits(LED_GPIO_PORT,LED_R_GPIO_PIN);
Delay(0xFFFFF);
}
}
-
位带公式
((addr & 0xF000 0000)+0X0200 0000 + ((addr&0x00FF FFFF)<<5)+(bitnum<<2))
-
位带宏定义
#define GPIOB_ODR_Addr (GPIOB_BASE+0x0C) #define PBout(n) *(unsigned int *)((GPIOB_ODR_Addr & 0xF0000000)+0X02000000+((GPIOB_ODR_Addr&0x00FFFFFF)<<5)+(n<<2))
- 位带公式,经编译后,运算得到的值只是一个数,芯片无法识别为地址。
- 要想识别为地址,需要将这个数强制类型转换为地址,加
(unsigned int *)
- 经过转换后,要用一个指针指向此地址,需要加``*`
-
变量
n
在PBout(n)
作为一个未知数的作用,#define
很强啊。 -
综上,实现位带操作,需要两个宏定义
- 一是某一外设地址=基地址+偏移地址
- 二是将Pxout(n)、Pxint(n)进行宏定义
梨梨笔记
时间戳:2020年8月4日 20:37:09
网友评论