STM32入门系列-位带操作介绍

发布者:心若澄明最新更新时间:2019-07-12 来源: eefocus关键字:STM32  入门系列  位带操作 手机看文章 扫描二维码
随时随地手机看文章

向大家介绍 STM32F1 的位带操作,让 STM32 的位操作和 51 单片机的位操作一样简单。


位带操作


在学习 51 单片机的时候就使用过位操作,通过关键字 sbit 对单片机 IO 口进行位定义。但是 STM32 没有这样的关键字,而是通过访问位带别名区来实现。即将每个比特位膨胀成一个 32 位字,当访问这些字的时候就达到了访问比特的目的。比方说 BSRR 寄存器有 32 个位,那么可以映射到 32 个地址上,当我们去访问这 32 个地址就达到访问 32 个比特的目的。


STM32F1 中有两个区域支持位带操作,一个是 SRAM 区的最低 1MB 范围,一个是片内外设区的最低 1MB 范围(APB1、APB2、AHB 外设)。如下图所示:

在这里插入图片描述

从图中可知,SRAM 的最低 1MB 区域,地址范围是 0X2000 0000-0X200FFFFF。片内外设最低 1MB 区域,地址范围是 0X4000 0000-0X400F FFFF,在这个地址范围内包括了 APB1、APB2、AHB 总线上所有的外设寄存器。


在 SRAM 区中还有 32MB 空间,其地址范围是 0X2200 0000-0X23FF FFFF,它是 SRAM 的 1MB 位带区膨胀后的位带别名区,前面已经说过位带操作,要实现位操作即将每一位膨胀成一个 32 位的字,因此 SRAM 的 1MB 位带区就膨胀为 32MB的位带别名区,通过访问位带别名区就可以实现访问位带中每一位的目的。


片内外设区的 32MB 的空间也是一样的原理。 片内外设区的 32MB 地址范围是0X4200 0000-0X43FF FFFF。


通常我们使用位带操作都是在外设区,在外设区中应用比较多的也就是GPIO 外设,SRAM 区内很少使用位操作。


位带区与位带别名区地址转换


前面已经说过, 位带操作就是将位带区中的每一位膨胀成位带别名区中的一个 32 位的字,通过访问位带别名区中的字就实现了访问位带区中位的目的。因此我们就可以使用指针来访问位带别名区的地址, 从而实现访问位带区内位的目的。那么位带别名区与位带区地址是如何转换的,我们下面就来介绍下。


(1)外设位带别名区地址

对于片上外设位带区的某个比特,记它所在字节的地址为 A,位序号为 n,n值的范围是 0-7,则该比特在别名区的地址为:

AliasAddr=0x42000000+ (A-0x40000000)84 +n4

0x42000000 是外设位带别名区的起始地址,0x40000000 是外设位带区的起始地址,(A-0x40000000)表示该比特前面有多少个字节,一个字节有 8 位,所以8,一个位膨胀后是 4 个字节,所以4,n 表示该比特在 A 地址的序号,因为一个位经过膨胀后是四个字节,所以也4。


(2)SRAM 位带别名区地址

对于 SRAM 位带区的某个比特,记它所在字节的地址为 A,位序号为 n,n 值的范围是 0-7,则该比特在别名区的地址为:

AliasAddr= =0x22000000+ (A-0x20000000)84 +n4

0x22000000 是 SRAM 位带别名区的起始地址, 0x20000000 是 SRAM 位带区的起始地址,(A-0x20000000)表示该比特前面有多少个字节,一个字节有 8 位,所以8,一个位膨胀后是 4 个字节,所以4,n 表示该比特在 A 地址的序号,因为一个位经过膨胀后是四个字节,所以也4。


上面我们已经把外设位带别名区地址和 SRAM 位带别名区地址使用公式表示出来,为了操作方便,我们将这两个公式进行合并,通过一个宏来定义,并把位带地址和位序号作为这个宏定义的参数。公式如下:

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

addr & 0xF0000000 是为了区分我们操作的是 SRAM 还是外设,实际上就是获取最高位的值是 4 还是 2。如果操作的是外设,那么 addr & 0xF0000000 结果就是 0x40000000,后面+0x2000000 就等于 0X42000000,0X42000000 是外设别名区的起始地址。如果操作的是 SRAM,那么 addr & 0xF0000000 结果就是0x20000000,后面+0x2000000 就等于 0X22000000,0X22000000 是 SRAM 别名区的起始地址。


addr & 0x000FFFFF 屏蔽了高三位,相当于减去 0X20000000 或者

0X40000000,屏蔽高三位是因为 SRAM 和外设的位带区最高地址是 0X200F FFFF和 0X400F FFFF,SRAM 或者外设位带区上任意地址减去其对应的起始地址,总是低 5 位有效,所以这里屏蔽高 3 位就相当于减去了 0X20000000 或者0X40000000。<<5 相当于84, <<2 相当于*4,其作用在前面已经分析过。


最后就可以通过指针形式来操作这些位带别名区地址, 实现位带区对应位的操作。代码如下:

//把 addr 地址强制转换为 unsigned long 类型的指针

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

//把位带别名区内地址转换为指针 ,获取地址内的数据

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

这里说明下 volatile 关键字,volatile 提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有 volatile 关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。更详细的内容大家可以百度查找。


位带操作的优点


在 STM32 应用程序开发中虽然可以使用库函数操作外设, 但如果加上位操作就如虎添翼。想想 51 单片机内位操作的方便,就可以理解为什么要对 STM32 使用位操作。STM32 位操作优点非常多,我们这里就列举几个突出的:


(1)对于控制 GPIO 的输入和输出非常简单。

(2)操作串行接口芯片非常方便(DS130274HC595 等),如果采用库函数的话,那么这个时序编写就非常不方便。

(3)代码简洁,阅读方便。


GPIO位带操作


我们已经知道 STM32F1 支持的位带操作区有两个, 其中应用最多的还是外设位带区,在外设位带区中包含了 APB1、APB2 还有 AHB 总线上的所有外设寄存器,使用位带操作应用最多的外设还属 GPIO,通过位带操作控制 STM32 引脚输入与输出,因此我们就以 GPIO 中 IDR 和 ODR 这两个寄存器的位操作进行讲解。


根据《STM32F10x 中文参考手册》对应的 GPIO 寄存器章节中可以知道,IDR和 ODR 寄存器相对于 GPIO 基地址的偏移量是 8 和 12。所以可以通过宏定义实现这两个寄存器的地址映射,具体代码如下:


//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

从上述代码中可以看到有 GPIOx_BASE,这个也是一个宏,里面封装的是相应 GPIO 端口的基地址,在库函数中有定义。


获取寄存器的地址以后,就可以采用位操作的方法来操作 GPIO 的输入和输出,代码如下:

//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) //输入

上述代码中我们已经将 STM32F1 芯片的所有端口都进行了位定义封装, 假如要使用 PC0 管脚进行输出,那么就可以调用 PCout(n)宏,n 值即为 0。假如使用的是 PC0 管脚作为输入,那么就可以调用 PCin(n)宏,n 值即为 0。其他端口调用方法类似。



关键字:STM32  入门系列  位带操作 引用地址:STM32入门系列-位带操作介绍

上一篇:STM32F1学习-驱动led灯(位操作版本)
下一篇:Stm32位带操作分析-浅显易懂

推荐阅读最新更新时间:2024-11-09 13:28

十五年创新路:意法半导体举办首届STM32中国线上技术周
2022年是意法半导体STM32家族问世15周年。在全球疫情阻止人们面对面沟通交流的当下,7月18-22日,意法半导体举办首届暨2022年STM32中国线上技术周,庆祝与生态合作伙伴共同创新的十五载。 在这个为期五天的线上活动中,意法半导体总裁兼首席执行官Jean-Marc Chery、意法半导体执行副总裁、通用微控制器子产品部总经理Ricardo De Sa Earp、意法半导体执行副总裁、中国区市场营销负责人曹志平(Henry Cao) 将分别作主题演讲。同时,意法半导体和合作伙伴带来30多场在线研讨会、100多个展品视频演示。在在线研讨会后设有技术问答环节,参观者将有机会与我们的专家和工程师进行现场互动。 下面,
[单片机]
十五年创新路:意法半导体举办首届<font color='red'>STM32</font>中国线上技术周
STM32_ TIM输出PWM波形
前言 今天讲解“STM32F103 TIM输出PWM波形”,提供的软件工程支持最大输出18MHz的PWM波形,函数接口只有两个参数:频率Freq和 占空比Dutycycle。 定时器的功能很强大,今天讲解的PWM属于定时器中比较输出的功能,难度算一般吧(懂了的人觉得很简单),因为使用了比较的功能。 PWM在实际应用中特别广泛,可能在校的学生不是很了解,但对于很多工作的人来说PWM的应用基本上遍布整个电子化的时代。对于电子相关专业的学生来说,信号发生器都不陌生,信号发生器就是PWM典型的应用。 本文特点:1.提供讲解的软件工程; 2.图片代码比直接贴出源代码容易阅读。 本着免费分享的原则,将讲解的工程源代码分享给大家,还望看到的
[单片机]
STM32_ TIM输出PWM波形
STM32时钟问题(重点)
STM32上电默认时钟内部8MHZ,经过库函数SystemInit的初始化,设置成启用外部晶振模式,并设为系统时钟为PLL倍频后的时钟:72MHZ. * SYSCLK 72MHz * AHB 72MHz * PCLK1 36MHz * PCLK2 72MHz * PLL 72MHz 但是用户可以自己选择使用不同时钟,下面给出了几个函数。 可以配置成内部时钟或者外部时钟。 /* * 寄存器的方式设置系统时钟: * 输入PLL倍频因子,输入PLL的倍频值2—16倍频(注意:不同的芯片有不同的倍频因子) * HCLK = PLLCLK=SYSCLK=P2CLK=P1CLK*2=ADCCLK*2=TIMCLK=U
[单片机]
STM32 + ESP8266 + MQTT协议连接OneNet
一、环境介绍 单片机 采用: STM32 F103C8T6 上网方式:采用 ESP8266 ,也可以使用其他设备代替,只要支持TCP协议即可。比如:GSM模块、有线网卡等。 开发软件: keil 5 硬件 连接功能:ESP8266接在STM32的串口3上。通过AT指令与ESP8266进行 通信 。 注意:本篇文章没有贴ESP8266的底层 编程 代码,如果不会ESP8266底层编程,请看这里: https://blog.csdn.net/xiaolong1126626497/ar ti cle/det ai ls/107379554 如果需要了解ESP8266+MQTT协议连接阿里云 物联网 服务器请看这里:https:/
[单片机]
<font color='red'>STM32</font> + ESP8266 + MQTT协议连接OneNet
智能锁中用到的加解密以及STM32 Cryptolib
STM32加密库 STM32提供了加密库X-Crypto-lib对之前提到的三大类算法的支持,甚至包括一些近几年才出现的算法ChaCha20以及Poly。STM32加密库包括几乎所有的分组模式,例如ECB,CBC,GCM等等。 STM32加密库通过了美国密码算法认证体系认证,在实现上安全性得到了保证,也适合用在一些有认证需求的MCU产品上。 密码技术可以由软件实现,也可以由硬件加速。软件加密库可以运行在所有的STM32平台上。STM32特定型号有常用的算法加速,可以减轻内核负载,降低功耗。 除了STM32加密库,如果用户对认证等级要求不高,也可以采用一些第三方或者开源的加密实现。例如mbedTLS就包含了所有流行的加解
[单片机]
STM32之旅6——WWDG
WWDG是stm32f103的窗口看门狗,使用的时钟是APB1的时钟,在使用wwdg是被一个小问题困扰了很久——没有打开中断,无法喂狗,一直复位。 初始化完之后需要使能中断: __HAL_WWDG_ENABLE_IT(&hwwdg, WWDG_IT_EWI); 在中断回调函数中喂狗: void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg) { HAL_WWDG_Refresh(hwwdg); }
[单片机]
<font color='red'>STM32</font>之旅6——WWDG
STM32常见的串行通信接口
通信接口背景知识 设备之间通信的方式 一般情况下,设备之间的通信方式可以分成并行通信和串行通信两种。并行与串行通信的区别如下表所示。 串行通信的分类 1、按照数据传送方向,分为: 单工:数据传输只支持数据在一个方向上传输; 半双工:允许数据在两个方向上传输。但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;它不需要独立的接收端和发送端,两者可以合并一起使用一个端口。 全双工:允许数据同时在两个方向上传输。因此,全双工通信是两个单工通信方式的结合,需要独立的接收端和发送端。 2、按照通信方式,分为: 同步通信:带时钟同步信号传输。比如:SPI,IIC通信接口。 异步通信:不带时钟同步信号。比
[单片机]
<font color='red'>STM32</font>常见的串行通信接口
基于STM32单片机的简易电子琴设计(1)
1.1 系统功能 按照设计要求,本系统具有以下功能: 共有三个基本模式:电子琴模式、录音模式、播放器模式 电子琴模式:7个基本按键控制产生7种音调,功能键实现调节音阶和音量 录音模式:可分为录音和放音两个模块,录音状态下会记录弹奏的音调以及时间;放音模式调用音乐播放器某些模块,实现相同的功能。 音乐播放器模式:可以实现音乐的播放、暂停、切歌、调速、顺序播放、单曲循环、随机播放、以及进度条显示。 有两个全局按键中断,可控制模式切换和全局静音/暂停。 1.2 主要技术性能指标 基本按键:7个; 功能按键:6个; 全局中断按键:2个; 扬声器:1个; 扬声器功率:1w; LCD1602:1块; 主要模式:3个; 曲库:8首; 音
[单片机]
基于<font color='red'>STM32</font>单片机的简易电子琴设计(1)
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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