结合存储器映像理解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存储器映像和标准库中定义外设地址的方法的更多相关文章

  1. 参考C++STL标准库中对了的使用方法

    http://www.cppblog.com/zhenglinbo/archive/2012/09/18/191170.html 参考:http://www.cppblog.com/zhenglinb ...

  2. STL笔记(6)标准库:标准库中的排序算法

    STL笔记(6)标准库:标准库中的排序算法 标准库:标准库中的排序算法The Standard Librarian: Sorting in the Standard Library Matthew A ...

  3. 用CAS操作实现Go标准库中的Once

    Go标准库中提供了Sync.Once来实现"只执行一次"的功能.学习了一下源代码,里面用的是经典的双重检查的模式: // Once is an object that will p ...

  4. 彻底弄清c标准库中string.h里的常用函数用法

    在我们平常写的c/c++程序,一些算法题中,我们常常会用到c标准库中string.h文件中的函数,这些函数主要用于处理内存,字符串相关操作,是很有用的工具函数.而且有些时候,在笔试或面试中也会出现让你 ...

  5. 通过atomic_flag简单自旋锁实现简单说明标准库中锁使用的memory_order

    在使用标准库中的加锁机制时,例如我们使用std::mutex,写了如下的代码(下面的代码使用condition_variable可能更合适) std::mutex g_mtx; int g_resNu ...

  6. Python 标准库中的装饰器

    题目描述 1.简单举例 Python 标准库中的装饰器 2.说说你用过的 Python 标准库中的装饰器 1. 首先,我们比较熟悉,也是比较常用的 Python 标准库提供的装饰器有:property ...

  7. (转)python标准库中socket模块详解

    python标准库中socket模块详解 socket模块简介 原文:http://www.lybbn.cn/data/datas.php?yw=71 网络上的两个程序通过一个双向的通信连接实现数据的 ...

  8. c/c++标准库中的文件操作总结

    1 stdio.h是c标准库中的标准输入输出库 2 在c++中调用的方法 直接调用即可,但是最好在函数名前面加上::,以示区分类的内部函数和c标准库函数. 3 c标准输入输出库的使用 3.1 核心结构 ...

  9. C标准库中atoi的一种可能的实现

    为避免与标准库中的atoi产生歧义, 我将自己编写的函数命名为strToInt, 以下是示例代码 #include <stdio.h> int strToInt(const char *s ...

随机推荐

  1. (Java实现) 过河卒

    过河卒 题目描述 棋盘上AA点有一个过河卒,需要走到目标BB点.卒行走的规则:可以向下.或者向右.同时在棋盘上CC点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为&q ...

  2. C# Winform学习(六)

    目标: 1.树型控件TreeView 2.列表视图控件ListView 一.树型控件 1.命名:tv开始 2.作用:用来显示有层次结构的数据 3.特点 1)允许有多个根节点 2)每个节点可以有多个子节 ...

  3. Java实现 LeetCode 390 消除游戏

    390. 消除游戏 给定一个从1 到 n 排序的整数列表. 首先,从左到右,从第一个数字开始,每隔一个数字进行删除,直到列表的末尾. 第二步,在剩下的数字中,从右到左,从倒数第一个数字开始,每隔一个数 ...

  4. Java实现 LeetCode 90 子集 II(二)

    90. 子集 II 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: [1,2,2] 输出: [ [2], [1], [ ...

  5. java实现第七届蓝桥杯寒假作业

    题目6.寒假作业 寒假作业 现在小学的数学题目也不是那么好玩的. 看看这个寒假作业: □ + □ = □ □ - □ = □ □ × □ = □ □ ÷ □ = □ (如果显示不出来,可以参见[图1. ...

  6. Navicat 连接远程服务器端MySQL

    Navicat是一个很好的操作各种数据库的图形化工具,我用它在本地连接过MySQL.SQL Server.SQLite,用它操作数据库确实非常方便.快捷,再搭配SQL语句,是一个很好的选择了. 废话不 ...

  7. Mysql添加索引及索引的优缺点

    一.什么是索引? 索引是对数据库表中的一列或多列值进行排序的一种结构,使用索引可以快速访问数据库表中的特定信息. 二.索引的作用? 索引相当于图书上的目录,可以根据目录上的页码快速找到所需的内容,提高 ...

  8. c/c++混编

    /* head.h */#ifndef __SUM_H__ #define __SUM_H__ #ifdef __cplusplus extern "C" { #endif int ...

  9. 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(四)

    系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...

  10. 使用navicat连接mysql连接错误:Lost connection to Mysql server at 'waiting for initial communication packet'

    使用navicat时,报错截图如下: 原因分析: mysql开启了DNS的反向解析功能,这样mysql对连接的客户端会进行DNS主机名查找. mysql处理客户端解析过程: 当mysql的client ...