STM32单片机(五)-寄存器地址理解和控制LED闪烁

芯片: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);
		
		
	}
	
}

猜你喜欢

转载自blog.csdn.net/fzf1996/article/details/89004566