STM32位带区和位带别名区的浅谈

1.首先谈下为什么要使用位带?

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

2.存储单元和存储地址的相关概念

在计算机中最小的信息单位是bit,也就是一个二进制位,8个bit组成一个Byte,也就是字节。一个存储单元可以存储一个字节,也就是8个二进制位。计算机的存储器容量是以字节为最小单位来计算的,对于一个有128个存储单元的存储器,可以说它的容量为128字节。如果有一个1KB的存储器则它有1024个存储单元,它的编号为从0-1023。存储器被划分成了若干个存储单元,每个存储单元都是从0开始顺序编号,如一个存储器有128个存储单元,则它的编号就是从0-127。

存储地址一般用十六进制数表示,而每一个存储器地址中又存放着一组二进制(或十六进制)表示的数,通常称为该地址的内容。值得注意的是,内储单元的地址和地址中的内容两者是不一样的。前者是存储单元的编号,表示存储器总的一个位置,而后者表示这个位置里存放的数据。正如一个是房间号码,一个是房间里住的人一样。

存放一个机器字的存储单元,通常称为字存储单元,相应的单元地址叫字地址。而存放一个字节的单元,称为字节存储单元,相应的地址称为字节地址。如果计算机中可以编址的最小单元是字存储单元,则该计算机称为按字寻址的计算机。如果计算机中可编址的最小单位是字节,则该计算机称为按字节寻址的计算机。如果机器字长等于存储器单元的位数,一个机器字可以包含数个字节,所以一个存储单元也可以包含数个能够单独编址的字节地址。例如一个16位二进制的字存储单元可存放两个字节,可以按字地址寻址,也可以按字节地址寻址。当用字节地址寻址时,16位的存储单元占两个字节地址。(摘自百度百科)

以STM32来说,STM32是一个32位的微控制器,它是按字存储单元;每一个寄存器都是占用4个字节即32位,这点将在下面位带和位带别名地址换算的时候用到

3.Cortex-M3位带区和位带映射区对应关系

STM32位带及位带别名区域支持位带操作的区域是SRAM 区的最低1MB 范围(APB1/2,AHB1外设)和片内外设区的最低1MB范围。
图一
对于SRAM/GPIO位带区的某个比特(bit),记它所在的字节地址为A,位序号为n(0<=n<=7)(如果是GPIO则n<=16),则该比特在位带别名区中的地址为:

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

上式中‘8’表示每个字节中有8个比特,‘4’表示4个字节(因为CM3是32位机,机器字为4个字节)。

(A-0x20000000)表示一共用这么多个字节,(A-0x20000000)*8+n表示一共有这么多位,在别名区中,每个位占4个字节地址,故((A-0x20000000)*8+n)*4表示该位在别名区中的偏移字节地址。偏移地址加上基地址就是该比特在位带别名区中的地址
在这里插入图片描述

4.最后附上STM32F103的实现代码

#ifndef _BIT_BIND_H_
#define _BIT_BIND_H_#include "stm32f10x.h"//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(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)  //输入#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/531475.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hibernate的数据查找,添加!

1.首先看一下测试数据库的物理模型 2.测试所需要的Hibernate的jar包 3.数据库的sql /**/ /* DBMS name: MySQL 5.0 */ /* Created on: 2015/7/3 23:17:57 */ /**/drop table if exists books;drop tab…

新手如何在Altium Designer中绘制电路板

好久没用AD画电路板了&#xff0c;这次电子实训让画个PCB板&#xff0c;借着这个机会写了一篇新手教程。 此教程所用的电路图是自动循迹小车&#xff0c;虽然元件比较简单&#xff0c;但是感觉还是很厉害的&#xff0c;一块看一下吧。 此教程仅适用于没有基础的同学 一、概述 …

Qt模仿QQ登录界面(一)

这两天研究qt&#xff0c;练习时做了个仿QQ登录界面&#xff0c;我这次实现的比较简单&#xff0c;先在这里记录一下&#xff0c;以后有空了会继续完善的。 &#xff08;一&#xff09;效果图 这里使用我的qq号测试的如图&#xff1a; &#xff08;二&#xff09;工程文件 &…

回流焊和波峰焊的区别

本文首先分别介绍回流焊和波峰焊的特点&#xff0c;然后对两者进行比较&#xff0c;欢迎评论补充哦~ 最近在实习看到了厂里面的回流焊的波峰焊&#xff0c;有点好奇就查了点资料&#xff0c;分享给同样爱学习的你。 一.回流焊 一般的表面贴装工艺分三步&#xff1a;印刷机施加…

三对角矩阵的压缩

三对角矩阵&#xff0c;从第二行开始选中的元素的个数都为3个。对于a[i,j]将要存储的位置k&#xff0c;首先前(i-1)行元素的个数是(i-2)*3 2(第一行元素的个数为2)&#xff0c;又a[i,j]属于第i行被选中元素的第j-i1个元素&#xff0c;所以k (i-2)*3 2 j-i1 2*ij-3 如果知道了…

LC和RC滤波电路分析

一、概述 整流电路的输出电压并不是纯粹的直流&#xff0c;从示波器观察整流电路的输出&#xff0c;与直流相差很大&#xff0c;波形中含有较大的脉动成分&#xff0c;称为纹波。为了获得比较理想的直流电压&#xff0c;需要利用具有储能作用的电抗性元件(如&#xff1a;电感、…

dev c++ Boost库的安装

dev c 的boost库的安装步骤 然后点击“check for updates”按钮 最后点击“Download selected”按钮&#xff0c;下载完成后安装.... 给dev添加boost库文件&#xff0c;找到之前安装的目录 #include<iostream> #include<string> #include<cstring> #include…

(一)C语言之数据类型

在这里主要讲了基本的知识&#xff0c;具体练习时注意用代码看看数据存储的位数和大小&#xff0c;像char a127;aa1;这时候a的值。可以用sizeof查看数据类型占的字节数。以及不同数据类型之间如何自动转换和强制转换&#xff0c;还有printf和scanf的具体用法&#xff0c;多动手…

十字链表的应用

#include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> #define MAX_VERTEX_NUM 20 using namespace std; typedef struct ArcBox{int tailVex, headVex;//该弧的尾和头顶点的位置 struct ArcBox *hlink, *tlink;//分别为弧…

(二)C语言数据类型(2)

今天主要总结了一下运算符&#xff0c;详细介绍了运算符分类和优先级的基本知识 欢迎加入嵌入式学习群&#xff1a;559601187 运算符按操作数可以分为&#xff1a;单目运算符、双目运算符和三目运算符&#xff0c;优先级依次为单目运算符>双目运算符>三目运算符,在c语言里…

AOE网的关键路径的计算

求关键路径&#xff0c;只需理解顶点&#xff08;事件&#xff09;和边&#xff08;活动&#xff09;各自的两个特征属性以及求法即可&#xff1a; 先根据首结点的Ve(j)0由前向后&#xff08;正拓扑序列&#xff09;计算各顶点的最早发生时间 再根据终结点的Vl(j)等于它的V…

(三)C语言之九条语句

今天来说一下我们以后可能用的最多的C语言语句&#xff1a;条件语句、循环语句、控制语句。理论很简单&#xff0c;注重多自己写代码才能熟练运用。 欢迎加入嵌入式学习群&#xff1a;559601187 一起愉快的玩耍啊~ &#xff08;一&#xff09;条件语句 &#xff08;1&#xff…

次优查找树的建立

查找效率最高即平均查找长度最小&#xff0c;根据前面所学知识&#xff0c;我们可以给出有序表在非等概率情况下应遵循的两个原则&#xff1a; 1、最先访问的结点应是访问概率最大的结点&#xff1b; 2、每次访问应使结点两边尚未访问的结点的被访概率之和尽可能相等。 这两…

平衡二叉树AVL插入

平衡二叉树(Balancedbinary tree)是由阿德尔森-维尔斯和兰迪斯(Adelson-Velskiiand Landis)于1962年首先提出的&#xff0c;所以又称为AVL树。 定义&#xff1a;平衡二叉树或为空树,或为如下性质的二叉排序树: &#xff08;1&#xff09;左右子树深度之差的绝对值不超过1; &…

(五)C语言之二维数组

今天的第二个内容单独拿出来讲一下&#xff0c;对于初接触C语言的人来说&#xff0c;这个知识点比较难懂&#xff0c;后面在讲指针的时候我还会提到这部分的内容&#xff0c;看不懂的同学可以看后面的内容。 指针变量可以指向一维数组中的元素&#xff0c;当然也就可以指向二维…

平衡二叉树AVL删除

平衡二叉树的插入过程: http://www.cnblogs.com/hujunzheng/p/4665451.html 对于二叉平衡树的删除采用的是二叉排序树删除的思路: 假设被删结点是*p&#xff0c;其双亲是*f&#xff0c;不失一般性&#xff0c;设*p是*f的左孩子&#xff0c;下面分三种情况讨论&#xff1a;  ⑴…

(六)C语言之函数

本篇文章分为三个部分讲解&#xff0c;分别为函数、局部变量和全局变量、c语言存储分区 &#xff08;一&#xff09;函数的定义和调用 函数&#xff1a;工程中最小的单位&#xff0c;为了实现某一功能的 函数的定义&#xff1a; 数据类型 函数名(数据类型 形参1&#xff0c;…

堆排序算法---属于选择排序

1.堆 堆实际上是一棵完全二叉树&#xff0c;其任何一非叶节点满足性质&#xff1a; Key[i]<key[2i1]&&Key[i]<key[2i2]或者Key[i]>Key[2i1]&&key>key[2i2] 即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。 堆分为大顶堆和小顶堆…

(七)C语言之指针

c语言相比其他高级语言来说&#xff0c;更接近于对计算机硬件的操作&#xff0c;而指针的应用更是为我们对硬件的操作插上了翅膀&#xff0c;所以指针是嵌入式编程不可少的一部分&#xff0c;在一定意义上说&#xff0c;指针是c语言的精髓。 一、 什么是指针 在计算机中&#…

(八)C语言之结构

今天来说一下C语言里的结构体(struct)、共用体(l联合体)union、枚举。 &#xff08;一&#xff09;结构体&#xff1a;struct 1.1 概念 是一种自定义的数据类型结构体是构造类型的一种不同数据类型的集合地址空间连续&#xff0c;每次分配最大数据类型的宽度占用内存为所有变…