STM32学习笔记一一GPIO

前言:

为了方便查看博客,特意申请了一个公众号,附上二维码,有兴趣的朋友可以关注,和我一起讨论学习,一起享受技术,一起成长。

在这里插入图片描述


1. GPIO工作方式

STM32 每个 IO 口可以自由编程,但 IO 口寄存器必须要按 32 位字被访问。 本文主要是库函数实现的笔记。相关图片来自正点原子教程。

1.1 4种输入模式

输入浮空 输入上拉 输入下拉 模拟输入

a.输入浮空

这里写图片描述

CPU可以通过输入数据寄存器读出I/O口的高低电平,工作电路如图。


b.上拉下拉输入:添加了上拉、下拉电阻后,CPU再读电平

这里写图片描述


c.模拟输入

这里写图片描述

输入量为模拟量,不再是电平,输入的电压范围:0—3.3V


1.2 4种输出模式

开漏输出 开漏复用功能 推挽式输出 推挽式复用功能


a. 开漏输出

这里写图片描述

开漏输出:输出端相当于三极管的集电极. 要得到高电平状态需要上拉电阻才行。适合于做电流型的驱动,其吸收电流的能力相对强(一般 20ma 以内)。

开漏是用来连接不同电平的器件,匹配电平用的,因为开漏引脚不连接外部的上拉电阻时,只能输出低电平,如果需要同时具备输出高电平的功能,则需要接上拉电阻,很好的一个优点是通过改变上拉电源的电压,便可以改变传输电平。

b. 推挽输出

这里写图片描述

推挽输出:可以输出高,低电平,连接数字器件; 推挽结构一般是指两个三极管分别受两互补信号的控制,总是在一个三极管导通的时候另一个截止。高低电平由 IC 的电源决定。

推挽电路是两个参数相同的三极管或MOSFET,以推挽方式存在于电路中,各负责正负半周的波形放大任务,电路工作时,两只对称的功率开关管每次只有一个导通,所以导通损耗小、效率高。输出既可以向负载灌电流,也可以从负载抽取电流。推拉式输出级既提高电路的负载能力,又提高开关速度。

(2) 8 个模式定义

GPIO_Mode_AIN = 0x0, //模拟输入
GPIO_Mode_IN_FLOATING = 0x04, //浮空输入
GPIO_Mode_IPD = 0x28, //下拉输入
GPIO_Mode_IPU = 0x48, //上拉输入
GPIO_Mode_Out_OD = 0x14, //开漏输出
GPIO_Mode_Out_PP = 0x10, //通用推挽输出
GPIO_Mode_AF_OD = 0x1C, //复用开漏输出
GPIO_Mode_AF_PP = 0x18 //复用推挽

STM32 的 IO 口位配置表如下

这里写图片描述

(3)IO口速度定义

GPIO_Speed_10MHz = 1,
GPIO_Speed_2MHz,
GPIO_Speed_50MHz

STM32 输出模式配置:

这里写图片描述

I/O口输出速度是指I/O口驱动电路的响应速度而不是输出信号的速度,输出信号的速度与程序有关(芯片内部在I/O口的输出部分安排了多个响应速度不同的输出驱动电路,用户可以根据自己的需要选择合适的驱动电路)。通过选择速度来选择不同的输出驱动模块,达到最佳的噪声控制和降低功耗的目的。高频的驱动电路,噪声也高,当不需要高的输出频率时,请选用低频驱动电路,这样非常有利于提高系统的EMI性能。当然如果要输出较高频率的信号,但却选用了较低频率的驱动模块,很可能会得到失真的输出信号。关键是GPIO的引脚速度跟应用匹配。

(4)IO配置

① 作为普通GPIO输入:
根据需要配置该引脚为浮空输入、带弱上拉输入或带弱下拉输入,同时不要使能该引脚对应的所有复用功能模块。
② 作为普通GPIO输出:
根据需要配置该引脚为推挽输出或开漏输出,同时不要使能该引脚对应的所有复用功能模块。
③ 作为普通模拟输入:
配置该引脚为模拟输入模式,同时不要使能该引脚对应的所有复用功能模块。
④ 作为内置外设的输入:
根据需要配置该引脚为浮空输入、带弱上拉输入或带弱下拉输入,同时使能该引脚对应的某个复用功能模块。
⑤ 作为内置外设的输出:
根据需要配置该引脚为复用推挽输出或复用开漏输出,同时使能该引脚对应的所有复用功能模块。

(5)GPIO口初始化

①使能GPIO口的时钟
②配置模式设置(8种模式)
注:STM32的GPIO的时钟统一挂接在APB2上,具体的使能寄存器为RCC_APB2ENR。该寄存器的第2位到第8位分别控制GPIOx(x=A,B,C,D,E,F,G)端口的时钟使能。

Eg:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE); //使能PA,PD端口时钟

注:STM32 的很多 IO 口都是 5V 兼容的,可以从该芯片的数据手册管脚描述章节查到( I/O Level 标 FT 的就是 5V 电平兼容的)。

(6)GPIO配置寄存器

a.STM32 的 CRL 控制着每组 IO 端口( A~G)的低 8 位的模式。每个 IO 端口的位占用 CRL 的 4 个位,高两位为 CNF,低两位为 MODE。GPIO口配置是通过配置寄存器来进行的,每个GPIO 端口有:

两个32位配置寄存器(GPIOx_CRL,GPIOx_CRH)分别控制每个端口的高八位和低八位。如果IO口是0-7号的话,则写CRL寄存器;如果IO口是8-15号的话,则写CRH寄存器。CRL 和 CRH 控制着每个 IO 口的模式及输出速率。

配置表如下:

这里写图片描述

输出模式配置:

这里写图片描述

端口低配置寄存器 CRL 的描述:

这里写图片描述

这里写图片描述

该寄存器的复位值为 0X4444 4444,复位值其实就是配置端口为浮空
输入模式。从上图还可以得出: STM32 的 CRL 控制着每组 IO 端口( A~G)的低 8 位的模式。每个 IO 端口的位占用 CRL 的 4 个位,高两位为 CNF,低两位为 MODE。

几个常用的配置,比如 0X0 表示模拟输入模式( ADC 用)、 0X3 表示推挽输出模式(做输出口用,50M 速率)、 0X8 表示上/下拉输入模式(做输入口用)、 0XB 表示复用输出(使用 IO 口的第二功能, 50M 速率)。

CRH 的作用和 CRL 完全一样,只是 CRL 控制的是低 8 位输出口,而 CRH 控制的是高 8位输出口。

b.两个32位数据寄存器(GPIOx_IDR,GPIOx_ODR)一个是只读作输入数据寄存器,一个是只写作输出寄存器。

端口输入数据寄存器 IDR 各位描述:

这里写图片描述

要想知道某个 IO 口的状态, 你只要读这个寄存器,再看某个位的状态就可以了。

ODR 是一个端口输出数据寄存器,也只用了低 16 位。该寄存器为可读写,从该寄存器读出来的数据可以用于判断当前 IO 口的输出状态。而向该寄存器写数据,则可以控制某个 IO 口的输出电平。

这里写图片描述

一个32位置位/复位寄存器(GPIOx_BSRR)。
一个16位复位寄存器(GPIOx_BRR)。
一个32位锁定寄存器(GPIOx_LCKR)。
常用的IO端口寄存器只有四个:CRH,CRL,IDR,ODR。

数据手册中列出的每个I/O端口的特定硬件特征。 GPIO端口的每个位可以由软件分别配置成多种模式。每个I/O端口位可以自由编程,然而I/O端口寄存器必须按32位字被访问(不允许半字或字节访问)。 另外,STM32的每个端口使用前都要将其时钟使能,STM32的GPIO的时钟统一挂接在APB2上,具体的使能寄存器为RCC_APB2ENR,该寄存器的第2位到第8位分别控制GPIOx(x=A,B,C,D,E,F,G)端口的时钟使能,当外设时钟没有启用时,程序不能读出外设寄存器的数值。

(7)GPIO库函数简要解释:

函数名具体功能
GPIO_DeInit重新初始化外围设备GPIOx相关寄存器到它的默认复位值
GPIO_AFIODeInit初始化交错功能(remap, event control和 EXTI 配置) 寄存器
GPIO_Init根据GPIO_初始化结构指定的元素初始化外围设备GPIOx
GPIO_StructInit填充GPIO_初始化结构(GPIO_InitStruct)内的元素为复位值
GPIO_ReadInputDataBit读指定端口引脚输入数据
GPIO_ReadInputData读指定端口输入数据
GPIO_ReadOtputDataBit 读指定端口引脚输出数据
GPIO_ReadOtputData读指定端口输出数据
GPIO_SetBits置1指定的端口引脚
GPIO_ResetBits清0指定的端口引脚
GPIO_WriteBit设置或清除选择的数据端口引脚
GPIO_Write写指定数据到GPIOx端口寄存器
GPIO_ANAPinConfig允许或禁止 GPIO 4 模拟输入模式
GPIO_PinLockConfig锁定GPIO引脚寄存器
GPIO_EventOutputConfig选择GPIO引脚作为事件输出
GPIO_EventOutputCmd允许或禁止事件输出
GPIO_PinRemapConfig改变指定引脚的映射
GPIO_EXTILineConfig设置外部中断
GPIO_ETH_MediaInterfaceConfig配置以太网接口

(8)实例学习

①GPIO输出——LED实现:关键部分是实现GPIO的初始化工作,具体实现如下:

#define LED PAout(12) //输出,使用的是位带操作来实现操作某个 IO 口的 1 个位

void led_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能PA端口
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//PA.8端口设置
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//IO口的速度为50MHZ
	
	GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化PA
	GPIO_SetBits(GPIOA,GPIO_Pin_12);//PA.8输出高
}

在使用PA15引脚的时候,按照正常的 IO 初始化,并且停止使用JTAG,依然不能点亮LED,因为PA15默认JTAG的一个脚,现在要变成普通IO就要使能复用时钟。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);//使能PA端口
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //关闭JTAG口,使PB3,PB4,PA15这几个IO作为普通IO使用

注:操作 IO 口输出高低电平的三种方法

位操作就是可以单独的对一个比特位读和写,这个在51单片机中非常常见。51单片机中通过关键字sbit来实现位定义,STM32F103中没有这样的关键字,而是通过访问位带别名区来实现。

	a.通过位带操作 PA12 输出高低电平从而控制 LED 的方法如下:
	#define LED PAout(15) //输出
	LED=1; //通过位带操作控制 LED 的引脚 PA12 输出高电平
	LED=0; //通过位带操作控制 LED 的引脚 PA12 输出低电平
	
	b.使用固件库操作和寄存器操作:
	来实现 IO 口操作。 库函数操作方法如下:
	GPIO_SetBits(GPIOA, GPIO_Pin_12); //设置 GPIOA12 输出 1,等同 LED=1;
	GPIO_ResetBits (GPIOA, GPIO_Pin_12); //设置 GPIOA12 输出 0,等同 LED=0;
	库函数操作就直接调用两个函数即可控制 IO 输出高低电平。
	
	c.通过直接操作寄存器:
	BRR 和 BSRR 的方式来操作 IO 口输出高低电平,方法如下:
	GPIOA->BRR=GPIO_Pin_12; //设置 GPIOA.12 输出 1,等同 LED=1;
	GPIOA->BSRR=GPIO_Pin_12; //设置 GPIOA.12 输出 0,等同 LED=0;

② 仿真测试

IO 口复用的,信号在逻辑分析窗口是不能显示出来的(看不到波形),比如串口的输出, SPI, USB, CAN 等。

相关设置如下:
Use Simulator,即使用软件仿真。选择: Run to main(),即跳过汇
编代码,直接跳转到 main 函数开始仿真。
设置下方的: Dialog DLL 分别为: DARMSTM.DLL
和 TARMSTM.DLL,
Parameter 均为: -pSTM32F103RC,用于设置支持 STM32F103RC 的软硬件仿真。如下图:

这里写图片描述

仿真结果如下:

这里写图片描述

下载到开发板上,运行结果与仿真的一致。

③ GPIO输入——按键输入
STM32 的 IO 口做输入使用的时候,是通过调用函数
GPIO_ReadInputDataBit() 来读取 IO 口的状态的。

主要实现部分:

void Key_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能 PORTA 时钟
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//PA12
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉
	GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化PA12
	
}

void Key_Scan(void)
{
	if(KEY == 0)
	{
		delay_ms(10);
		if(KEY == 0)
			LED = !LED;
	}
}

逻辑分析仪仿真如下:

这里写图片描述

效果:按下按键实现 LED 亮灭。

参考:
1.STM32使用之GPIO
2.STM32学习笔记之GPIO口的使用
3.STM32的GPIO输入输出模式配置
4.原子STM32开发手册—库函数版

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值