位带操作理解

1.概念理解

位带操作实际就是通过将寄存器的一个位(bit)映射到某一个区域的字(32位)上,这些区域的字已经由官方设定好,我们通过对这些字的操作就能够实现对寄存器的某个位操作。图像如下
image

stm32一个字有4个字节共32个位,膨胀之后为在别名区为4*8=32个字。所以接下来要做的就是根据位带区地址找到位带别名区的字地址。

以GPIOF—ODR寄存器的bit9为例,该寄存器地址为0x4002 1414,相对GPIO偏移量为0x21414,膨胀为字后的别名区地址为0x2141448=0x428280,所以在位别名区从0x42428280开始的32个字区域均是ODR寄存器膨胀,由于4个字节组成一个字,对于bit0偏移为0,bit9就是9*4,也即是0x24,所以最终的地址计算公式如下:

Addr = 0x4200 0000+(A - 0x4000 0000)48 +bit*4

其中A是寄存器地址。0x4200 0000是外设位带别名区起始地址。

将SRAM和片上外设结合起来公式如下:
Addr = (addr&0xF000 0000)+0x200 0000+(addr&0x00FF FFFF)<<5+(bit<<2)

2.代码实现

找到ODR输出寄存器的地址,再找到对应位带别名区的地址,并定义一个带参函数如下:
image
代码:

#define AddrB_ODR       (GPIOB_BASE+0x0C)
#define PBout(n)  *(unsigned int*)((AddrB_ODR & 0xF0000000)+0x2000000+((AddrB_ODR & 0x00FFFFFF)<<5)+(n<<2))

其中对地址应该强制类型转换为指针,再对指针进行操作。
主函数控制代码如下:


int main(void)
{
	GPIO_LED_Config();
	while(1)
	{
    //实现灯的闪烁
		PBout(0) = 1;
		Delay(0xFFFFF);
		PBout(0) = 0;
		Delay(0xFFFFF);
	}
}
void Delay(uint32_t count)
{		
	for(;count !=0;count--);
}

值得一提的是,尽管一个位bit膨胀为位带别名区的 一个字,但是这个字仅仅最低位有效。这么操作是因为stm32系统总线是32位,这样处理效率更高。

posted @ 2023-11-20 10:07  京多安  阅读(178)  评论(0)    收藏  举报