STM32学习笔记之:第二章GPIO

         由于现在学习的是以寄存器库为基础来实现功能,所以以后的知识点和代码都是以寄存器库来配置的,还有目前现在用的板子是STM32F407VET6,该笔记只是自己的见解和理解,大佬勿喷。

2.1GPIO口的介绍

2.1.1 什么是GPIO口&GPIO作用

        GPIO是什么?        GPIO:通用型输入输出接口        GP:General - Purpose     通用型

        什么是输出?  什么是输入?                站在芯片角度上,看数据方向

        输出:芯片将数据发送到外界  ;   输入:芯片接收外界数据

        作用:GPIO是单片机与外界进行信息交换的唯一窗口

        UART(串口)、SPI、IIC等片上外设也需要借助IO口才能跟外界进行信息交换

        单片机只能处理数字量   0   /   1        TTL电平      0 = 0V(低电平)       1  = 3.3V(高电平)

        IO可以给外界输出低电平  /   高电平        IO可以接受外界低电平/  高电平                        

        IO口也可以接收连续的模拟量,单片机不能处理模拟量数据,需要借助ADC(模数转换器)将模拟量转换为数字量,供单片机处理。

2.1.2 STM32的GPIO口

①GPIO数量

该怎么看GPIO口的数量呢?                               在这款芯片的数据手册---第二大点

管脚数量不代表有多少个IO  

        GPIO口数量决定了可以外接多少模块,GPIO口数量越多外接模块越多

②GPIO口的命名方式

GPIOA   ---    GPIOH :每一个GPIO端口都有16个管脚       GPIOI:有12个管脚

在STM32F407中只有GPIOA - GPIOE

GPIOA - GPIOE:80个管脚

GPIOH:PH0      PH1       外界晶振输出和输入管脚

GPIO命令:端口号 + 管脚号     PA1    PB2    PC3

2.1.3 GPIO口的八大模式

输出4种模式 和 输入四种模式

输入4种模式:

        上拉输入     数字量        带有上拉功能         弱上拉        IO默认电平为高电平     

        下拉输入     数字量        带有下拉功能         弱下拉        IO默认电平为低电平

        浮空输入     数字量        不带有上下拉功能      如果没有特殊需求,IO输入一般配置为浮空

        模拟输入     模拟量        接收模拟量,需要借助ADC转换

输出4种模式:

        通用推挽输出;通用开漏输出;复用推挽输出;复用开漏输出

        通用:作为普通IO口,实现普通IO输出的功能

        复用:复用输出一般与片上外设有关,如片上外设需要与外界进行信息交换,则对应IO需要配置为复用模式

        推挽:IO口既可以输出0(低电平),也可以输出1(高电平)

        开漏:IO口只能输出0(低电平),不能输出1(高电平)

2.1.4 GPIO控制器框图(重点)

        只要我们理解框图,我们就能知道如何配置寄存器和代码思路,我们后面要配置的所以东西都会按照这个思路去配置我们的一个寄存器。

        这是我们的GPIO框图,上下部分分别为输入模式和输出模式

输入部分框图:

        模拟输入:外界过来模拟量,通过ADC进行转换,将模拟量转换数字量,再给CM4进行处理

        复用输入:外界过来数据,通过斯密特触发器后,直接到片上外设的数据寄存器,如CM4需读取外界数据,则需要读取片上外设的数据寄存器

        输入模式:外界过来数据,通过斯密特触发器后,直接暂存到输入数据寄存器,如CM4需读取外界数据,则需要读取输入数据寄存器

输出部分框图:

        ①配置置位/复位寄存器,从而会影响输出数据寄存器,如置位/复位寄存器配置为置位状态,则输出数据寄存器为1(输出高电平);如置位/复位寄存器配置为复位状态,则输出数据寄存器为0(输出低电平)

        ②用户可直接往输出数据寄存器里面实现置位和清零操作,从而想外界输出数据0或者数据1

        ③片上外设需要向外界输出数据,则需要配置为复用模式

        ④输出数据为模拟量:内核把需要输出的数字量提供给DAC,DAC将数字量转换为模拟量后,直接输出给外界

2.1.5 GPIO寄存器

STM32单片机给我们工程师预留的接口为寄存器

1.什么是寄存器

        一般寄存器8bit 、16bit32bit无符号整型存储空间,里面存放命令/数据

2.对寄存器的操作

        其实寄存器都会有一个唯一独立的地址

该如何往地址赋值呢?        *(unsigned int *)0x80 = 10;

2.1.6 GPIO寄存器操作方法

方法一:

        举例:把10写入A组MODER寄存器中  (4字节)

A组MODER:*(unsigned int *)0x40020000 = 10;(指针类型:数据类型 *)  把10写入GPIOA_MODER

该方法缺点:不方便阅读代码

强转时:如果是地址->数据类型 *

                  如果是数据->数据类型

举例:把10写入B组OTYPER输出类型寄存器中  (4字节)

*(unsigned int *)0x4002 0404 = 10;

方法二:宏定义:增加了代码的阅读性  

#define GPIOA_MODER   *(unsigned int *)0x40020000

GPIOA_MODER = 10;

因为芯片上的寄存器非常多,定义宏定义会非常的麻烦

方法三:ST公司弄好了      包含芯片支持文件:stm32f4xx.h

用到寄存器的文件都需要把头文件包含过来  struct{};

芯片厂家已经做好了GPIOA->MODER

有用到寄存器的地方就需要把单片机头文件包含过来(寄存器定义都在单片机头文件中)

所以我们一般配置寄存器的方法都是用方法三

GPIOA->MODER = 10;
#define  GPIOA               ((GPIO_TypeDef *) GPIOA_BASE)//0x4002 0000
#define GPIOA_BASE            (AHB1PERIPH_BASE + 0x0000)
#define AHB1PERIPH_BASE       (PERIPH_BASE + 0x00020000)
#define PERIPH_BASE           ((uint32_t)0x40000000)
            0x4000 0000 + 0x0002 0000
            0x4000 0000 + 0x0002 0000 + 0x0000
            0x4002 0000(GPIOA组寄存器的起始地址)



GPIOA的基地址强制类型转化为GPIO结构体的首地址

例子:将20写入GPIOB       MODER寄存器中  (4字节)
GPIOB ->MODER = 20;

2.1.7 如何操作GPIO口

        操作IO分为以下三个步骤

1.需要打开GPIO端口所对应的控制总线的时钟

找到GPIOA挂靠的总线

步骤:数据手册  第二大点

GPIO口都挂靠在AHB1总线上,AHB1总线频率168Mhz

2.寻找预留接口

其实STM32给工程师预留了接口   接口:寄存器

通过操作寄存器来实现IO输出高低电平或接收外界的高低电平

3.决定IO功能

LED : IO口需要输出高电平点亮

寄存器如何设置  -- 也需要参考手册

2.2 STM32的GPIO口相关寄存器

中文参考手册里面有相关寄存器的配置

第七章        7.4 GPIO寄存器

配置寄存器步骤:

①先看寄存器大标题

        GPIO 端口模式寄存器 (GPIOx_MODER) (x = A..I)

②复位值,查看复位值是否为0,如不为零配置时需要清零

③看对应寄存器位的功能

例子:如需要将PB5配置为输入模式,如何操作?

管脚号:5

GPIOB->MODER  &=~ (3 << 10);

如需要将PE10配置为输出模式,如何操作?

GPIOE->MODER |= 1 << 20;

GPIO寄存器分析:

GPIO 端口模式寄存器 (GPIOx_MODER)

作用:配置模式

注意:如遇到复位值不为零的寄存器,为了保证配置正确,最好在配置前先清零

一个管脚需要配置2

MODERy[1:0]: 端口 x 配置位 (Port x configuration bits) (y = 0..15)这些位通过软件写入,用于配置 I/O 方向模式。

00:输入(复位状态)

01:通用输出模式

10:复用功能模式

11:模拟模式

GPIO 端口输出类型寄存器 (GPIOx_OTYPER)     GPIOC->OTYPER &=~ (1 << 15)

作用:配置输出模式的类型

注意:配置输出类型只针对输出模式,如配置为输入模式后,配置此寄存器无效

OT0 - OT15代表管脚号,一个管脚对应1bit

15:0 OTy[1:0]: 端口 x 配置位 (Port x configuration bits) (y = 0..15)这些位通过软件写入,用于配置 I/O 端口的输出类型。

0:输出推挽(复位状态)

1:输出开漏

GPIO 端口输出速度寄存器 (GPIOx_OSPEEDR)

注意:对于普通器件开关来说速度没任何的作用,但是对有一定的影响通信协议

SPI通信  25Mhz 需要利用IO口模拟SPI通信,如果想让SPI通信速率跑满,那么IO输出速度需要设置为多少?

至少IO设置为25Mhz

一个管脚对应两位进行控制

2y:2y+1 OSPEEDRy[1:0]: 端口 x 配置位 (Port x configuration bits) (y = 0..15)这些位通过软件写入,用于配置 I/O 输出速度。

002 MHz(低速)

0125 MHz(中速)

1050 MHz(快速)

1130 pF 时为 100 MHz(高速)( 15 pF 时为 80 MHz 输出(最大速度))

GPIO 端口上拉/下拉寄存器 (GPIOx_PUPDR)

一个管脚对应2bit

2y:2y+1 PUPDRy[1:0]: 端口 x 配置位 (Port x configuration bits) (y = 0..15)这些位通过软件写入,用于配置 I/O 上拉或下拉。

00:无上拉或下拉

01:上拉

10:下拉

11:保留

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

15:0 IDRy[15:0]: 端口输入数据 (Port input data) (y = 0..15)

这些位为只读形式,只能在字模式下访问。它们包含相应 I/O 端口的输入值。

CPU读取外界过来的数字量数据

例子:如需判断按键有没有按下,条件:按键按下时为高电平        PA0

 &           |

if(GPIOA->IDR  &  (1 << 0))

{

//按键按下

}

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

作用:决定IO口输出的数据是1 / 0

一个管脚对应1bit

例子:如需PB3输出一个高电平,如何用代码表示

GPIOB->ODR |= 1  << 3;

 2.2.1程序设计

控制板子的四个LED灯亮灭

LED1   ----   PC4   ----  通用推挽输出

LED2   ----   PC5   ----  通用推挽输出

LED3   ----   PC6   ----  通用推挽输出

LED4   ----   PC7   ----  通用推挽输出

代码实现:led.c

#include "led.h"

/*
函数功能:LED灯IO初始化
返回值:void
形参:void
函数说明:
LED1   ----   PC4   ----  通用推挽输出
LED2   ----   PC5   ----  通用推挽输出
LED3   ----   PC6   ----  通用推挽输出
LED4   ----   PC7   ----  通用推挽输出
*/

void Led_Init(void)
{
	
	//1、打开GPIOC的时钟 -- AHB1
	RCC->AHB1ENR |= 1 << 2;
	
	//2、配置模式
	GPIOC->MODER &=~ (0xff << 8);
	GPIOC->MODER |= 0x55 << 8;
	
	//3、输出类型
	GPIOC->OTYPER &=~ (0xf << 4);
	
	//4、配置IO输出速度
	GPIOC->OSPEEDR |= (0xaa << 8);
	
	//5、配置IO口上下拉
	GPIOC->PUPDR &=~ (0xff << 8);
	
	//6、配置LED默认电平为熄灭   --  IO拉高   ODR
	GPIOC->ODR |= 0xf << 4;
	
	
	

	
}

 led.h

#ifndef _LED_H
#define _LED_H

#include "stm32f4xx.h"

//注意:宏定义后不能加分号
#define LED1_ON  (GPIOC->ODR &=~ (1 << 4))
#define LED1_OFF (GPIOC->ODR |= (1 << 4))

#define LED2_ON  (GPIOC->ODR &=~ (1 << 5))
#define LED2_OFF (GPIOC->ODR |= (1 << 5))

#define LED3_ON  (GPIOC->ODR &=~ (1 << 6))
#define LED3_OFF (GPIOC->ODR |= (1 << 6))

#define LED4_ON  (GPIOC->ODR &=~ (1 << 7))
#define LED4_OFF (GPIOC->ODR |= (1 << 7))


void Led_Init(void);


#endif

 main.c

#include "main.h"



int main(void)
{
	/***************只会执行一次*****************/
	Led_Init();//LED管脚初始化
	
	LED1_ON;//点亮LED1
	LED2_ON;//点亮LED2
	LED3_ON;//点亮LED3
	LED4_ON;//点亮LED4
	
	while(1)//防止单片机跑飞
	{
		/***************循环运行的代码*****************/
		
		
		
	}
	
}







以上就是我对GPIO的一点拙见,由于我现在用的板子是STM32F407VET6,所以后面的代码和图片都是基于这块板子的。后面会继续更新相关我的STM32的学习之路。

  • 14
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值