【STM32】GPIO控制LED(寄存器版)

【STM32】GPIO控制LED(寄存器版)_第1张图片

 在开始之前记得先准备好环境:

STM32F103核心板下载教程.pdf · 林何/STM32F103C8 - 码云 - 开源中国 (gitee.com)

一、STM32的GPIO模块数据手册详解

每个GPIO端口对应16个引脚,例GPIOA(PA0~PA15)
内核cpu就可以通过APB2总线对寄存器读写,完成输出电平和读取电平的功能

 1.GPIO和APIO

GPIO:通用输入/输出IO

APIO:备用输入/输出IO

2.GPIO功能描述

【STM32】GPIO控制LED(寄存器版)_第2张图片

3.配置模式

【STM32】GPIO工作原理(八种工作方式超详细分析,附电路图)-CSDN博客

1.输入浮动,输入上拉,输入下拉(数字状态)

都是数字模式,数字IO,只关心电平是1还是0

输入浮空:就是当电平输入进来后,直接输入到寄存器中【不对其进行操作】

输入上拉:在内部有一个上拉电阻(将电平拉高),只能外部接地,才能将电平拉低,如果TTL肖特基触发器:输入的是高电平或者干扰信号,则会将其过滤调。

2.模拟输入(模拟状态)

AD转换

可以工作在模拟电路或者数字电路

3.输出

开漏输出

【STM32】GPIO控制LED(寄存器版)_第3张图片

推挽输出

【STM32】GPIO控制LED(寄存器版)_第4张图片

4.备用

将不用的引脚配置成备用引脚(GPIO)才可以被使用

【STM32】GPIO控制LED(寄存器版)_第5张图片

4.输出字节数控制

1)输出32位字:使用GPIO_CRL---效率低,但是兼容性好

2)输入小于32位字:使用CPIOx_BSRR--效率高,但是兼容性差

5.I/O 端口位框图

【STM32】GPIO控制LED(寄存器版)_第6张图片

6.端口位配置表

【STM32】GPIO控制LED(寄存器版)_第7张图片

7.输出模式位

【STM32】GPIO控制LED(寄存器版)_第8张图片

8.外部中断/唤醒线

将IO口和相对应的中断映射起来

【STM32】GPIO控制LED(寄存器版)_第9张图片

9.GPIO寄存器描述

1. 端口配置低寄存器(GPIOx_CRL)

由于每个GPIO口需要4位来进行配置输入输出模式(2位配置MODE,2位配置CNF),这样的话每组16个GPIO口则需要64位,这也就表明需要两个32位寄存器。于是GPIOx_CRL用于配置GPIO0-GPIO7的输入输出模式。同理GPIOx_CRH则用于配置GPIO8-GPIO15的输入输出模式。

控制PX0---PX7引脚工作模式

四个位控制一个引脚

【STM32】GPIO控制LED(寄存器版)_第10张图片

【STM32】GPIO控制LED(寄存器版)_第11张图片

【STM32】GPIO控制LED(寄存器版)_第12张图片

【STM32】GPIO控制LED(寄存器版)_第13张图片

2. 端口配置高寄存器(GPIOx_CRH)

控制PX8---PX15引脚工作模式

【STM32】GPIO控制LED(寄存器版)_第14张图片

【STM32】GPIO控制LED(寄存器版)_第15张图片

【STM32】GPIO控制LED(寄存器版)_第16张图片

3.端口输入数据寄存器(GPIOx_IDR) 

【STM32】GPIO控制LED(寄存器版)_第17张图片

4. 端口输出数据寄存器(GPIOx_ODR)

【STM32】GPIO控制LED(寄存器版)_第18张图片

5. 端口位设置/复位寄存器(GPIOx_BSRR)

如果想要将bit7和bit6置为0,则表示要将bit7和bit6写为1,其他位置为0

对复位上写1表示复位

对置位上写1表示置为

【STM32】GPIO控制LED(寄存器版)_第19张图片

【STM32】GPIO控制LED(寄存器版)_第20张图片

如果置位和复位同时设置,则置位起作用。

6.端口位复位寄存器(GPIOx_BRR)

【STM32】GPIO控制LED(寄存器版)_第21张图片

7.端口配置锁定寄存器(GPIOx_LCKR)

【STM32】GPIO控制LED(寄存器版)_第22张图片

8.复用功能I/O和调试配置(AFIO)

【STM32】GPIO控制LED(寄存器版)_第23张图片

二、原理图分析

1.硬件接线

1)杜邦线连接到P0端口到LCD的J19接口,这样相当于8个LED分别对应PB8-PB15

2)因为GPIO接到LCD的负极,所以输入0亮,输入1暗

【STM32】GPIO控制LED(寄存器版)_第24张图片

【STM32】GPIO控制LED(寄存器版)_第25张图片

三、MDK工程建立

与前面51建立工程是一样的

1.注意点1:

【STM32】GPIO控制LED(寄存器版)_第26张图片

【STM32】GPIO控制LED(寄存器版)_第27张图片

【STM32】GPIO控制LED(寄存器版)_第28张图片

【STM32】GPIO控制LED(寄存器版)_第29张图片

2.注意点2:

单片机中用到的c语言其实不是原始c语言,而是有点定制性c语言

之前认识:整个程序从main函数开始执行,main执行完整个程序就结束

起始代码:从CPU复位开始执行的第一句指令,到main函数之前所做的事情就是起始代码

3.起始代码

1)起始代码是从哪里来的:编译环境提高的,STM32CPU提供的

2)不同CPU的起始代码一般是不同的

3)起始代码是用汇编写的

【STM32】GPIO控制LED(寄存器版)_第30张图片

【STM32】GPIO控制LED(寄存器版)_第31张图片

四、写代码控制GPIO点亮和熄灭

1.寄存器现象确认

我们使用的是P0端口(对应PB8-PB15),所以我们要去对应查找PB的寄存器起始地址

1)STM32 PortB的起始是0x4001 0c00

【STM32】GPIO控制LED(寄存器版)_第32张图片

【STM32】GPIO控制LED(寄存器版)_第33张图片

2.有可能使用到的GPIO的地址:

因为我们是PB8-PB15,所以我们只使用CRH

【STM32】GPIO控制LED(寄存器版)_第34张图片

3.C语言操作寄存器

1)ARM是内存与IO统一编址的,所以ARM中的所有外设都是通过寄存器的方式来操作的

2)每一个寄存器都有地址,c语言通过这些地址来操作这些寄存器位,用到的c语言的技巧主要是c与的位操作和c语言指针

3)常见面试题:用c语言向内存地址0x3000 0004写入16

        *(unsigned int *)0x3000 0004=16;

等价于

        unsigned int *p=(unsigned int *)0x3000 0004;

        *p=16;

4.解析寄存器

1.端口配置高寄存器(GPIOx_CRH)-高8位

	//向CRH寄存器写内容,将GPIO_GPB15配置为输出模式【此时高位有用】
	//推挽输出模式,输出的速率为50MHZ【0011 0011 0011 0011.。。】
	*((unsigned int *)GPIOB_CRH)=0x33333333;//表示将GPIO_CRH的值设置为0x33333333

【STM32】GPIO控制LED(寄存器版)_第35张图片

2.端口输出数据寄存器(GPIOx_ODR)

	//向CRH寄存器写内容,将GPIO_GPB15配置为输出模式【此时高位有用】
	//推挽输出模式,输出的速率为50MHZ【0011 0011 0011 0011.。。】
	*((unsigned int *)GPIOB_CRH)=0x33333333;//表示将GPIO_CRH的值设置为0x33333333

【STM32】GPIO控制LED(寄存器版)_第36张图片

5.注意点:

【STM32】GPIO控制LED(寄存器版)_第37张图片

记得在操作GPIO的时候要先打开时钟

【STM32】GPIO控制LED(寄存器版)_第38张图片

【STM32】GPIO控制LED(寄存器版)_第39张图片

#define GPIOB_CRH		0x40010C04
#define GPIOB_ODR		0x40010C0C

#define RCC_APB2ENR		0x40021018

void main(void){
	
	//STM32所有外设默认关闭
	//所以我们在打开时钟
	*((unsigned int *)RCC_APB2ENR)=0x00000008;

	//向CRH寄存器写内容,将GPIO_GPB15配置为输出模式
	//推挽输出模式,输出的速率为50MHZ【0011 0011 0011 0011.。。】
	*((unsigned int *)GPIOB_CRH)=0x33333333;//表示将GPIO_CRH的值设置为0x33333333
	
	//输出1,点亮LED
	//ff:对应15-8位
	*((unsigned int *)GPIOB_ODR)=0x0000f000;
	
	while(1);
	
}

五、其他寄存器的测试

1.端口位设置/清除寄存器(GPIOx_BSRR)

【STM32】GPIO控制LED(寄存器版)_第40张图片

将bit8-bit15置0(变亮),因为我们前面是使用了GPIO_GRH(所以只能控制8-15个引脚),所以此时改变0-7是无效的

	//使用寄存器【GPIOB_BSRR】:将bit8-bit15置0(此时表示全亮) 
	//*((unsigned int *)GPIOB_BSRR)=0x00000000;
	//因为前面我们是控制GPIOB_CRH,所以只有8-15位才起效果,0-7无论设置什么都无所谓
	//*((unsigned int *)GPIOB_BSRR)=0x000000ff;//此时全亮,与上面效果一样
	
	//0101 0101
	//*((unsigned int *)GPIOB_BSRR)=0x00005500;//此时2,4,6,8亮
	
	//此时led1,led3不亮,其他亮
	//使用置位
	*((unsigned int *)GPIOB_BSRR)=0x00005500;//此时2,4,6,8亮
	//使用复位:将高4位全部复位
	*((unsigned int *)GPIOB_BSRR)=0xf0000000;

2.端口位清除寄存器(GPIOx_BRR)

【STM32】GPIO控制LED(寄存器版)_第41张图片

只能操作bit0-bit15

BRR:只能用来复位,不能置位(所以只能将其置为0,而不能置为1)

    //使用寄存器【GPIOB_BRR】:将bit8-bit15置0(此时表示全亮) 
	//GPIOB_BRR:只能进行复位(意思是只能将电平置为0)
	//前面16-32是无效位
	*((unsigned int *)GPIOB_BRR)=0x00000000;//全亮
	*((unsigned int *)GPIOB_BRR)=0x0000ffff;//全亮
	//*((unsigned int *)GPIOB_BRR)=0x0000ff00;//只亮高4位(led的4-7)
	

六、总结

对数据操作的三种方法:

ODR:可以进行任何操作,但是只能一次性操作32位,效率低,但是移植性高【其次考虑】

BSRR:原子操作,效率高;移植性差【优先考虑】

BRR:只能进行复位,不能置位,原子操作,效率高;移植性差

1.代码

#define GPIOB_CRH		0x40010C04
#define GPIOB_CRL		0x40010C00
#define GPIOB_ODR		0x40010C0C
#define GPIOB_BSRR	0x40010C10
#define GPIOB_BRR		0x40010C14

#define RCC_APB2ENR		0x40021018

void main(void){
	
	//STM32所有外设默认关闭
	//所以我们在打开时钟
	*((unsigned int *)RCC_APB2ENR)=0x00000008;

	//向CRH寄存器写内容,将GPIO_GPB15配置为输出模式【此时高位有用】
	//推挽输出模式,输出的速率为50MHZ【0011 0011 0011 0011.。。】
	*((unsigned int *)GPIOB_CRH)=0x33333333;//表示将GPIO_CRH的值设置为0x33333333
	
	//输出0,点亮LED
	//ff:对应15-8位
	//*((unsigned int *)GPIOB_ODR)=0x00000000;
	
	
	//使用寄存器【GPIOB_BSRR】:将bit8-bit15置0(此时表示全亮) 
	//*((unsigned int *)GPIOB_BSRR)=0x00000000;
	//因为前面我们是控制GPIOB_CRH,所以只有8-15位才起效果,0-7无论设置什么都无所谓
	//*((unsigned int *)GPIOB_BSRR)=0x000000ff;//此时全亮,与上面效果一样
	
	//0101 0101
	//*((unsigned int *)GPIOB_BSRR)=0x00005500;//此时2,4,6,8亮
	
	//此时led1,led3不亮,其他亮
	//使用置位
	//*((unsigned int *)GPIOB_BSRR)=0x00005500;//此时2,4,6,8亮
	//使用复位:将高4位全部复位
	//*((unsigned int *)GPIOB_BSRR)=0xf0000000;
	
	//使用寄存器【GPIOB_BRR】:将bit8-bit15置0(此时表示全亮) 
	//GPIOB_BRR:只能进行复位(意思是只能将电平置为0)
	//前面16-32是无效位
	*((unsigned int *)GPIOB_BRR)=0x00000000;//全亮
	*((unsigned int *)GPIOB_BRR)=0x0000ffff;//全亮
	//*((unsigned int *)GPIOB_BRR)=0x0000ff00;//只亮高4位(led的4-7)
	
	while(1);
	
}

2.对宏定义的封装

【STM32】GPIO控制LED(寄存器版)_第42张图片

#define GPIOB_CRH		0x40010C04
#define GPIOB_CRL		0x40010C00
#define GPIOB_ODR		0x40010C0C
#define GPIOB_BSRR	0x40010C10
#define GPIOB_BRR		0x40010C14

#define RCC_APB2ENR		0x40021018

#define rGPIOB_CRH 		(*((unsigned int *)GPIOB_CRH))
#define rGPIOB_ODR 		(*((unsigned int *)GPIOB_ODR))
#define rGPIOB_BSRR 	(*((unsigned int *)GPIOB_BSRR))
#define rGPIOB_BRR 		(*((unsigned int *)GPIOB_BRR))
#define rRCC_APB2ENR 	(*((unsigned int *)RCC_APB2ENR))

void main(void){
	rRCC_APB2ENR = 0x00000008;

	rGPIOB_CRH = 0x33333333;
	rGPIOB_ODR = 0x0000aa00;
}

你可能感兴趣的:(STM32,stm32,嵌入式硬件,单片机)