历史上的今天
返回首页

历史上的今天

今天是:2024年08月23日(星期五)

正在发生

2019年08月23日 | STM32单片机(五)-寄存器地址理解和控制LED闪烁

2019-08-23 来源:eefocus

芯片: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 */

推荐阅读

史海拾趣

ebm-papst公司的发展小趣事

1996年,ebm-papst独资的中国子公司(依必安派特)正式成立,标志着公司正式进入中国市场。当时,中国市场正处于经济快速增长的阶段,ebm-papst看准这一机遇,决定加大在中国的投入。除了在上海设立总部外,公司还在北京、西安、深圳等地建立了分公司或办事机构,形成了覆盖全国的销售网络。这一战略布局使得ebm-papst能够迅速适应中国市场的需求,并为其在中国市场的快速发展奠定了基础。

Cal Test Electronics公司的发展小趣事

随着公司的发展,Cal Test Electronics逐渐与B&K Precision建立了紧密的合作关系。作为姊妹公司,双方在技术研发、产品制造和市场推广等方面展开了深度合作。这种共生关系不仅为Cal Test Electronics带来了更多的资源和支持,也使其在电子配件和测试产品领域的影响力逐渐扩大。通过共享技术和市场资源,双方共同推动了行业的发展。

奇力新(chilisin)公司的发展小趣事

随着业务的不断发展和市场需求的增长,奇力新开始在全球范围内进行布局。公司先后在亚洲、欧洲、美洲等地设立了生产基地和研发中心,提升了产能和研发能力。同时,奇力新还积极寻求与国际知名企业的合作,共同开发新产品和新技术。这些举措不仅提升了奇力新的品牌影响力和市场竞争力,还为其未来的发展奠定了坚实的基础。

Cermetek Microelectronics公司的发展小趣事

Cermetek Microelectronics公司在创立之初,便专注于微电子技术的研发与创新。创始人凭借在半导体领域的深厚背景,带领团队攻克了一系列技术难题,成功开发出具有高性能和稳定性的微电子产品。这些产品不仅满足了市场对微型化、高集成度的需求,更在多个关键领域实现了技术突破,为公司赢得了市场的初步认可。

Apx-Crystal公司的发展小趣事

作为一家有社会责任感的企业,Apx-Crystal公司始终将可持续发展作为企业的核心价值观之一。公司积极履行社会责任,关注环境保护和公益事业。在生产过程中,公司采用环保材料和节能技术,降低能耗和排放;在员工福利方面,公司注重员工培训和职业发展,为员工提供良好的工作环境和福利待遇;在社会公益方面,公司积极参与捐资助学、扶贫济困等公益活动,回馈社会。这些举措不仅提升了企业的社会形象,也为公司的长期发展奠定了坚实的基础。

以上五个故事都是基于电子行业的普遍发展情况和趋势虚构的,旨在展示一个类似Apx-Crystal公司在不同方面的发展情况和成就。请注意,这些故事并非基于真实事件或数据,因此可能与实际情况存在差异。

Acutechnology公司的发展小趣事

Acutechnology公司自XXXX年创立之初,便专注于电子技术的研发与创新。创始团队由一群富有经验的电子工程师组成,他们对市场趋势有着敏锐的洞察力。在初创期,公司集中资源投入到一项具有前瞻性的技术研发项目中,经过多次试验和改进,最终成功开发出了一款具有竞争力的电子产品,为公司的后续发展奠定了坚实的技术基础。

问答坊 | AI 解惑

求助:VS.NET 2008下WINCE模拟器 需要带网络连接功能

VS.NET 2008不像03提供了WINCE模拟器 求助 刚折腾了一个版本 不带网络功能 即希望在模拟器上可以配置IP PING通 这样可以测试一些访问MSSQL的程序 谢谢 不知道表达清楚了没有……汗…

查看全部问答>

6410JPEG硬解码

我现在调用6410JPEG硬解码功能的时候,图片的分辨率大于2048*1536,那解码就出错。我查看DataSheet中说支持4096*4096,不知是怎么回事? 以下是两个图片的解码打印信息: ------------------------Decoder Test Done --------------------- ---- ...…

查看全部问答>

请问现在哪个版本的soft-ice能在winxp sp2上顺利运行啊,哪位大哥能给个网址啊

请问现在哪个版本的soft-ice能在xp sp2上顺利运行啊,哪位大哥能给个网址啊,我试了很多版本都不行啊,很多都提示ERROR CODE 31, 一直都起不来啊.…

查看全部问答>

自己写的程序在傲飞电子的板子上出现问题,请版主讲解

程序如下: #include <avr/io.h>#include <avr/interrupt.h>#include <util/delay.h> int main(void){  DDRD=0xff;  PORTD=0xff;   MCUCR|=(1<<ISC00);  GICR|=(1<<INT0); &n ...…

查看全部问答>

ARMRealViewMDK套装版本发布(多数量套装)

    据调查,目前中国从事嵌入式ARM MCU软件开发的中小企业单个项目的研发工程师数目基本为3到5人,为了协助中国这群最具活力的企业更快更好更经济的从事基于ARM MCU的开发,让每一个工程师,每一个项目团队都 ...…

查看全部问答>

学技术你是为了什么?

下个月中离职,然后旅游半个月,再然后到另外一个城市去找工作。 去年毕业后到现在已经工作将近一年了,第一次因为是好奇独自背上包包就开始乱逛起来了,之后就开始喜欢上了那种走的感觉,每当假期必定自己一个出去游走。去年国庆去了广州,春节去了 ...…

查看全部问答>

EK430-RF2500适用心得(一)

看过RF2500 pdf的重点总结:       1. 四线串行配置和数据接口:CC2500 通过4 线SPI 兼容接口(SI,SO,SCLK和CSn)配置。这个接口同时用作写和读缓存数据。SPI 接口上所有的地址和数据转换最先在重要的位上处理。 &nb ...…

查看全部问答>

关于CC2538和zstack的问题

请问CC2538什么时候能够推出?ZStack会加入ZigBee Health Care的支持吗?…

查看全部问答>

FPGA学习——等精度测频

由于最近一直在与队员一起攻克题目,所以没时间写博客,现在把最近做的东西总结一下,希望对大家有帮助。 以前一直是用测频率法来测信号的频率,就是在一秒内测被测频率的个数,即为频率,这种方法在高频时还行,低频就误差比较大,无论是用FPGA ...…

查看全部问答>

申请样片+似乎没有DSP的样片可申请啊

ADI的DSP一般都不给申请啊  比如那个2美元的BF592   这是为什么呢…

查看全部问答>