以前在学习STM32时候关注过STM32的位带操作,那时候只是知道位带是啥,用来干嘛用,说句心里话,并没有深入去学习,知其然而不知其所以然。但一直在心中存在疑惑,故今日便仔细看了一下,写下心得供日后参考。

位带操作,我所理解的是就是像51单片机那样驱动IO引脚一样,比如要驱动P1端口的第一个引脚直接用P1^1即可对P1.1引脚进行输入和输出,由于STM32基于32位寄存器操作,不允许直接访问某一位,要想控制GPIO端口的某一位怎么办,于是就有了位带操作,说白了就是为解决STM32不能直接访问GPIO中的具体位而提出的办法。

在STM32的存储结构中外设区有位带区和位带别名区,这两个有何区别呢,位带区就是实际操作的外设地址,而位带别名区就是这个位带区的另一个名字。要想操作位就要把这个位变成一个能访问的地址,于是就将位带区膨胀成位带别名区,区别就是在位带别名区可以直接访问,因为已经把每一位都变成了一个字。

因此1M内存的BitBand区就对应32M内存的BitBand别名区,因为将每一位膨胀成为了一个32位的地址,所以相应的别名区的内存也会是位带区的32倍。

位带操作具体实现如下图片中公式所示:

  实现过程就是先找到端口的起始地址获得要操作端口的偏移地址也就是A-0X40000000,因为在别名区上的偏移也是对等的,将获得的这个偏移地址扩大到字(乘以8)也就是具体到某一位都有一个地址,然后在这个基础上想要操作哪位就是n直接加上就行,最后再乘以4扩到到字,再加上别名区的起始地址就获得了要设置的端口在别名区中的地址了,此时对别名区中的32位地址操作实际就是对GPIO的位操作。

位带别名区的起始地址为:0x42000000

GPIO端口起始地址如下所示(以STM32F4为例):

然后在STM32F4中ODR寄存器的偏移地址为0X14,IDR寄存器的偏移地址为0X10,根据上述具体公式便设置如以下代码便可实现对GPIO端口的位进行操作:

 #define    PAout(Pin_x)        * ((volatile unsigned long *)(0x42000000 + ((0X20000  + 0X14) * 32) + (Pin_x * 4)))
#define PBout(Pin_x) * ((volatile unsigned long *)(0x42000000 + ((0X20400 + 0X14) * 32) + (Pin_x * 4)))
#define PCout(Pin_x) * ((volatile unsigned long *)(0x42000000 + ((0X20800 + 0X14) * 32) + (Pin_x * 4)))
#define PDout(Pin_x) * ((volatile unsigned long *)(0x42000000 + ((0X20C00 + 0X14) * 32) + (Pin_x * 4)))
#define PEout(Pin_x) * ((volatile unsigned long *)(0x42000000 + ((0X21000 + 0X14) * 32) + (Pin_x * 4)))
#define PFout(Pin_x) * ((volatile unsigned long *)(0x42000000 + ((0X21400 + 0X14) * 32) + (Pin_x * 4)))
#define PGout(Pin_x) * ((volatile unsigned long *)(0x42000000 + ((0X21800 + 0X14) * 32) + (Pin_x * 4)))
#define PHout(Pin_x) * ((volatile unsigned long *)(0x42000000 + ((0X21C00 + 0X14) * 32) + (Pin_x * 4)))
#define PIout(Pin_x) * ((volatile unsigned long *)(0x42000000 + ((0X22000 + 0X14) * 32) + (Pin_x * 4))) #define PAin(Pin_x) * ((volatile unsigned long *)(0x42000000 + ((0X20000 + 0X10) * 32) + (Pin_x * 4)))
#define PBin(Pin_x) * ((volatile unsigned long *)(0x42000000 + ((0X20400 + 0X10) * 32) + (Pin_x * 4)))
#define PCin(Pin_x) * ((volatile unsigned long *)(0x42000000 + ((0X20800 + 0X10) * 32) + (Pin_x * 4)))
#define PDin(Pin_x) * ((volatile unsigned long *)(0x42000000 + ((0X20C00 + 0X10) * 32) + (Pin_x * 4)))
#define PEin(Pin_x) * ((volatile unsigned long *)(0x42000000 + ((0X21000 + 0X10) * 32) + (Pin_x * 4)))
#define PFin(Pin_x) * ((volatile unsigned long *)(0x42000000 + ((0X21400 + 0X10) * 32) + (Pin_x * 4)))
#define PGin(Pin_x) * ((volatile unsigned long *)(0x42000000 + ((0X21800 + 0X10) * 32) + (Pin_x * 4)))
#define PHin(Pin_x) * ((volatile unsigned long *)(0x42000000 + ((0X21C00 + 0X10) * 32) + (Pin_x * 4)))
#define PIin(Pin_x) * ((volatile unsigned long *)(0x42000000 + ((0X22000 + 0X10) * 32) + (Pin_x * 4)))

设置后就可直接用PXout(n)和PXin(n)进行X端口的n位进行输出和输入了。

关于STM32位带操作随笔的更多相关文章

  1. STM32位带操作总结---浅显易懂

    正在准备做毕业设计,配置LED_Config()的时候,又看到了位带操作的宏定义,我又嘀咕了,什么是位带操作,一年前在使用位带操作的时候,就查阅过好多资料,Core-M3也看过,但是对于博主这种“低能 ...

  2. STM32位带操作

    STM32的位带操作是基于cortex内核自带的,而不是st公司独创.基本的思路就是用一个32位的地址空间访问一个bit,因为stm32只支持32位数据的读取,不像51单片机一样,是可以单独对一位操作 ...

  3. 【ARM】---STM32位带操作总结---浅显易懂

    正在准备做毕业设计,配置LED_Config()的时候,又看到了位带操作的宏定义,我又嘀咕了,什么是位带操作,一年前在使用位带操作的时候,就查阅过好多资料,Core-M3也看过,但是对于博主这种“低能 ...

  4. STM32—位带操作

    STM32中的位带操作: 名字为位带操作,实际上是对位的操作,位操作就是可以单独的对一个比特位读和写,这个在 51 单片机中非常常见. 51 单片机中通过关键字 sbit 来实现位定义, STM32 ...

  5. (stm32学习总结)—GPIO位带操作

    本章参考资料:<STM32F10X-中文参考手册>存储器和总线构架章节.GPIO 章节,<CM3 权威指南 CnR2>存储器系统章节. 位带简介 位操作就是可以单独的对一个比特 ...

  6. STM32之GPIO端口位带操作

    #ifndef __SYS_H #define __SYS_H #include "stm32f10x.h" //位带操作 //把“位带地址+位序号”转换别名地址宏 #define ...

  7. STM32F030系列实现仿位带操作

    1.闲言 最近开发的时候,用到了STM32F030F4P6型号的单片机,它只有20个引脚,价格非常便宜,但是功能齐全:定时器.外部中断.串口.IIC.SPI.DMA和WWDG等等,应用尽有,非常适合用 ...

  8. 玩转X-CTR100 l STM32F4 l 基础例程printf、LED、蜂鸣器、拨码开关、位带操作

    我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ]      本文介绍X-CTR100控制器基础板载资源 ...

  9. 玩转X-CTR100 | STM32F4 l GPIO位带操作

    更多塔克创新资讯欢迎登陆[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ]       STM32F4位带概念,及位带的GPIO操作实践应用. 原理介 ...

随机推荐

  1. Petya and Graph(最小割,最大权闭合子图)

    Petya and Graph http://codeforces.com/contest/1082/problem/G time limit per test 2 seconds memory li ...

  2. 条款2:尽量以const, enum, inline替换#define

    原因: 1. 追踪困难,由于在编译期已经替换,在记号表中没有. 2. 由于编译期多处替换,可能导致目标代码体积稍大. 3. define没有作用域,如在类中定义一个常量不行. 做法: 可以用const ...

  3. 【校招面试 之 C/C++】第16题 C++ new和delete的实现原理

    1.new new操作针对数据类型的处理,分为两种情况: (1)简单数据类型(包括基本数据类型和不需要构造函数的类型) 代码实例: int* p = new int; 汇编码如下: int* p = ...

  4. OC - runtime - 1

  5. mysql中GROUP_CONCAT的使用

    现在有三个表,结构如下: cate表 CREATE TABLE `cate` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', ...

  6. 电商类Web原型制作分享-IKEA

    IKEA是一个家居整合大型零售商,属于电商类官网.电商以展示商品.售后服务.购物流程为主.根据网站的图文方式排版,主导航栏使用的标签组,区域导航栏使用的是垂直选项卡,实现下拉弹出面板交互的功能. 本原 ...

  7. 经典递归问题:0,1背包问题 kmp 用遗传算法来解背包问题,hash表,位图法搜索,最长公共子序列

    0,1背包问题:我写笔记风格就是想到哪里写哪里,有很多是旧的也没删除,代码内部可能有很多重复的东西,但是保证能运行出最后效果 '''学点高大上的遗传算法''' '''首先是Np问题的定义: npc:多 ...

  8. JavaScript 静态方法和实例方法

    总结: 直接定义在构造函数上的方法和属性是静态的,  定义在构造函数的原型和实例上的方法和属性是非静态的 静态方法: function ClassA(){ //定义构造函数 }; ClassA.fun ...

  9. 2018.09.21 codeforces1051D. Bicolorings(线性dp)

    传送门 sb线性DP. f[i][j][0/1/2/3]f[i][j][0/1/2/3]f[i][j][0/1/2/3]表示前i列j个连通块且第i列状态为00/01/10/11时的方案总数. 这个显然 ...

  10. 2018.09.01 独立集(树形dp)

    描述 给定一颗树(边权为1),选取一个节点子集,使得该集合中任意两个节点之间的距离都大于K.求这个集合节点最多是多少 输入 第一行是两个整数N,K 接下来是N-1行,每行2个整数x,y,表示x与y有一 ...