历史上的今天
返回首页

历史上的今天

今天是:2025年06月07日(星期六)

2018年06月07日 | STM32位带操作详解

2018-06-07 来源:eefocus

一. Cortex-M3存储器映射

存储区最开始的1GB空间分别为code(代码)区和SRAM区,Code区使用经过针对优化的I-Code总线来连接,同理,SRAM区使用D-Code总线连接,虽然SRAM也可以用来转载和执行代码,但这样做会使CPU不得不通过系统总线来取指令,产生额外CPU等待周期,因此在SRAM中运行代码会比代码区的片上Flash中运行要缓慢。

接下来的0.5GB存储空间是片上外设区,微控制器的所有用户设备的基地址都落在这个区域内,片上外设区和SRAM区的起始1MB区域可以用来使用位带技术实现位寻址,由于STM32所有SRAM和外设都位于这个区域,因此STM32所有存储区都可以用“字(Word)”或“位(bit)”为最小单位实现数据操作

早期的ARM7和ARM9处理器使用“&”,“|”指令来想、实现SRAM区域或者外设存储区进行位操作,这是一个“读”-> “修改” -> “写”的过程,因此为了实现单个位操作讲会耗费数个时钟周期,并增加了代码量

 

二.位带区域的意义

如何能像MCS51中位操作,sbit P1.0 = P1^0;   P1.1 = 1;于是STM的位段和位带别名区实现这个功能。可以操作SRM,外设I/O进行位操作,

STM32支持了位带操作(bit_band),有两个区中实现了位带。其中一个是SRAM 区的最低1MB 范围,第二个则是片内外设 区的最低1MB 范围。这两个区中的地址除了可以像普通的RAM 一样使用外,它们还都有自己的“位带别名区”,位带别名区  把每个比特扩展成一个32 位的字。 每个位扩展成一个32 位的字,就是把  1M  扩展为 32M , 
 于是:

           RAM地址 0X200000000(一个字节)扩展到8个32 位的字,它们是:(STM32中的SRAM依然是8位的,所以RAM中任一地址对应一个字节内容)
          0X220000000 ,0X220000004,0X220000008,0X22000000C,0X220000010,0X220000014, 0X220000018,0X22000001C

在 CM3 支持的位段中,有两个区中实现了位段。

其中一个是 SRAM 区的最低 1MB 范围, 0x20000000 ‐ 0x200FFFFF(SRAM 区中的最低 1MB);

第二个则是片内外设区的最低 1MB范围, 0x40000000 ‐ 0x400FFFFF(片上外设区中的最低 1MB)。

 

三.位带操作实现

Cortex?-M3存储器映像包括两个位段(bit-band)区。这两个位段区将别名存储器区中的每个字映射到位段存储器区的一个位,在别名存储区写入一个字具有对位段区的目标位执行读-改-写操作的相同效果。
在STM32F10xxx里,外设寄存器和SRAM都被映射到一个位段区里,这允许执行单一的位段的写和读操作。
下面的映射公式给出了别名区中的每个字是如何对应位带区的相应位的:
bit_word_addr = bit_band_base + (byte_offset x 32) + (bit_number × 4)

其中:
bit_word_addr是别名存储器区中字的地址,它映射到某个目标位。
bit_band_base是别名区的起始地址。
byte_offset是包含目标位的字节在位段里的序号
bit_number是目标位所在位置(0-31)

位带别名区地址 = 位带别名区基地址 + 字偏移地址
字偏移地址 = (字节相对位带区的偏移 << 5 ) +  (位数目 << 2)

例子一:
计算GPIOB的第8位在位带别名区的地址:
寄存器地址        = 0x40010c0c
设备位带区基地址  = 0x40000000
设备位带别名区    = 0x42000000
位带区的字节偏移量  = 0x400010c0c - 0x40000000 = 10c0c
字偏移地址        = (0x10c0c << 5)  + (8 << 2)
位带别名区地址    = 0x42000000 + 0x2181A0 = 0x422181A0

例子二:
下面的例子说明如何映射别名区中SRAM地址为0x20000300的字节中位2
0x22006008 = 0x22000000 + (0x300*32)  + (2*4);

 

C代码实现:

把“位带地址+位序号”转换别名地址宏 
  #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
  把该地址转换成一个指针 
  #define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
  MEM_ADDR(BITBAND( (u32)&CRCValue,1)) = 0x1;

注意:当你使用位段功能时,要访问的变量必须用 volatile 来定义。因为 C 编译器并不知道同一个比特可以有两个地址。所以就要通过 volatile,使得编译器每次都如实地把新数值写入存储器,而不再会出于优化的考虑 ,在中途使用寄存器来操作数据的复本,直到最后才把复本写回。

方法一:
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))

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

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

然后定义:#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C

最后操作:#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 ODR保存要输出的数据;IDR保存读入的数据

 

测试代码:

/*
 *   爱雨测试位带操作区 实验
 *   硬件接口: GPIOC9  ----   LED   
*   实验现象:  低电平亮
*/
#define MeM_Addr(addr)    *((volatile unsigned long *)(addr))

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

void main()
{
    RCC_Configuration();                                                        //System clocks configuration
    NVIC_Configuration();                                                       //NVIC configuration
    TIM2_Configuration();
    LED_Init();
    LED_Off();
    while (1)
    {
       //LED_Prompt();
       MeM_Addr(BITBAND(0x4001100C,9)) = 0;  // LED点亮
    }
}

 

方法二

#define __BITBAND__ __attribute__((bitband))

#define __BITBAND__ADDR(addr) __attribute__((at(addr)))

typedef struct

{

u32 a1 :1;

u32 a2 : 1;

} _STATE_FLAG __BITBAND__;

volatile _STATE_FLAG StateFlag __BITBAND__ADDR(0x20000000);

StateFlag.a1 = 1;

汇编代码比较:

 

方法三直接在 C/C++编译选项中加入“--bitband”,那么凡是结构体中的位变量都会使

用位带操作。

如果用这方法, C 文件中不用像方法二中介绍的这么麻烦。 可以直接按照普通的结构体进行

变量说明。

volatile struct

{

u32 a1 : 1;

u32 a2 : 1;

} StateFlag;

 

四. 位带区域局限性

要想使编译器支持位带操作,对代码是有要求的。只能使用在纯粹的结构体中,不能和 uinon、enum 混合使用。对结构体中的某个位有效,当结构体中的位是 2 位或以上,编译后还是按照“读-改-写”的顺序进行。

 

本文根据借鉴一下资料:

1> CortexM3技术参考手册.pdf

2> STM32中文参考手册_V10.pdf

3> STM32自学笔记 2012.pdf

4> MDK下Cortex-M3的位带操作.pdf

位操作文章:

http://blog.csdn.net/cy757/article/details/5816929


推荐阅读

史海拾趣

天二科技(EVER OHMS)公司的发展小趣事

天二科技始终将产品质量视为企业的生命线。为了不断提升产品品质,公司引进了先进的自动化设备和生产工艺,并建立了严格的质量控制体系。经过多年的努力,天二科技的产品质量得到了显著提升,并先后通过了ISO9001、TS16949等多项国际质量管理体系认证。这些认证的取得不仅证明了天二科技在产品品质方面的卓越表现,更为公司赢得了客户的信任和市场的认可。

Capar Components Corp公司的发展小趣事

随着国内市场的饱和,Capar Components Corp开始将目光投向国际市场。公司积极参加国际电子展会,与海外客户建立联系,拓展销售渠道。同时,公司还根据不同国家和地区的市场需求,调整产品结构和营销策略,逐步打开了国际市场的大门。如今,公司的产品已经远销欧美、东南亚等多个国家和地区,成为了国际电子市场上的一支重要力量。

Conflux公司的发展小趣事

随着公司业务的不断发展,Conflux开始寻求与其他电子行业企业的合作。通过与智能手机制造商的合作,Conflux成功将其区块链技术集成到了手机支付应用中,为用户提供了更加便捷、安全的支付体验。此外,Conflux还与多家电商平台达成战略合作,利用区块链技术优化交易流程,提高交易透明度。这些合作不仅拓展了Conflux的市场份额,也进一步提升了其在电子行业的影响力。

安普康(AMPCOM)公司的发展小趣事

随着业务的不断发展,安普康开始积极寻求市场拓展和战略合作的机会。公司在香港市场取得了显著的成绩后,决定进一步拓展内地市场。通过设立深圳安普康科技有限公司等分支机构,安普康逐步在内地市场建立了完善的销售网络和服务体系。同时,公司还与多家知名企业建立了长期合作关系,共同开拓市场、分享资源。这些合作不仅提升了安普康的市场地位,也为其未来的发展奠定了坚实的基础。

浙江东亚电子(DongYa)公司的发展小趣事

浙江东亚电子一直将品质管理作为公司发展的重要基石。公司建立了完善的质量管理体系,从原材料采购到产品制造、销售等各个环节都严格把关。此外,公司还积极参与行业标准和规范的制定工作,不断提升自身的品质管理水平。

博巨兴公司的发展小趣事

博巨兴公司一直注重技术研发和自主创新,近年来公司研发费用投入均占当年销售额的10%以上。凭借科学的管理手段和雄厚的技术力量,公司于2006年被认定为“深圳市软件企业”,2007年被认定为“深圳市高新技术企业”,2011年更是荣获“国家高新技术企业”称号。这些荣誉的获得不仅是对公司技术实力的认可,也为公司的进一步发展奠定了坚实基础。

问答坊 | AI 解惑

方波有源滤波器谐波电流检测的一种新方法

方波有源滤波器谐波电流检测的一种新方法 随着电力电子技术的发展,电力电子装置的应用日益广泛,引起的电网谐波污染也日趋严重[1][2]。因此,对电网谐波采取有效的抑制并对无功功率进行动态补偿已成为重要的研究方向。 采用电力滤波装置就近吸收谐 ...…

查看全部问答>

2007年全国大学生电子设计竞赛索尼杯奖.pdf

2007年全国大学生电子设计竞赛索尼杯奖.pdf…

查看全部问答>

USB开发资料

USB开发使用的一些资料~~…

查看全部问答>

关于DSP 与FPGA 数据线连接的问题

用DSP和FPGA连接,发现FPGA配置后,DSP的数据线某些位被拉低了,不配置FPGA就没问题。这就是典型的DSP与FPGA间数据总线没处理好。FPGA的数据都要通过三态门接到数据总线上,输出,输入受DSP的控制。这儿还有一个问题就是关于FPGA的IO双向操作的问题 ...…

查看全部问答>

LM3S8962试用前的准备—KEIL软件破解

快拿到论坛的试用LM3S8962开发板了,心里很激动,搜集了好多资料,准备好好学习TI M3。俗话说工欲善其事必先利其器,好的开发工具能提高开发效率,由于学51时就用KEIL软件,所以对KEIL软件情有独钟,现在开始学习ARM了,还是选择KEIL,看到大家写了 ...…

查看全部问答>

ISE11.1上的工程稍作改动工程就运行通不过是什么原因

在ISE11.1上建立的工程,管脚位置稍做改动,工程运行要么运行通不过,报错:时序无法满足或者有信号线无法布线,即使运行通过了时序也有几个不满足,在改动之前是没有时序错误的,管脚位置变后,就不行了,这是怎么回事呀?感觉工程好像很脆弱,稍 ...…

查看全部问答>

求一LM3S811的SPI使用的例程

我现在学习LM3S811,但不知道如何使用SPI,想问有没有对SPI的使用比较熟悉的坛友,求指教,谢谢。…

查看全部问答>

[原创]基于AD9858的复杂波形产生器

  【制作日期】2005 啥时候了?  【板层数】 4【描述】    ADI公司推出频率合成器AD9858,它是第一个具有1GSPS(千兆次取样/秒)直接数字合成器(DDS),10位D/A转换器,快速频率跳跃和精细调谐分辨率功能的单片解决方案。AD9 ...…

查看全部问答>

dsp 编译出现的 error

TI6763:   error:: system error, can\'t open file \'w.obj\' for input: No such file or dire   请问这是为什么啊?…

查看全部问答>

求8*8点阵电路、显示程序

要求:①用8*8的LED点阵作为字符显示器       ②显示全部的大写英文字符       ③显示方式:依次显示和连续显示。         显示频率可调       ④ ...…

查看全部问答>