前言
//在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 - GPIO 的位带操作
推荐阅读最新更新时间:2024-11-16 22:51
推荐帖子
- 两台机器,主机双网卡,共享上网的方法
- 最简单的方法是直接连接:需要两个网卡。一根做好的网线(连接方式是:网线的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 嵌入式系统