STM32-寄存器-点灯

使用寄存器点亮LED灯

一、LED原理

由电路图可以看到,LED0右端连接3.3高电平电压,左侧对应PB5端口。所以当PB5=0时,会形成从右向左的电流。LED灯点亮。

在这里插入图片描述
在这里插入图片描述

二、端口值的输出-(GPIOx_ODR) (x=A…E)

因为LED接的端口是PB5,所以对应了GPIOB_ODR
在这里插入图片描述
代码:

*( unsigned int * )0x40010C0C &= ~( 1 << 5 ) ;

在这里插入图片描述

  1. 0x40010C0C:在参考手册中查找存储器映射,可以查到GPIO寄存器的起始地址。GPIOB起始地址0x40010C00+ODR寄存器地址偏移0Ch(h表示16进制),所以为0x40010C0C
  2. ( unsigned int * )0x40010C0C &= ~( 1 << 5 ) :
    等价于
    ( unsigned int * )0x40010C0C &= ~(0010 0000)
    等价于*( unsigned int * )0x40010C0C=(0000 0000)&(1101 1111)
    等价于*( unsigned int * )0x40010C0C=1101 0000

操作中,常用 置位 |= ,清零 &=~

三、使端口模式为输出模式

每四位对应ODR中的1位,所以对于PB5来说,就是CRL中的20,21,22,23四位控制,要想使PB5端口为输出电压模式,要将CNF置为00,MODE置为01,偏移地址为0x00,实际地址即为0x40010C00
在这里插入图片描述

	*( unsigned int * )0x40010C00 |=( (1) << (4*5) ) ;	

四、打开端口时钟控制

时钟相当于单片机的心脏,任何程序的运行需要先将时钟使能
在这里插入图片描述

在这里插入图片描述
PB端口是第3位控制

*( unsigned int * )0x40021018 |=( 1 << 3  )

所以在RCC寄存器中,第3位的值要置1,才能开启B时钟,端口才能正常工作

完整代码

#include "stm32f10x.h"

int main(void)
{
	*( unsigned int * )0x40021018 |=( 1 << 3  )	;									//打开GPIO端口的时钟
	
	*( unsigned int * )0x40010C00 |=( (1) << (4*5) ) ;						// 配置IO口为输出
	
	*( unsigned int * )0x40010C0C &= ~( 1 << 5 ) ;								// 控制 ODR 寄存器
	

}


//置位 |=  ,清0 &=~

void SystemInit(void)
{
	//函数体为空,为了不报错
}


改进

代码是直接通过地址来进行位操作的,可读性差。用寄存器外设来达到类似51单片机P0=1/0这样的效果。

操作时需要查阅STM32参考手册:
在这里插入图片描述
三条总线:APB1,APB2,AHB
参考存储器映像查看它们的起始地址
在这里插入图片描述
AHB起始地址:0x4001 8000,但是为了后面数据操作方便,将0x4002 0000设置为起始地址
在这里插入图片描述
APB2起始地址:0x4001 0000
在这里插入图片描述
AHB1起始地址:0x4000 0000
总代码如下:

//用来存放STM32寄存器映射的代码
//外设 peripheral

//首先定义外设的基地址
#define PERIPH_BASE  					((unsigned int)0x40000000)

#define APB1PERIPH_BASE					PERIPH_BASE

//APB2在基地址上+1000
#define APB2PERIPH_BASE					(PERIPH_BASE+0x10000)

//AHP同理
#define AHBPERIPH_BASE					(PERIPH_BASE+0x20000)

//时钟RCC
#define RCC_BASE						(AHBPERIPH_BASE +0x1000)

//开始定义寄存器
#define GPIOB_BASE						(APB2PERIPH_BASE +0x0C00)
#define RCC_APB2ENR						*(unsigned int *)(RCC_BASE+0x18)

#define GPIOB_CRL						*(unsigned int *)(GPIOB_BASE+0x00)
#define GPIOB_CRH						*(unsigned int *)(GPIOB_BASE+0x04)
#define GPIOB_ODR						*(unsigned int *)(GPIOB_BASE+0x0C)

寄存器代码映射完成后,原代码可以改为:

#include "stm32f10x.h"
int main(void)
{

while(1)
	{
		RCC_APB2ENR|=( 1 << 3  )	;						 //打开GPIO端口的时钟
		GPIOB_CRL  |=( (1) << (4*5) ) ;						// 配置IO口为输出
		GPIOB_ODR  &= ~( 1 << 5 ) ;								// 控制 ODR 寄存器
	}
}
void SystemInit(void)
{
	//函数体为空,为了不报错
}


在原先基础上, 建立GPIO_TypeDef结构体,就可以通过结构体的方式来访为寄存器

完整代码:

#define PERIPH_BASE  						((unsigned int)0x40000000)
#define APB1PERIPH_BASE					PERIPH_BASE
#define APB2PERIPH_BASE					(PERIPH_BASE+0x10000)
#define AHBPERIPH_BASE					(PERIPH_BASE+0x20000)

#define RCC_BASE								(AHBPERIPH_BASE +0x1000)
#define GPIOB_BASE							(APB2PERIPH_BASE +0x0C00)

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

typedef unsigned int			unit32_t;
typedef unsigned short		unit16_t;

typedef struct
{
  uint32_t CRL;
  uint32_t CRH;
  uint32_t IDR;
  uint32_t ODR;
  uint32_t BSRR;
  uint32_t BRR;
  uint32_t LCKR;
}GPIO_TypeDef;

#define GPIOB 		((	GPIO_Typedef*	)GPIOB_BASE)	
#include "stm32f10x.h"

int main(void)
{

while(1)
	{
		RCC_APB2ENR	|=( 1 << 3  )	;						//打开GPIO端口的时钟
	
		GPIOB->CRL  |=( (1) << (4*5) ) ;			// 配置IO口为输出
	
		GPIOB->ODR  &= ~( 1 << 5 ) ;					// 控制 ODR 寄存器
		
	}
}

void SystemInit(void)
{
	//函数体为空,为了不报错
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值