stm32存储器映像和标准库中定义外设地址的方法
结合存储器映像理解stm32标准库中定义外设地址的方法。
stm32f103zet6是32位的。它所能访问的地址空间范围为2^32=4GB,把4GB分为8个block,分别为block0-block-7。把这8个block用于不同的用途。
block0-block7的用途

图1
————————————————————————————————————————————————————————


图2
从上面的图2中可以看到block2作为外设的地址,也就是说我们操作的外设都在block2中。block2的起始地址是0x4000 0000。这些外设包括哪些?看下面图3上,所有APB1、APB2、AHB上的外设都在这个block2中。
- #define PERIPH_BB_BASE ((uint32_t)0x42000000) /*!< Peripheral base address in the bit-band region */
 
//标准库中定义了外设起始地址(block2的起始地址)

图3
————————————————————————————————————————————————————————
我们操作的外设都在block2中,而外设又必定在APB1、APB2、AHB中的某一条总线上。那APB1、APB2、AHB在block2中怎么排布?图4上列出来3条总线的地址,可以看到APB1总线的起始地址和block2的起始地址是一样的。
- #define APB1PERIPH_BASE PERIPH_BASE //APB1的起始地址是block2的起始地址
 - #define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) //APB2的起始地址是在block2的地址上偏移得到的
 - #define AHBPERIPH_BASE (PERIPH_BASE + 0x20000) //AHB的起始地址是0x4001 8000(SDIO的地址),标准库中AHBPERIPH_BASE是0x4002 000(DMA1外设)
 

图4
从图5中列出了APB1总线上的外设。观察发现APB1总线上的第一个外设是TIM2定时器。
- #define TIM2_BASE (APB1PERIPH_BASE + 0x0000) //标准库中定义的定时器2的地址,+0x0000是因为tim2地偏移地址是0,
 
//比如,APB1总线上第二给外设是tim3,偏移地址0x0400,它的写法就是
#define TIM3_BASE (APB1PERIPH_BASE + 0x0400)

图5
经过上面的外设基地址+偏移地址得到了TIM2的起始地址,TIM2这个外设有很多寄存器,第一个寄存器偏移地址是0x00。每个寄存器的偏移地址都是0x04。这里没有再用上面的宏定义的方法去通过基地址+偏移地址去计算每个外设的寄存器的地址,通过一种更巧妙的方法。
因为寄存器是32位的,也就是4个字节。寄存器都是内存对齐的(寄存器用不了32位的,剩多少保留多少),用结构体的方式去强制转换一TIM2的起始地址。这个利用了结构体中变量对齐和外设寄存器对齐的方式。
- #define TIM2 ((TIM_TypeDef *) TIM2_BASE)
 
结构体内部:
- typedef struct
 - {
 - __IO uint16_t CR1;
 - uint16_t RESERVED0;
 - __IO uint16_t CR2;
 - uint16_t RESERVED1;
 - __IO uint16_t SMCR;
 - uint16_t RESERVED2;
 - __IO uint16_t DIER;
 - uint16_t RESERVED3;
 - __IO uint16_t SR;
 - uint16_t RESERVED4;
 - __IO uint16_t EGR;
 - uint16_t RESERVED5;
 - __IO uint16_t CCMR1;
 - uint16_t RESERVED6;
 - __IO uint16_t CCMR2;
 - uint16_t RESERVED7;
 - __IO uint16_t CCER;
 - uint16_t RESERVED8;
 - __IO uint16_t CNT;
 - uint16_t RESERVED9;
 - __IO uint16_t PSC;
 - uint16_t RESERVED10;
 - __IO uint16_t ARR;
 - uint16_t RESERVED11;
 - __IO uint16_t RCR;
 - uint16_t RESERVED12;
 - __IO uint16_t CCR1;
 - uint16_t RESERVED13;
 - __IO uint16_t CCR2;
 - uint16_t RESERVED14;
 - __IO uint16_t CCR3;
 - uint16_t RESERVED15;
 - __IO uint16_t CCR4;
 - uint16_t RESERVED16;
 - __IO uint16_t BDTR;
 - uint16_t RESERVED17;
 - __IO uint16_t DCR;
 - uint16_t RESERVED18;
 - __IO uint16_t DMAR;
 - uint16_t RESERVED19;
 - } TIM_TypeDef;
 
总结一下:
stm32中,标准库中定义一个外设地址的方法是,外设起始地址(block2起始地址)+总线偏移地址(APB1、APB2、AHB)+具体外设偏移地址(TIM、GPIO等)。最后把具体外设偏移地址通过结构体类型强制转换成结构体变量。
stm32存储器映像和标准库中定义外设地址的方法的更多相关文章
- 参考C++STL标准库中对了的使用方法
		
http://www.cppblog.com/zhenglinbo/archive/2012/09/18/191170.html 参考:http://www.cppblog.com/zhenglinb ...
 - STL笔记(6)标准库:标准库中的排序算法
		
STL笔记(6)标准库:标准库中的排序算法 标准库:标准库中的排序算法The Standard Librarian: Sorting in the Standard Library Matthew A ...
 - 用CAS操作实现Go标准库中的Once
		
Go标准库中提供了Sync.Once来实现"只执行一次"的功能.学习了一下源代码,里面用的是经典的双重检查的模式: // Once is an object that will p ...
 - 彻底弄清c标准库中string.h里的常用函数用法
		
在我们平常写的c/c++程序,一些算法题中,我们常常会用到c标准库中string.h文件中的函数,这些函数主要用于处理内存,字符串相关操作,是很有用的工具函数.而且有些时候,在笔试或面试中也会出现让你 ...
 - 通过atomic_flag简单自旋锁实现简单说明标准库中锁使用的memory_order
		
在使用标准库中的加锁机制时,例如我们使用std::mutex,写了如下的代码(下面的代码使用condition_variable可能更合适) std::mutex g_mtx; int g_resNu ...
 - Python 标准库中的装饰器
		
题目描述 1.简单举例 Python 标准库中的装饰器 2.说说你用过的 Python 标准库中的装饰器 1. 首先,我们比较熟悉,也是比较常用的 Python 标准库提供的装饰器有:property ...
 - (转)python标准库中socket模块详解
		
python标准库中socket模块详解 socket模块简介 原文:http://www.lybbn.cn/data/datas.php?yw=71 网络上的两个程序通过一个双向的通信连接实现数据的 ...
 - c/c++标准库中的文件操作总结
		
1 stdio.h是c标准库中的标准输入输出库 2 在c++中调用的方法 直接调用即可,但是最好在函数名前面加上::,以示区分类的内部函数和c标准库函数. 3 c标准输入输出库的使用 3.1 核心结构 ...
 - C标准库中atoi的一种可能的实现
		
为避免与标准库中的atoi产生歧义, 我将自己编写的函数命名为strToInt, 以下是示例代码 #include <stdio.h> int strToInt(const char *s ...
 
随机推荐
- SpringBoot返回html页面
			
一般Controller返回数据或页面,今天谈一下返回页面的场景. 一.不使用template 1. controller中定义对应的访问路由及返回的页面(使用Controller,不要使用RestC ...
 - Java实现 LeetCode 780 到达终点(逻辑题)
			
780. 到达终点 从点 (x, y) 可以转换到 (x, x+y) 或者 (x+y, y). 给定一个起点 (sx, sy) 和一个终点 (tx, ty),如果通过一系列的转换可以从起点到达终点,则 ...
 - Java实现 蓝桥杯VIP 算法训练 大小写判断
			
问题描述 给定一个英文字母判断这个字母是大写还是小写. 输入格式 输入只包含一个英文字母c. 输出格式 如果c是大写字母,输出"upper",否则输出"lower&quo ...
 - Java实现 神犇的悲惨一生
			
[问题描述] 传说中有位神犇,因其一贯低调,所以人们连他活了多少岁都不知道. 好在XXXX文献上有段关于他生平细节的文字:神犇一生中, 幼年占了1/6,又过了1/12的青春期,又谈了1/6的恋爱后结婚 ...
 - 第六届蓝桥杯JavaB组国(决)赛真题
			
解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论 题目1.分机号 X老板脾气古怪,他们公司的电话分机号都是3位数,老板规定,所有号码必须是降序排列,且不能有重复的数位.比如: 751,520, ...
 - Java实现最优二叉查找树
			
1 问题描述 在了解最优二叉查找树之前,我们必须先了解何为二叉查找树? 引用自百度百科一段讲解: 二叉排序树(Binary Sort Tree)又称二叉查找树(Binary Search Tree), ...
 - Cookie默认不设置path时,哪些请求会携带cookie数据
			
默认不设置path的时候,只会在请求和servlet同路径的情况下才会携带cookie中存储的数据,包含同级目录和下级目录 例如: 在http://localhost:8080/day01/test/ ...
 - 关于vue不能像angular深度克隆数据解决办法
			
vue要让数据源实现响应式前提必须要在初始化的时候有这个属性 如果没有这个属性,也可实现数据实时响应.解决方法: this.数组/对象.spice(0,1,'属性值') Vue.set(要修改的数组或 ...
 - JS中的各类运算符
			
2020-04-15 JS中的各类运算符 // 假设有如下代码,那么a(10)的返回结果是?( ) function a(a) { a^=(1<<4)-1; return a; } // ...
 - Git中的core.autocrlf选项
			
项目的开发环境为Windows,在Linux环境下编译,使用Git进行版本控制. 在安装好Git和TortoiseGit后,从远端clone,遇到一个奇怪的问题,Shell脚本中的LF总是被替换成了C ...