芯片:stm32f103zet6


1、存储单元一般应具有存储数据和读写数据的功能,一般以8位二进制作为一个存储单元,也就是一个字节.每个单元有一个地址,是一个整数编码,可以表示为二进制整数。


2、stm32是32位单片机,说明基本的寄存器是32位的,4字节。内存地址需要4位


3、基址也就是基础地址,最开始的地址,这个查看芯片手册,是人家规定的。


4、偏移,即偏移地址,一般是正整数,也是增加的数字。比如基址是10,偏移是4,地址就是10+4=14.


下面STM32F10xxx中内置外设的起始地址。


每个外设的起始地址就是,每个外设的基址了,当然这个基址也可以再分解为基址和偏移地址。


比如,GPIOB的起始地址是0X4001 0C00,可以分解为


片上外设基地址:0x40000000    GPIO都挂载到APB2总线:APB2偏移:0x10000,RCC在APB2总线的偏移是 0x0C00


GPIOB外设上有什么寄存器呢? 


 

 

看看其中的CRL寄存器,偏移是0x00 。如果要找GPIOB的CRL寄存器,则起始地址0X4001 0C00+偏移0x00


 

ODR偏移是0x0C,如果要找GPIOB的ODR寄存器,则起始地址0X4001 0C00+偏移0x0C


 来,用用吧。


我就让我的开发板的一个LED闪烁。


电路是这样的


现在要让GPIOB0输出低电平,灯亮,高电平,灯灭。


stm32使用一个外设得使能相应的时钟,即RCC。


我现在要使用GPIOB0,首先使能GPIOB的时钟,时钟也是寄存器控制的啊,查上面的地址表,RCC的基址是


0x40021000,使能GPIOB的时钟,它是由RCC_APB2ENR控制的,因为挂在APB2总线上。偏移是0x18


则RCC_APB2ENR地址:0x40021000+0x18=0x40021018

再设置GPIOB的IO模式,CRL寄存器控制。(CRL控制低8位引脚IO的模式,CRH控制高八位IO的模式,四位控制一个io的模式,一个寄存器控制8个引脚,共32位,一个寄存器)

 设置GPIOB的电平高低,ODR寄存器控制(直接对相应的引脚,写入1或者0就行,1,高电平,0,低电平)

 工程文件结构:起始文件,头文件,源文件


/*  片上外设基地址  */

#define PERIPH_BASE              ((unsigned int)0x40000000)

 

/*  总线基地址,GPIO都挂载到APB2上 */

#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)

 

/*  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 (0x40021000  +  0x1000) 

/* RCC的AHB1时钟使能寄存器地址,强制转换成指针  */

#define RCC_APB2ENR     *(unsigned int*)(RCC_BASE+0x18)

SystemInit()是为了骗过启动文件,这里应该配置时钟树,下次再讲。 对于那些逻辑运算不懂,看前面的stm32编程要点。


#include "stm32f1.h"

 

void SystemInit()

 

{

 

}

 

void delay(int t)

 

{

 

int i;

 

for( ;t>0; t--)

 

for(i=0;i<2000;i++);

 

}

 

int main(void)

{

RCC_APB2ENR |= (1<<3);

 

//清空控制PB0的端口

GPIOB_CRL &= ~(0x0F<<(4*0)); 

//配置PB0为通用推挽输出,速度为50M

GPIOB_CRL |= (0x03<<(4*0));

 

while(1)

{

GPIOB_ODR =0x00;

delay(1000);

GPIOB_ODR =0x01;

delay(1000);

}

}

现在我们怎么算这个偏移呢,我也是理解了好一会,只能说C语言还不够。

有了首地址  0x4002 3830  

也可以直接加偏移量,用宏定义。


在正点原子中,利用的是,结构体的内存对齐原则

**内存对齐,对齐规则是按照成员的声明顺序,依次安排内存,其偏移量为成员大小的整数倍,0看做任何成员的整数倍,最后结构体的大小为最大成员的整数倍**可以参考下面两篇文章。

https://blog.csdn.net/shi2huang/article/details/80290192

https://blog.csdn.net/weixin_40853073/article/details/81451792


好好理解 变量的地址,值,内存,之间的关系。很容易懵。下面会具体举例


再来理解  结构体  RCC_TypeDef 

因为每个寄存器变量都是32位的值,4个字节,所以占4个内存地址


所以每个变量代表的地址偏移量都是4的倍数,例如

typedef struct

{

  __IO uint32_t CR;            /*!< RCC clock control register,                                  Address offset: 0x00 */

  __IO uint32_t PLLCFGR;       /*!< RCC PLL configuration register,                              Address offset: 0x04 */

  __IO uint32_t CFGR;          /*!< RCC clock configuration register,                            Address offset: 0x08 */

  __IO uint32_t CIR;           /*!< RCC clock interrupt register,                                Address offset: 0x0C */

  __IO uint32_t AHB1RSTR;      /*!< RCC AHB1 peripheral reset register,                          Address offset: 0x10 */

  __IO uint32_t AHB2RSTR;      /*!< RCC AHB2 peripheral reset register,                          Address offset: 0x14 */

  __IO uint32_t AHB3RSTR;      /*!< RCC AHB3 peripheral reset register,                          Address offset: 0x18 */

  uint32_t      RESERVED0;     /*!< Reserved, 0x1C                                                                    */

  __IO uint32_t APB1RSTR;      /*!< RCC APB1 peripheral reset register,                          Address offset: 0x20 */

  __IO uint32_t APB2RSTR;      /*!< RCC APB2 peripheral reset register,                          Address offset: 0x24 */

  uint32_t      RESERVED1[2];  /*!< Reserved, 0x28-0x2C                                                               */

  __IO uint32_t AHB1ENR;       /*!< RCC AHB1 peripheral clock register,                          Address offset: 0x30 */

  __IO uint32_t AHB2ENR;       /*!< RCC AHB2 peripheral clock register,                          Address offset: 0x34 */

  __IO uint32_t AHB3ENR;       /*!< RCC AHB3 peripheral clock register,                          Address offset: 0x38 */

  uint32_t      RESERVED2;     /*!< Reserved, 0x3C                                                                    */

  __IO uint32_t APB1ENR;       /*!< RCC APB1 peripheral clock enable register,                   Address offset: 0x40 */

  __IO uint32_t APB2ENR;       /*!< RCC APB2 peripheral clock enable register,                   Address offset: 0x44 */

  uint32_t      RESERVED3[2];  /*!< Reserved, 0x48-0x4C                                                               */

  __IO uint32_t AHB1LPENR;     /*!< RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50 */

  __IO uint32_t AHB2LPENR;     /*!< RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54 */

  __IO uint32_t AHB3LPENR;     /*!< RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58 */

  uint32_t      RESERVED4;     /*!< Reserved, 0x5C                                                                    */

  __IO uint32_t APB1LPENR;     /*!< RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60 */

  __IO uint32_t APB2LPENR;     /*!< RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64 */

  uint32_t      RESERVED5[2];  /*!< Reserved, 0x68-0x6C                                                               */

  __IO uint32_t BDCR;          /*!< RCC Backup domain control register,                          Address offset: 0x70 */

  __IO uint32_t CSR;           /*!< RCC clock control & status register,                         Address offset: 0x74 */

  uint32_t      RESERVED6[2];  /*!< Reserved, 0x78-0x7C                                                               */

  __IO uint32_t SSCGR;         /*!< RCC spread spectrum clock generation register,               Address offset: 0x80 */

  __IO uint32_t PLLI2SCFGR;    /*!< RCC PLLI2S configuration register,                           Address offset: 0x84 */

  __IO uint32_t PLLSAICFGR;    /*!< RCC PLLSAI configuration register,                           Address offset: 0x88 */

  __IO uint32_t DCKCFGR;       /*!< RCC Dedicated Clocks configuration register,                 Address offset: 0x8C */

[1] [2]
关键字:STM32  单片机  寄存器地址  控制LED闪烁 引用地址:STM32单片机(五)-寄存器地址理解和控制LED闪烁

上一篇:移植freeRTOS V10.2.0到stm32f103zet6
下一篇:STM32单片机(三)-基本的工程文件介绍

推荐阅读

   旨在进一步开拓海外市场,小米于近期发布了全新的子品牌Pocophone,致力于打造高性价比的旗舰产品。8月22日下午,Pocophone于印度召开新品发布会,发布了旗下首款机型——Pocophone F1,该机搭载骁龙845移动平台,配备液冷散热系统,售价20999卢比,约合人民币2058元,成为目前最便宜的骁龙845机型。Pocophone F1依然采用了主流的刘海屏设计,6.18...
对于弯弓射大雕爷而言,今天是个好日子。他一扫半年前的阴霾,发了篇文章提醒大家,别怀疑了,“新消费”滔天巨浪来了。  雕爷描述了阿芙精油、河狸家青春再次焕发,并总结道,因为“新媒体、新渠道、新产品”的缘故,这是一个三十年一遇的“新品牌”机遇。雕爷的兴奋喜悦,弥漫在空气中每个角落。不禁令人遐想,黄太吉什么时候发文章。  不过,可以肯...
根据昨日和早前的报道,三星即将向印度市场推出推出一款可与 OnePlus Nord 一较高下的 Galaxy M51 中端新机。据说该机采用了高通骁龙 730 芯片组,6.67 英寸 @ FHD+ 分辨率的 AMOLED 打孔屏,后置 64MP 四摄、电池容量 7000 mAh、并且支持 25W 快充。近日,Pricebaba 又从 Twitter 爆料人 Ishan Agarwal 那获悉,...
首先看看我的板子,(s3c2440)可以看出,要使LED灯管亮,只要将nLED1置为低电平即可,就是将对应的GPIO引脚置为低电平。从上面两幅图可以发现,LED1、LED2、LED4对应着S3c2440的GPF端口,于是,通过查询手册可以知道对应寄存器的地址。于是可以开始编程了.text.global _start_start: @将GPF配置为输出引脚 LDR R0, =0x56000050 MOV R1, #0x00005500 ...

史海拾趣

问答坊 | AI 解惑

单片机PO口驱动问题

我用单片机P0口,采用了10K上拉电阻,然后每个口接了一个3mm的小发光二极管,在下载流水灯程序成功后,一开始指示灯还正常闪烁,但是一小会就不正常了,指示灯到后来干脆一个都不亮了,单片机插到实验板上后正常,单独测试每个发光管也正常。请教大 ...…

查看全部问答∨

七段数码管不够亮

本人现在在毕业设计中遇到了一个问题,就是我在显示年月日时分秒的时候如果在显示程序中加入了延时子程序,这时的LED数码管会比较亮,但是这样也造成了秒的显示时快时慢,但是如果我不在显示子程序中加入延时子程序,这时秒的显示正确了,但是七段 ...…

查看全部问答∨

请教关于 : ADS那个BOOT和EBOOT的区别??

修改EBOOT还是卡在打开MMU之后 晕了 想问一下ADS1.2写的那个BOOTLOADER(不知道应该怎么称呼这个BOOT,貌似叫VIVI??) 跟EBOOT有多大区别 是不是ADS1.2写的那个BOOTLOADER不需要用到CE下的OEMAddressTable  ??? 我发现我只要一修 ...…

查看全部问答∨

读flash的id号

    目标板式270的,原来用的板子上的flash是intel的E28F128J3,现在的flash是AMD的S29GL128N,用了两片,单片16M.进行如下id号的执行语句 typedef unsigned short U16; typedef unsigned int   U32; #include "norflash. ...…

查看全部问答∨

小妹想求购一块二手arm开发板

因为本人课题需要,需购买一块二手开发板用于视频监控,时间有限,最好是一块已经用来研究开发过一段时间的板子,这样一方面可以减少一部分的工作,也好入手学习,如有请留联系方式,小妹不甚感激…

查看全部问答∨

EVC4.0通过ADOCE31访问CDB数据库,不能定义主键和字段非空吗?

EVC4.0通过ADOCE31访问CDB数据库,不能定义主键吗?只要不添加主键,数据表可以正常建立。一旦添加主键,执行sql语句就报错。 我还发现不支持定义字段为非空,一旦加上not null,数据表建立就失败。是CDB数据库的问题吗?我很需要主键这项功能,不 ...…

查看全部问答∨

请问谁知道现在USB一拖四的芯片名称 谢谢

请问谁知道现在USB一拖四的芯片名称 谢谢…

查看全部问答∨

LED 显示屏的应用领域

LED 显示屏产品系列很多,根据使用环境分为室内显示屏和室外显示屏两类;根据发光像素的大小分为φ3mm、φ3.75mm、φ5mm、φ8mm、φ1 5 mm、φ1 9mm 和φ20MM等几种;根据发光像素的颜色分为单色、红绿双基色、红绿蓝( RGB)三基色全彩屏等;根据 ...…

查看全部问答∨

ADI+芯片申请问题

ADI芯片芯片申请时账号注册了几次,我用的是我的QQ邮箱,但是不知道为何收不到激活链接。是不是不是可以用自己的QQ邮箱。我看TI的都可以。不知道为什么,望解答…

查看全部问答∨

在altium desiner破解中如何去除标题上的not signed in

请问dxp破解后在标题上出现下图样,如何去掉not signed in…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved