高手经验!STM32中的位带(bit-band)操作

发布者:SereneMeadow最新更新时间:2018-11-20 来源: eefocus关键字:STM32  位带(bit-band)操作 手机看文章 扫描二维码
随时随地手机看文章

支持了位带操作后,可以使用普通的加载/存储指令来对单一的比特进行读写。在 CM3 中,有两个区中实现了位带。其中一个是 SRAM 区的最低 1MB 范围,第二个则是片内外设区的最低 1MB范围。这两个区中的地址除了可以像普通的 RAM 一样使用外,它们还都有自己的“位带别名区”,位带别名区把每个比特膨胀成一个 32 位的字。当你通过位带别名区访问这些字时,就可以达到访问原始比特的目的。


位带操作的概念其实 30 年前就有了,那还是8051 单片机开创的先河,如今,CM3 将此能力进化,这里的位带操作是 8051 位寻址区的威力大幅加强版。


CM3 使用如下术语来表示位带存储的相关地址:


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


位带别名:对别名地址的访问最终作用到位带区的访问上(这中途有一个地址映射过程)

 

在位带区中,每个比特都映射到别名地址区的一个字——这是只有 LSB 有效的字。当一个别名地址被访问时,会先把该地址变换成位带地址。对于读操作,读取位带地址中的一个字,再把需要的位右移到 LSB,并把 LSB 返回。对于写操作,把需要写的位左移至对应的位序号处,然后执行一个原子的“读-改-写”过程。

 

1.jpg 

2.jpg

4.png

 

支持位带操作的两个内存区的范围是:


0x2000_0000‐0x200F_FFFF(SRAM 区中的最低 1MB)

0x4000_0000‐0x400F_FFFF(片上外设区中的最低 1MB)


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


AliasAddr=0x22000000+((A-0x20000000)*8+n)*4=0x22000000+(A-0x20000000)*32+n*4


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


AliasAddr=0x42000000+((A-0x40000000)*8+n)*4=0x42000000+(A-0x40000000)*32+n*4

上式中,“*4”表示一个字为 4 个字节,“*8”表示一个字节中有 8 个比特。


这里再不嫌啰嗦地举一个例子:


1. 在地址 0x20000000 处写入 0x3355AACC


2. 读取地址0x22000008。本次读访问将读取 0x20000000,并提取比特 2,值为 1。


3. 往地址 0x22000008 处写 0。本次操作将被映射成对地址 0x20000000 的“读-改-写”操作(原子的),把比特2 清 0。


4. 现在再读取 0x20000000,将返回 0x3355AAC8(bit[2]已清零)。


位带别名区的字只有 LSB 有意义。另外,在访问位带别名区时,不管使用哪一种长度的数据传送指令(字/半字/字节),都把地址对齐到字的边界上,否则会产生不可预料的结果。


[cpp] view plain copy///////////////////////////////////////////////////////////////

//位带操作,实现51类似的GPIO控制功能

//具体实现思想,参考<>第五章(87页~92页).

//IO口操作宏定义

#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))

//IO口地址映射

#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C

#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C

#define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C

#define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C

#define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C

#define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C

#define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C

#define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808

#define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08

#define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008

#define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408

#define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808

#define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08

#define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08

//IO口操作,只对单一的IO口!

//确保n的值小于16!

#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出

#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入

#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出

#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入

#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出

#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入

#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出

#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入

#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出

#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入

#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出

#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入

#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出

#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入


关键字:STM32  位带(bit-band)操作 引用地址:高手经验!STM32中的位带(bit-band)操作

上一篇:STM32学习笔记之使用库函数驱动LED灯
下一篇:STM32中AHB总线、APB2总线、APB1总线这些是什么

推荐阅读最新更新时间:2024-03-16 16:17

STM32经典概述,纯干货
首先,在学习Cortex-M3时,我们必须要知道必要的缩略语。 整理如下:AMBA:先进单片机总线架构 ADK:AMBA设计套件AHB:先进高性能总线 AHB-AP:AHB访问端口APB:先进外设总线 ARM ARM:ARM架构参考手册ASIC:行业领域专用集成电路 ATB :先进跟踪总线BE8:字节不变式大端模式 CPI:每条指令的周期数DAP:调试访问端口 DSP:数字信号处理(器)DWT:数据观察点及跟踪 ETM:嵌入式跟踪宏单元FPB:闪存地址重载及断点 FSR:fault状态寄存器HTM:Core Sight AHB跟踪宏单元ICE:在线仿真器 IDE:集成开发环境IRQ:中断请求(通常是外中断请求)ISA:指令系统架构
[单片机]
<font color='red'>STM32</font>经典概述,纯干货
STM32初学笔记5之ADC(上)
自己单独编写了一个ADC的单独API接口文件,如下所示: =============================================================== ADC_Config.C =============================================================== /** ** 文件名称:ADC_Config.C ** 功能描述:ADC转换模块的配置 ** 硬件平台:ALIENTEK(STM32F103RBT6) ** 编译环境:Keil uversion4 IDE ** 库版本 :v3.5.0
[单片机]
<font color='red'>STM32</font>初学笔记5之ADC(上)
STM32:定时器中断与优先级
前言 利用HAL库开发实现功能:使用TIM2实现定时,每隔1秒实现双闪功能 一、基础知识 1、常见的定时器资源 1.系统滴答定时器 SysTick 集成在Cortex M3内核的定时器,主要目的是给RTOS提供时钟节拍做时间基准。比如HAL库函数中的HAL_Delay()就是基于这个定时器开发的。如果要做嵌入式Linux的相关项目,要和上位机进行通讯的话,这个函数就不能用了。 2.看门狗定时器 WatchDog 3.实时时钟 RTC 4.基本定时器 TIM6、TIM7 5.通用定时器 TIM2、TIM3、TIM4、TIM5 在基本定时器的基础上,实现输出比较、输入捕获、PWM生成、单脉冲模式输出等功能。这类定时
[单片机]
<font color='red'>STM32</font>:定时器中断与优先级
STM32 f103搭配LM386声音传感器实现简单音乐识别
1.前言 2019年12月初,有一个中国机器人技能大赛中的双足机器人比赛项目,意思是机器人识别音乐跳对应节奏的舞蹈,五首音乐随机抽三首歌曲,音乐停,机器人停。 新比赛,新项目,难度自然有,坑也不少。希望这篇文章能给大家带来一点帮助。废话不多说,进入正题。 2.效果 (健康歌)每100ms采样一次,歌曲前5秒内共测50次数据,重复12组 (卡路里) 重复7组 可以看出一首歌经过多次测值,其采样值数组呈现出有规律的特征;不同的歌曲的特征也有较好的区分度。达到了区分歌曲的效果。下面讲讲具体实现步骤。 3.思路 href= 做什么:识别不同音乐,识别声音有无。 href= 怎么做:a.利用传感器判断出音乐或声音
[单片机]
<font color='red'>STM32</font> f103搭配LM386声音传感器实现简单音乐识别
初学STM32及GPIO入门之流水灯
一.准备工作---建立一个keil工程 STEP1. 打开keil,选择project-new uvision project,建立一个LED工程 STEP2. 在工程文件保存的路径下新建以下文件夹,在官网上或其他渠道下载STM32的3.5版库,将inc 和scr文件夹放入fwlib中。将startup_stm32f10x_hd.s放入asm文件夹中。将库文件放入cmsis中。 STEP3. 在keil中分别新建 【startcode】【user】【fwlib】【cmsis】四个组,再按照下图所示将C文件加入组中。这里要注意的是组里面添加的都是汇编文件和C文件,头文件不需要添加。 STEP4. 为了更好的理清各项文
[单片机]
初学<font color='red'>STM32</font>及GPIO入门之流水灯
如何画出STM32系列单片机的原理图
关于STM32F1系列单片机的一个常识: 看上图得知,根据Flash存储器的大小,把STM32F1分为了4种类型,分别是“低密度”“中密度”“高密度”“超高密度”,然后还有一种“互联型”。我们使用的STM32F103VET6的FLASH大小是512K,所以属于“高密度”型的。 我们这次要做的,就是把单片机STM32F103VET6的原理图画出来。 画的时候,要看STM32F103的datasheet。这个datasheet可以在ST的官网上找到。记住,是数据手册,不是参考手册。ST的官网是支持中文的,方便英文不好的朋友浏览。 打开ST的官方网站,看上图第一个红色矩形框里面的路径,依次到这一页。然后点击“数据手册”: 文
[单片机]
如何画出<font color='red'>STM32</font>系列单片机的原理图
单片机之STM32 中的 assert_param 函数
我们在学STM32的时候函数assert_param出现的几率非常大,上网搜索一下,网上一般解释断言机制,做为程序开发调试阶段时使用。下面我就谈一下我对这些应用的看法,学习东西抱着知其然也要知其所以然。 4 断言机制函数assert_param 我们在分析库函数的时候,几乎每一个函数的原型有这个函数assert_param();下面以assert_param(IS_GPIO_ALL_PERIPH(GPIOx));为例说一下我的理解,函数的参数IS_GPIO_ALL_PERIPH(GPIOx),我们可以寻找到原型 #define IS_GPIO_ALL_PERIPH(PERIPH) (((*(uint32_t*)&(PERIPH))
[单片机]
单片机之<font color='red'>STM32</font> 中的 assert_param 函数
关于STM32存储的堆栈地址
由c/C++编译的程序占用的内存分为以下几个部分 1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。 3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。-程序结束后有系统释放 4、文字常量区—常量字符串就是放在这里的。程序结束后由系统释放 5、程序代码区—存放函数体的二进制代码。 STM32的地址
[单片机]
关于<font color='red'>STM32</font>存储的堆栈地址
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved