STM32单片机学习笔记(二)-点亮LED灯(寄存器版)(二)

写在前面:本系列内容均为自学笔记,参考资料为野火指南者开发板资料及芯片参考手册等,使用野火指南者开发板进行学习,该系列内容仅用于记录笔记,不做其他用途,笔记的内容可能会存在不准确或者错误等,如有大佬看到错误内容还望能够评论指正,感谢各位。
本节包括前一节的程序,请参考野火开发板资料,里面由更加清晰的教学,野火B站账号:野火官方B站账号链接。
本节内容与上一节(STM32单片机学习笔记(二)-点亮LED灯(寄存器版)(一))的内容相关,在上一节的基础上进一步学习优化。

学习目标

1、进行寄存器映射,并使用寄存器点亮LED灯;
2、操作GPIOx_BSRR或者GPIOx_BRR寄存器,点亮或者熄灭LED灯;

一、寄存器映射,点亮LED灯

本节用到以下电路图:
图2-1:绿色LED灯点灯电路
STM32单片机学习笔记(二)-点亮LED灯(寄存器版)(二)_第1张图片
先看一下来自芯片官方参考手册的关于寄存器及其地址的表格,共截图3张,参考英文版手册,当然中文版手册也有这几个表格;
图2-2:寄存器及其地址(截图来自官方参考手册,共截图3张)
STM32单片机学习笔记(二)-点亮LED灯(寄存器版)(二)_第2张图片
STM32单片机学习笔记(二)-点亮LED灯(寄存器版)(二)_第3张图片
STM32单片机学习笔记(二)-点亮LED灯(寄存器版)(二)_第4张图片
以上表格我们着重看总线APB1、APB2、AHB基地址,GPIOB、RCC基地址;除此之外还要看GPIOB各个寄存器偏移地址,RCC中RCC_APB2ENR寄存器偏移地址;
表2-1:寄存器偏移地址

寄存器名称 偏移地址
RCC_APB2ENR 0x18
GPIOB_CRL 0x00
GPIOB_CRH 0x04
GPIOB_IDR 0x08
GPIOB_ODR 0x0C
GPIOB_BSRR 0x10
GPIOB_BRR 0x14
GPIOB_LCKR 0x18

上面的表格是RCC部分寄存器及GPIO寄存器的偏移地址;
表2-2:总线地址及偏移

总线名称 总线地址 外设基地址 偏移地址
APB1 0x40000000 0x40000000 0x00000
APB2 0x40010000 0x40000000 0x10000
AHB 0x40018000 0x40000000 0x18000

上面的表格是总线的地址及偏移地址;
由上面的表格和图片可以看出APB1基地址为0x4000000,APB2基地址为0x40010000,AHB基地址为0x40018000,于是可以进行以下寄存器映射:
下列程序可放至stm32f10x.h文件中,前提该文件为空,上节内容有提到:

//stm32f10x.h文件中的内容,存放用于寄存器映射的程序
//外设英文:peripheral,本程序简写为PERIPH
//十六进制的加减法,不要用十进制加减法算,两种方式结果不一样

#define PERIPH_BASE 						((unsigned int)0x40000000)  //外设基地址,不做强制转换,方便后面进行宏定义
#define APB1PERIPH_BASE 					(PERIPH_BASE + 0x00000)		//APB1总线基地址
#define APB2PERIPH_BASE						(PERIPH_BASE + 0x10000)		//APB2总线基地址
#define AHBPERIPH_BASE						(PERIPH_BASE + 0x18000)		//AHB总线基地址

#define RCC_BASE							(AHBPERIPH_BASE + 0x9000)		//RCC寄存器基地址
#define GPIOB_BASE							(APB2PERIPH_BASE + 0x0C00)	//GPIO寄存器基地址

#define RCC_APB2ENR							*(unsigned int*)(RCC_BASE + 0x18)		//APB2外设时钟使能寄存器地址,强制转换
	
#define GPIOB_CRL							*(unsigned int*)(GPIOB_BASE + 0x00)		//GPIOB端口配置低寄存器地址,强制转换
#define GPIOB_CRH							*(unsigned int*)(GPIOB_BASE + 0x04)		//GPIOB端口配置高寄存器地址,强制转换
#define GPIOB_ODR							*(unsigned int*)(GPIOB_BASE + 0x0C)		//GPIOB端口输出数据寄存器地址,强制转换

通过以上程序即可将相关寄存器进行映射,在之后使用时直接使用相关寄存器的名字即可实现功能,功能程序会简化一些;
main.c中的程序如下:

#include "stm32f10x.h"

int main(void)
{
	//使能GPIOB时钟
	RCC_APB2ENR |= (1<<3);
	//设置端口为输出模式,速率为10MHz
	GPIOB_CRL &= ~(1<<(4*0));	//防止其他程序影响配置,先将第0位的4位数值清零
	GPIOB_CRL |= (1<<(4*0));
	//设置PB0_0为低电平
	GPIOB_ODR &= ~(1<<0);
}

void SystemInit(void)
{
	//函数体为空,目的是骗过编译器
}


以上程序即为点灯程序,相较于学习笔记1中的点灯程序,本程序可以直观的看到使用的是什么寄存器,也更加简洁,当然前提是先进行正确的寄存器映射。

二、操作GPIOx_BSRR及GPIOx_BRR寄存器控制LED灯

首先看以下GPIOx_BSRR寄存器相关介绍:
图2-3:GPIOx_BSRR寄存器(截图来自官方参考手册)
STM32单片机学习笔记(二)-点亮LED灯(寄存器版)(二)_第5张图片
1、通过BSRR寄存器点亮LED灯
由图2-3可知,GPIOx_BSRR寄存器低16位负责将ODR寄存器置1,高16位负责置0,,根据这个特点,可以得到下面的程序,以实现控制LED灯:
stm32f10x.h文件程序如下,其中加入了GPIOB_BSRR和GPIOB_BRR两个寄存器的映射程序:

//stm32f10x.h文件中的内容,存放用于寄存器映射的程序
//外设英文:peripheral,本程序简写为PERIPH
//十六进制的加减法,不要用十进制加减法算,两种方式结果不一样

#define PERIPH_BASE 							((unsigned int)0x40000000)  //宏定义外设基地址,不做强制转换,方便后面进行宏定义
#define APB1PERIPH_BASE 						(PERIPH_BASE + 0x00000)		//APB1基地址
#define APB2PERIPH_BASE							(PERIPH_BASE + 0x10000)		//APB2基地址
#define AHBPERIPH_BASE							(PERIPH_BASE + 0x18000)		//AHB基地址

#define RCC_BASE								(AHBPERIPH_BASE + 0x9000)	//RCC寄存器基地址
#define GPIOB_BASE								(APB2PERIPH_BASE + 0x0C00)	//GPIO寄存器基地址

#define RCC_APB2ENR								*(unsigned int*)(RCC_BASE + 0x18)		//APB2外设时钟使能寄存器地址,强制转换
	
#define GPIOB_CRL								*(unsigned int*)(GPIOB_BASE + 0x00)		//GPIOB端口配置低寄存器地址,强制转换
#define GPIOB_CRH								*(unsigned int*)(GPIOB_BASE + 0x04)		//GPIOB端口配置高寄存器地址,强制转换
#define GPIOB_ODR								*(unsigned int*)(GPIOB_BASE + 0x0C)		//GPIOB端口输出数据寄存器地址,强制转换
#define GPIOB_BSRR								*(unsigned int*)(GPIOB_BASE + 0x10)		//GPIOB端口位设置/清除寄存器地址,强制转换
#define GPIOB_BRR								*(unsigned int*)(GPIOB_BASE + 0x14)		//GPIOB端口位清除寄存器地址,强制转换


main.c中的程序如下:

#include "stm32f10x.h"

int main(void)
{
	//使能GPIOB时钟
	RCC_APB2ENR |= (1<<3);
	//设置端口为输出模式,速率为10MHz
	GPIOB_CRL &= ~(1<<(4*0));		//防止其他程序影响配置,先将第0位的4位数值清零
	GPIOB_CRL |= (1<<(4*0));
	//设置PB0_0为低电平
	GPIOB_ODR |= 1<<0;				//先将ODR寄存器相关位置1,熄灭LED灯
	GPIOB_BSRR |= (1<<16);			//清零ODR寄存器第0位
}

void SystemInit(void)
{
	//函数体为空,目的是骗过编译器
}


main.c中的程序先对GPIOB_ODR进行操作,将其置1,这主要是为了排除ODR寄存器复位值的影响,ODR寄存器复位值为0x00000000,这会影响后续程序;将ODR寄存器置1后,LED灯将会处于熄灭状态,此时使用BSRR寄存器将相应位置0即可将LED灯点亮。
2、通过BSRR寄存器熄灭LED灯
main.c中程序如下:

#include "stm32f10x.h"

int main(void)
{
	//使能GPIOB时钟
	RCC_APB2ENR |= (1<<3);
	//设置端口为输出模式,速率为10MHz
	GPIOB_CRL &= ~(1<<(4*0));		//防止其他程序影响配置,先将第0位的4位数值清零
	GPIOB_CRL |= (1<<(4*0));
	//设置PB0_0为低电平
	GPIOB_ODR &= ~(1<<0);			//点亮LED灯
	GPIOB_BSRR |= (1<<0);			//置1ODR寄存器第0位
}

void SystemInit(void)
{
	//函数体为空,目的是骗过编译器
}


由于ODR寄存器复位为0,所以不对ODR寄存器操作LED灯也会亮,当ODR寄存器中第0位为0时LED灯亮,此时使用BSRR寄存器将该位置1,此时LED灯为熄灭状态。
3、通过BRR寄存器点亮LED灯
先看一下GPIOx_BRR寄存器相关介绍,分为两个截图:
图2-4:GPIOx_BRR寄存器(截图来自官方参考手册,2个截图)
STM32单片机学习笔记(二)-点亮LED灯(寄存器版)(二)_第6张图片
STM32单片机学习笔记(二)-点亮LED灯(寄存器版)(二)_第7张图片
通过图2-4可知,BRR寄存器只能会ODR寄存器进行清0,所以根据这个特点,得到以下程序:

#include "stm32f10x.h"

int main(void)
{
	//使能GPIOB时钟
	RCC_APB2ENR |= (1<<3);
	//设置端口为输出模式,速率为10MHz
	GPIOB_CRL &= ~(1<<(4*0));		//防止其他程序影响配置,先将第0位的4位数值清零
	GPIOB_CRL |= (1<<(4*0));
	//设置PB0_0为低电平
	GPIOB_ODR |= (1<<0);			//先将ODR寄存器相关位置1,熄灭LED灯
	GPIOB_BRR |= (1<<0);			//ODR寄存器第0位置0
}

void SystemInit(void)
{
	//函数体为空,目的是骗过编译器
}


程序中,先将LED灯熄灭,排除干扰,再操作BRR寄存器点亮LED灯。

以上仅作笔记参考,不做教学,感谢观看。

你可能感兴趣的:(笔记,STM32单片机学习笔记,单片机,stm32,学习)