idr寄存器、_嘿哈——寄存器映射

上一次我们已经实现了如何直接操作寄存器地址来点亮一盏LED灯,但是这样实在是太麻烦,那么这次要讲的就是,如何实现寄存器映射,更加快捷的实现点灯(怎么又是点灯??)

我们先来看一下上一次的代码。

5d2235b65cb891fe578f5a02236cf928.png

图中的这些地址都是看着官方给出的文档算出来的,这样做的缺点很明显,就是每一次都要算,算每一个寄存器的位置,实际上我们可以寄存器映射来做到同样的效果。

首先我们先定义所有外设的基地址的宏:

7bc3429f7b65e5c6d212df76928790f0.png

那么这个地址从哪里来的呢?可以看一下面这张图,ST把所有的存储器分成了8个块,直接来看(从下往上数)第三个块(绝对不是我不知道其他块是干哈的!!)

90fb34d7f140bbfeb86dbaedaa40b55a.png

Peripheral块这里存放了所有ST设计的外设,其中,包含了3条总线APB1、APB2和AHB,位置最低的APB1的基地址,也就是所有外设的基地址,也就是0x40000000,所以我们第二步要定义的,就是APB1的地址:

e6b11b0f4cb9a9f01a0766a02bdbc700.png

那么APB2的地址在哪呢?

155908f7b4057cccfa1e5dbe109816f3.png

在上图红色框中的位置,0x4001000,那么是直接定义#define APB2PERIPH_BASE  0x4001000这样吗?在这里,我们往往用偏移的方式,也就是这样:

97107a81031bf03dbde14fe0e7eaebd4.png

这里我们用外设基地址+0x10000的方式,到达APB2的位置。

那么AHB同理(虽然用不上,但还是写上吧...):

0e487ebd510870cfd149c80f01252deb.png

下一步,我们以点亮PB5为例,还记得我们上次说的,GPIOB也是有偏移量的,那么我们就基于APB2 + GPIOB的偏移量得出:

42629a63e135b3030be9b3401b1d974f.png

这样就可以操作GPIOB了,下一步,要操作GPIOB的CRL和ODR,GPIOB的基地址加上偏移量得出:

37fc50e829ff388db9e52b3529420ea5.png

然后我们再回到main.c里面,把上次的地址换成CRL和ODR:

2ecf49dc445b3e9f60e56c32b804f44d.png

RCC时钟配置同理,先在stm32f10x.h里面定义宏:

b765f25e9d9856aacac7705ff003d517.png

再回到main里面更换

cdd42f83d9018d1edf7cc73912c4e7a4.png

那么最终的代码就是:

//main.c#include "stm32f10x.h"int main(void){    // 开启GPIOB 端口时钟  RCC_APB2ENR |= (1<<3);  //清空控制PB5的端口位  GPIOB_CRL &= ~( 0x0F<< (4*5));    // 配置PB5为通用推挽输出,速度为10M  GPIOB_CRL |= (1<<4*5);  // PB5 输出 低电平  GPIOB_ODR |= (0<<5);    while(1);}// 函数为空,目的是为了骗过编译器不报错void SystemInit(void){  }
//stm32f10x.h#ifndef __STM32F10X__H#define __STM32F10X__H/*片上外设基地址  */#define PERIPH_BASE           ((unsigned int)0x40000000)/*APB1 总线基地址 */#define APB1PERIPH_BASE       (PERIPH_BASE)/*APB2 总线基地址 */#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)/* AHB总线基地址 */#define AHBPERIPH_BASE        (PERIPH_BASE + 0x20000)/*GPIOA外设基地址*/#define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800)/* GPIOA寄存器地址,强制转换成指针 */#define GPIOA_CRL      *(unsigned int*)(GPIOA_BASE+0x00)#define GPIOA_CRH      *(unsigned int*)(GPIOA_BASE+0x04)#define GPIOA_IDR      *(unsigned int*)(GPIOA_BASE+0x08)#define GPIOA_ODR      *(unsigned int*)(GPIOA_BASE+0x0C)#define GPIOA_BSRR        *(unsigned int*)(GPIOA_BASE+0x10)#define GPIOA_BRR      *(unsigned int*)(GPIOA_BASE+0x14)#define GPIOA_LCKR      *(unsigned int*)(GPIOA_BASE+0x18)/*GPIOB外设基地址*/#define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00)/* GPIOB寄存器地址,强制转换成指针 */#define GPIOB_CRL      *(unsigned int*)(GPIOB_BASE+0x00)#define GPIOB_CRH      *(unsigned int*)(GPIOB_BASE+0x04)#define GPIOB_IDR      *(unsigned int*)(GPIOB_BASE+0x08)#define GPIOB_ODR      *(unsigned int*)(GPIOB_BASE+0x0C)#define GPIOB_BSRR     *(unsigned int*)(GPIOB_BASE+0x10)#define GPIOB_BRR      *(unsigned int*)(GPIOB_BASE+0x14)#define GPIOB_LCKR     *(unsigned int*)(GPIOB_BASE+0x18)/*RCC外设基地址*/#define RCC_BASE      (AHBPERIPH_BASE + 0x1000)/*RCC的AHB1时钟使能寄存器地址,强制转换成指针*/#define RCC_APB2ENR     *(unsigned int*)(RCC_BASE+0x18)  #endif  /*__STM32F10X__H*/

3365ee2deb45159e6bc98ad2de52a1ac.png

我是谁我在哪,我在干神魔。。>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值