STM32位带操作详细介绍

发布者:delta14最新更新时间:2021-10-19 来源: eefocus关键字:STM32  位带操作  详细介绍 手机看文章 扫描二维码
随时随地手机看文章

前言

//在STM32中,如果我们要使PB0端口输出低电平,可以用如下语句

GPIOB->ODR |= 0<<0;

//在51单片机中我们是这样的

P0 = 0xff;   //总线操作

//还有一种方法

sbit LED1 = P0^0;

LED1 = 0;//位操作


在STM32中能不能实现位操作呢,当然是可以的,这种方法我们叫做位带操作。位操作就是可以单独的对一个比特位读和写。


1.位带简介

在STM32中,有两个地方实现了位带,一个是 SRAM 区的最低 1MB 空间,另一个是外设区最低 1MB 空间。这两个 1MB 的空间除了可以像正常的 RAM 一样操作外,他们还有自己的位带别名区,位带别名区把这 1MB 的空间的每一个位膨胀成一个 32 位的字,当访问位带别名区的这些字时,就可以达到访问位带区某个比特位的目的。


比如位带区:外设区,这其中的一个位,可以在位带别名区重新找到4个字节的地址,也就是32位,来重新命名,而这32位,只有最低位有效。所以空间利用不是很充足,但是提供了方便。


例子:

PB的ODR寄存器地址为0x40010C0C,假设我们就操作PB0,即操作ODR寄存器第0位,那么这个位新的地址Addr= =0x42000000+ (0x40010C0C-0x40000000)84 +0*4。


给这个地址命名为PBout(0);


2.计算公式

外设区:

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


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


SRAM区:

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


公式分析同上


统一公式

为了方便操作,我们可以把这两个公式合并成一个公式,把“位带地址+位序号”转

换成别名区地址统一成一个宏。


 // 把“位带地址+位序号”转换成别名地址的宏

2 #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x02000000+((addr & 0x00FFFFFF)<<5)+(bitnum<<2))


addr & 0xF0000000 是为了区别 SRAM 还是外设,实际效果就是取出 4 或者 2,如果是外设,则取出的是 4, +0X02000000 之后就等于 0X42000000, 0X42000000 是外设别名区的起始地址。如果是 SRAM,则取出的是 2, +0X02000000 之后就等于 0X22000000,0X22000000 是 SRAM 别名区的起始地址。

addr & 0x00FFFFFF 屏蔽了高三位,相当于减去 0X20000000 或者 0X40000000,但是为什么是屏蔽高三位?因为外设的最高地址是: 0X2010 0000, 跟起始地址 0X20000000 相减的时候,总是低 5 位才有效,所以干脆就把高三位屏蔽掉来达到减去起始地址的效果,具体屏蔽掉多少位跟最高地址有关。 SRAM 同理分析即可。 <<5 相当于84, <<2 相当于*4,这两个我们在上面分析过。


最后我们就可以通过指针的形式操作这些位带别名区地址,最终实现位带区的比特位操作。


// 把一个地址转换成一个指针

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

// 把位带别名区地址转换成指针

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


3.GPIO位带实现

// 把“位带地址+位序号”转换成别名地址的宏

#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x02000000+((addr & 0x00FFFFFF)<<5)+(bitnum<<2))


// 把一个地址转换成一个指针

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

// 把位带别名区地址转换成指针

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


//GPIO ODR 和 IDR 寄存器地址映射

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


//单独操作 GPIO 的某一个 IO 口, n(0,1,2...16),n 表示具体是哪一个 IO 口

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


这样就可以使用PBout(0),相比之下还是很方便的。

关键字:STM32  位带操作  详细介绍 引用地址:STM32位带操作详细介绍

上一篇:STM32位带操作-详解-计算过程
下一篇:STM32 - GPIO 的位带操作

推荐阅读最新更新时间:2024-11-16 22:51

STM32 生成7路PWM波
STM32的定时器中的两个高级定时器TIM1与TIM8可以生成7路PWM波,因为他们分别有7路引脚通道: 通道1 TIM1_CH1 PA8 通道1 TIM1_CH1N PB13 通道2 TIM1_CH2 PA9 通道2 TIM1_CH2N PB14 通道3 TIM1_CH3 PA10 通道3 TIM1_CH3N PB15 通道4 TIM1_CH4 PA11 通道1 TIM8_CH1 PC6 通道1 TIM8_CH1N PA7
[单片机]
零基础入门stm32知识学习的先后顺序
  这里大概的罗列了一些学习STM32的内容,以及学习顺序。如果是新手的话,建议边看中文手册和学习视频(一般都看原子的,视频的话百度就可以了,如果实在是找不到的话,我给大家推荐一个网站:21ic公开课,里面很多免费的基础学习视频,非常适合广大的学生);如果是已经入门的,个人建议自己做一个项目,不论项目大小,当然里面会涉及到自己已经学习过的,或者是自己正在学习的,亦或是自己想来想要学习的,一边学习,一边做项目。这样好处颇多,大家慢慢去体会。下面就是本人所罗列的一些STM32的内容,不需要看懂,只需要记住即可,在你以后慢慢深入的过程中,就会了解到的:   1、STM32基本配置(运行环境、编译器、下载器、板子等)。   2、G
[单片机]
STM32(RFID)阶段一:添加串口USART2,修改中断接收协议
因学校比赛原因接触到RFID技术,并结合STM32单片机开发一卡通系统。由于需要和RFID读写器通信,以及上位机软件通信,所以添加USART2串口,并根据RFID数据包改写中断接收协议。资料支持:《不完全手册》《中文手册》端口通用与复用,APB1外设,串口寄存器,中断配置 阶段一:demo程序功能:通过串口USART2接收数据包,并把数据再发回去。RFID型号M3650A-HA 数据包第二个数据为数据包的长度,使用str接收长度,USART_RX_STA bit15置1 表示接收结束。 上代码 void uart_init(u32 bound){ GPIO_InitTypeDef GPIO_InitStructure
[单片机]
STM32启动文件解析
当前的嵌入式应用程序开发过程里,并且C语言成为了绝大部分场合的最佳选择。如此一来main函数似乎成为了理所当然的起点——因为C程序往往从main函数开始执行。但一个经常会被忽略的问题是:微控制器(单片机)上电后,是如何寻找到并执行main函数的呢?很显然微控制器无法从硬件上定位main函数的入口地址,因为使用C语言作为开发语言后,变量/函数的地址便由编译器在编译时自行分配,这样一来main函数的入口地址在微控制器的内部存储空间中不再是绝对不变的。相信读者都可以回答这个问题,答案也许大同小异,但肯定都有个关键词,叫“启动文件”,用英文单词来描述是“Bootloader”。 无论性能高下,结构简繁,价格贵贱,每一种微控制器(处理器)都
[单片机]
<font color='red'>STM32</font>启动文件解析
STM32 LL库为什么比HAL库高效呢?
概 述 有些应用要求MCU能高效处理,特别是跑一些算法时,对CPU执行效率要求较高。 网上有很多文章说STM32Cube HAL执行效率不高,代码量大等问题 ,导致很多还没有入门,或初学的读者就产生各种各样的疑惑。 说实话,HAL相对标准外设库来说确实存在代码效率不高、代码量大灯这些问题,那么与之对应的STM32Cube LL恰好避免了这样的问题。 LL能高效的原因 简单总结一下原因: 巧妙运用C语言静态、内联函数直接操作寄存器 。 当然,这是其中重要的原因,还有一些其它原因,这里暂不描述。 你会在LL库.h文件中发现大量类似,静态、内联函数直接读写寄存器的函数。 比如读写IO口: __STATIC_
[单片机]
<font color='red'>STM32</font> LL库为什么比HAL库高效呢?
STM32芯片的内部架构如何
STM32芯片主要由内核和片上外设组成,STM32F103采用的是Cortex-M3内核,内核由ARM公司设计。STM32的芯片生产厂商ST,负责在内核之外设计部件并生产整个芯片。这些内核之外的部件被称为核外外设或片上外设,如 GPIO、USART(串口)、I2C、SPI 等。 芯片内部架构示意图 芯片内核与外设之间通过各种总线连接,其中驱动单元有 4 个,被动单元也有 4 个,具体如上图所示。可以把驱动单元理解成是内核部分,被动单元都理解成外设。 ICode 总线 ICode总线是专门用来取指令的,其中的I表示Instruction(指令),指令的意思。写好的程序编译之后都是一条条指令,存放在 FLASH中,内核通过ICod
[单片机]
<font color='red'>STM32</font>芯片的内部架构如何
关于stm32中printf函数重定向问题
学习stm32过程中,对printf函数进行了重定向,但是不能够在串口调试助手中显示出来,并且debug不能全速运行,printf函数阻碍了程序的运行。 后来求教了度娘。 标准库函数的默认输出设备是显示器,要实现在串口或LCD输出,必须重定义标准库函数里调用的与输出设备相关的函数. 例如:printf输出到串口,需要将fputc里面的输出指向串口(重定向),方法如下: #ifdef __GNUC__ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endi
[单片机]
关于<font color='red'>stm32</font>中printf函数重定向问题
STM32的ISP方式和IAP方式下载程序有什么区别
都可以通过串口来下载啊 ISP方式:需要将BOOT管脚配置成上电从System Memory启动,System Memory中有一段BOOTLOADER来接收串口来的数据,把它们烧写到FLASH中。 IAP方式:是用户自己写一段烧写程序,通过ISP或者仿真器事先烧写到用户FLASH中,使用时通过某种方式触发这段程序,再来从串口接收数据,然后烧到相应的FLASH中,不需要改变BOOT管脚配置。
[单片机]

推荐帖子

两台机器,主机双网卡,共享上网的方法
最简单的方法是直接连接:需要两个网卡。一根做好的网线(连接方式是:网线的1、3和2、6头互换)用网线将两台机器的网卡连接起来,IP和网关设置:如主机的IP为:192.168.0.2网关为:192.168.0.1则从机IP为:192.168.0.1网关为:192.168.0.1也就是说两台机器网关必须一样,从机IP必须与主机网关相同。注:如需要上网还需要一个网卡用来接入因特网,但只有这台电脑能上网,另一台只能与这台电脑资源共享和联机玩游戏。第二种方法:需要一台集线器将两台电
liudong2008lldd RF/无线
急!急!急!请教一个关于udp通信的问题
我想在一个多任务程序中用udp方式实现任务之间的通信,应该属于在本地机上实现通信,不知道怎么做啊,把ip设成一样的127.0.0.1就可以了吗?急!急!急!请教一个关于udp通信的问题没遇到过这种情况.完全可以的,但是任务间通讯为什么要使用UDP呢?同意楼上的,任务之间直接写函数调用不是比用任务更快吗?设一个标志来使用也不错啊.youcanusemessagequeue就绑定到本机的ip,用不同的端口就可以用端口号标识不同的任务,ip地址就是127.0.0.1可以的
yue009 嵌入式系统
求教一个基础问题
我想用C#写个程序,接收从传感器传来的信息,分析后将结果打印出来。但是如何用C#接收从传感器收集到的信息呢?求教一个基础问题
机电学子 嵌入式系统
【一起玩esp8266】固件升级失败
接上一篇帖子【一起玩esp8266】简单调试-【MicroPython开源版块】-电子工程世界-论坛https://bbs.eeworld.com.cn/thread-497591-1-1.html参考如下帖子升级固件【一起玩ESP8266】-固件升级+发现串口工具的选择问题-【MicroPython开源版块】-电子工程世界-论坛https://bbs.eeworld.com.cn/thread-497736-1-1.html电脑之前已安装pythonIDLE,即g
suoma MicroPython开源版块
问个adc很基础的问题
这几个概念采样序列,多通道输入我理解不到位。看了下几种adc的转换原理,都是一个模拟信号,这个多通道意思是芯片可以同时采样多个模拟信号吗?还有采样序列发生器起什么作用?问个adc很基础的问题由于32位的无比强大,所以采样分多个管脚采了,不象以前用模拟开关,且可规定采哪几路不采哪几路,连续采和一次采,牛完了我的理解哈多通道就是可以采样多路模拟信号的!~比如说8路10位ADC就是指能采样八个模拟信号,而且精度是10位的。当日不是8路同时采用,是分开的我理解的多通道就是你可以把8个
慢慢来 单片机
急需嵌入式讲师
中程在线(北京)科技有限公司成立于2002年,是信息产业部电子信息中心以及中科院软件所等政府部门指定的专业培训合作机构。中程在线致力于信息产业方面的培训、咨询与服务。急需嵌入式讲师精通linux系统及ARM同时具备两年以上讲师经验。如有意者请联系葛老师13910138767急需嵌入式讲师以后需再关注,现在先帮你顶一下
zjw8586 嵌入式系统
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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