位带操作理解
1.概念理解
位带操作实际就是通过将寄存器的一个位(bit)映射到某一个区域的字(32位)上,这些区域的字已经由官方设定好,我们通过对这些字的操作就能够实现对寄存器的某个位操作。图像如下
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输出寄存器的地址,再找到对应位带别名区的地址,并定义一个带参函数如下:
代码:
#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 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步