STM32的位带操作分析

8051单片机可以直接对某一位IO进行读写操作,而Cortex-M3的位带操作是8051位寻址区的加强版。使用位带操作后,可以使用普通的加载/存储指令对单一的比特进行读写操作。

一、相关概念。

位带区:支持位带操作的地址区。

位带别名区:对别名地址的访问最终作用到位带区的访问上。位带别名区对位带区的访问有个地址映射过程。

二、位带操作的原理

位带操作的最终目的是想对位带区的比特位进行独立的读写操作。但它是通过对位带别名区的操作来实现的。

具体过程如下:

对位带别名区进行读写访问,位带别名区通过地址映射关系映射到相应的位带区,对位带区进行原始比特的读写操作。

三、地址映射

上面对位带操作进行了简单的介绍,那么哪些地址支持位带操作?它们对应的位带别名区地址又是多少?两者间的地址映射关系又是怎么样的?

1、支持位带操作的地址

Cortex-M3有两个区支持位带操作。这两个区除了像普通的RAM一样使用外,还可以通过位带别名区进行操作。这两个区(位带区)分别是:

SRAM区中的最低1MB:0x2000 0000 - 0x200F FFFF

片上外设去中的最低1MB:0x4000 0000 - 0x400F FFFF

这两个位带区对应的位带别名区是:

SRAM区中的最低1MB的位带区对应的位带别名区:

片上外设去中的最低1MB的位带区对应的位带别名区:

2、位带区与位带别名区的地址映射关系

位带别名区把位带区的每一个比特位膨胀成32位的字,即位带区的每一个比特位对应位带别名区中一个4个字节大小的地址。

下图示例SRAM区中的最低1MB的位带区与位带别名区的膨胀对应关系:

计算公式:

对于SRAM位带区的某个比特,记它所在字节地址为A,比特位序号为n(0<=n<=7),则该比特位对应的位带别名区的地址为:

对于片上外设位带区的某个比特,记它所在字节地址为A,比特位序号为n(0<=n<=7),则该比特位对应的位带别名区的地址为:

说明:“*4”表示一个字为4个字节,“*8”表示一个字节中有8个比特。

四、读写操作的机制

在位带区中,虽然每个比特位都映射到别名区的一个字,但别名区的字只有LSB(最低位有效)有效,所以读写操作是对别名区字的LSB进行读写,LSB的数值是0或1.

1、读流程:

举例子:

读取SRAM地址0x2000 0000 的第二位的值:

2、写流程:读、改、写

举例子:

将SRAM地址0x2000 0000 的第二位的值置1:

五、位带操作编程实现

在C编译器中并没有直接支持位带操作,比如,C编译器并不知道同一块内存可以用不同的地址来访问,也不知道对位带别名区的访问只对LSB有效。欲在C中使用位带操作,最简单的做法时#define一个位带别名区的地址。

1、位带操作的宏定义

为了简化位带操作,我们可以建议一个把”位带地址+位序号“转换为别名地址的宏,再建立一个把别名地址转换为指针类型的宏:

  1. #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) /* 把”位带地址+位序号“转换为别名地址的宏 */

  2. #define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) /* 把别名地址转换为指针类型的宏 */

  3. #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) /* 某地址某一位的位带操作的宏 */

2、举个例子

下面以STM32F407的GPIOA->ODR寄存器(地址为0x40020014)为例,通过位带操作进行读写,并与传统方式读写比较,并通过串口将信息发送到控制台显示。代码如下:

头文件定义:

  1. #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))

  2. #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))

  3. #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))

  4. //IO口地址映射

  5. #define GPIOA_ODR_Addr (GPIOA_BASE+20) //0x40020014

  6. #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n)

main函数:

  1. int main(void)

  2. {

  3. u8 Temp;

  4. u16 Data;

  5. Data = 0;

  6. Stm32_Clock_Init(336,8,2,7);//初始化时钟为 168Mhz

  7. delay_init(168); //初始化延时函数

  8. uart_init(84,115200); //串口初始化为 115200

  9. printf("init finished\r\n");

  10. GPIOA->ODR = 0xffff; /* 传统方式写:将GPIOA->ODR各个位写1 */

  11. printf("Tratidional operate: GPIOA->ODR[0x%x]:0x%x\r\n", &GPIOA->ODR, GPIOA->ODR);

  12. GPIOA->ODR = 0x0; /* 将GPIOA->ODR清零 */

  13. printf("Clear GPIOA->ODR: GPIOA->ODR[0x%x]:0x%x\r\n", &GPIOA->ODR, GPIOA->ODR);

  14. for(Temp = 0; Temp < 16; Temp++)

  15. {

  16. PAout(Temp) = 1; /* 位带操作写:通过位带别名区写GPIOA->ODR每一位为1 */

  17. }

  18. printf("Bit-band write: GPIOA->ODR[0x%x]:0x%x\r\n", &GPIOA->ODR, GPIOA->ODR); /* 可以看到位带操作写后,GPIOA->ODR各位的值 */

  19. for(Temp = 0; Temp < 16; Temp++)

  20. {

  21. Data |= (PAout(Temp) << Temp); /* 位带操作读:通过位带别名区读GPIOA->ODR每一位的值,并存在Data中 */

  22. }

  23. printf("Bit-band read: GPIOA->ODR[0x%x]:0x%x\r\n", &GPIOA->ODR, Data); /* 可以看到位带操作读后,GPIOA->ODR各个比特位对应的别名区的值 */

  24. while(1)

  25. {

  26. }

  27. return 1;

  28. }

串口打印的信息:

STM32:位带操作分析相关推荐

  1. STM32位带区和位带别名区的浅谈

    1.首先谈下为什么要使用位带? 在学习51单片机时就已经使用过位操作,比如使用sbit对单片机IO口的定义,但是STM32中并没有这类关键字,而是通过访问位带别名区来实现,即通过将每个比特位膨胀成一个 ...

  2. STM32位带操作实现过程解析

    编辑这篇文档时候,听说相关的解析过程在<Cortex-M3权威指南>里有详细讲解. 前几日被一个跑马灯语句勾引 LED1=!LED1; 于是深入探究一下这句话的实现过程. #include ...

  3. STM32 位带应用

    Cortex-M3 支持了位操作后,可以使用普通的加载/存储指令来对单一的比特进行读写. 在 CM3  支持的位带中,有两个区中实现了位带. 其中一个是 SRAM区的最低 1MB 范围, 0x2000 ...

  4. 【STM32】标准库与HAL库对照学习教程六--位带操作

    [STM32]标准库与HAL库对照学习教程六--位带操作 一.前言 二.准备工作 三.位带介绍 1.位带操作 2.STM32位带及位带别名区域 四.位带区与位带别名区地址转换 五.GPIO的位带操作 ...

  5. STM32 进阶教程 8 - 位带操作

    前言 有过51单片机开发经历的朋友应该都对51的IO口或一些特殊寄存器可以直接按位操作的方式不陌生吧,那么在stm32中有没有类似的操作呢,答案是肯定的,本节将给大家介绍如何在STM32中实现位带操作 ...

  6. 【STM32】位带原理分析和应用

    00. 目录 文章目录 00. 目录 01. 位带概述 02. 位带操作 03. 位带C语言实现 04. 应用示例一 05. 应用示例二 06. 附录 07. 声明 01. 位带概述 位带操作简单的说 ...

  7. STM32(五)------GPIO位带操作

    GPIO位带操作 介绍 位带简介 外设位带区 SRAM位带区 位带区和位带别名区地址转换 GPIO 位带操作 代码解析 GPIO 寄存器映射 GPIO位操作 主函数 介绍 位带简介 位操作就是可以单独 ...

  8. STM32学习——位带区的理解

    位带简介 位操作就是可以单独的对一个比特位读和写,类似与51中sbit定义的变量,stm32中通过访问位带别名区来实现位操作的功能 STM32中有两个地方实现了位带,一个是SRAM,一个是片上外设. ...

  9. STM32的位带操作

    1. 什么是位带操作? 学习 51 单片机的时候就使用过位操作,通过关键字 sbit 对单片机IO口进行位定义.但STM32没有这样的关键字,于是便要通过访问位带别名区的方式来实现.即:将每一位膨胀成 ...

最新文章

  1. 百度之星第一题竟然没过
  2. python type创建类_Python基于内置函数type创建新类型
  3. Linux命令 比较文件
  4. [系统安全] 四十四.APT系列(9)Metasploit技术之基础用法万字详解及防御机理
  5. Spring MVC:使用SimpleUrlHandlerMapping的一个简单例子
  6. mkdir -p命令
  7. Could not obtain connection metadata
  8. NAB展会新闻:微软和媒体娱乐合作伙伴在Windows Azure平台上发展数字供应链解决方案...
  9. github创建远程仓库
  10. 哈希表:如何利用好高效率查找的“利器”?
  11. Linux中grep详解
  12. Linux 就该这么学
  13. 【技术】客服服务开发
  14. python 全栈开发,Day113(方法和函数的区别,yield,反射)
  15. js转化base64
  16. 再战双十一,阿里这回真的“上天”了!
  17. OJ---腐烂的橘子
  18. iOS KVC和KVO
  19. Netty介绍与实战(三)之粘包拆包
  20. 我愿意做一辈子的程序员

热门文章

  1. 第15节 三个败家子(15)—— 总被死后累
  2. [转]JAVA 在main中访问内部类、方法等
  3. 图片上传预览 (URL.createObjectURL)
  4. 强制类型转换运算符—C++基础篇
  5. 常见顺口溜 / 歇后语
  6. Java语言程序设计(一)选择题
  7. postgresql授权和撤销
  8. ip和nmcli命令的的使用方法
  9. 【Python-3.5】绘制随机漫步图
  10. 解决Eclipse编译web项目失败问题