为了能到远方,脚下的每一步都不能少.|

京多安

园龄:1年3个月粉丝:2关注:1

位带操作理解

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位,这样处理效率更高。

本文作者:manchestercity

本文链接:https://www.cnblogs.com/manchestercity/p/17843328.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   京多安  阅读(123)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起