STM32 GPIO

STM32 的 IO 口相比 51 而言要复杂得多,所以使用起来也困难很多。首先 STM32 的 IO 口可以由软件配置成如下 8 种模式:
1、输入浮空
2、输入上拉
3、输入下拉
4、模拟输入
5、开漏输出
6、推挽输出
7、推挽式复用功能
8、开漏复用功能
每个 IO 口可以自由编程,但 IO 口寄存器必须要按 32 位字被访问。STM32 的很多 IO 口都是 5V 兼容的,这些 IO 口在与 5V 电平的外设连接的时候很有优势,具体哪些 IO 口是 5V 兼容的,可以从该芯片的数据手册管脚描述章节查到(I/O Level 标 FT 的就是 5V 电平兼容的)。

STM32 的每个 IO 端口都有 7 个寄存器来控制他们分别是:
配置模式的 2 个 32 位的端口
配置寄存器 CRL 和 CRH;
2 个 32 位的数据寄存器 IDR 和 ODR;
1 个 32 位的置位/复位寄存器BSRR;
一个 16 位的复位寄存器 BRR;
1 个 32 位的锁存寄存器 LCKR。
大家如果想要了解每个寄存器的详细使用方法,可以参考《STM32 中文参考手册 V10》P105~P129。
注:CRL 和 CRH 控制着每个 IO 口的模式及输出速率。

I/O端口位的基本结构:
I/O端口位的基本结构
5伏兼容I/O端口位的基本结构:
在这里插入图片描述

一、输入模式

4种输入模式:输入浮空、输入上拉、输入下拉、模拟输入
(1) GPIO_Mode_AIN 模拟输入
(2) GPIO_Mode_IN_FLOATING 浮空输入
(3) GPIO_Mode_IPD 下拉输入
(4) GPIO_Mode_IPU 上拉输入

在输入模式时,施密特触发器打开,输出被禁止。可通过输入数据寄存器GPIOx_IDR 读取I/O 状态。输入模式可以配置为模拟、上拉、下拉以及浮空模式。上拉和下拉输入很好理解,默认的电平由上拉或者下拉决定。浮空输入的电平是不确定的,完全由外部的输入决定,一般接按键的时候可以使用这个模式。模拟输入则用于ADC 采集。数据寄存器每隔1个AHB1时钟周期更新一次,可通过数据寄存器GPIOx_IDR读取I/O状态。其中AHB1的时钟如按默认配置一般为180MHz。

1.GPIO_MODE_AIN 模拟输入 大多情况下,应用于ADC模拟输入或低功耗省电,模拟输入模式可以读取到很细微变化的值。

2.GPIO_MODE_IN_FLOATING 浮空输入 是指IO的点评状态是不确定的,完全是由外部输入决定,如果在该引脚悬空的情况下,读取到的该端口电平是不确定的

3.GPIO_MODE_IPD 下拉输入 IO内部下拉电阻输入 如果IO口外部没有信号输入或者引脚悬空,IO口默认为低电平 如果I/O口输入高电平,那么引脚就为高电平,MCU读取到的就是高电平

4.GPIO_MODE_IPU 上拉输入 IO内部上拉电阻输入 如果IO口外部没有信号输入或者引脚悬空,IO口默认为高电平 如果I/O口输入低电平,那么引脚就为低电平,MCU读取到的就是低电平

二、输出模式

4种输出模式:开漏输出、开漏复用功能、推挽式输出、推挽式复用功能
(1) GPIO_Mode_Out_OD 开漏输出
(2) GPIO_Mode_Out_PP 推挽输出
(3) GPIO_Mode_AF_OD 复用开漏输出
(4) GPIO_Mode_AF_PP 复用推挽输出
在输出模式中,输出使能,推完模式时以双MOS管的方式工作,输出数据寄存器GPIOx_ODR可控制I/O输出高低点评。开漏模式时,只有N-MOS工作,输出数据寄存器可控制I/O输出高阻态或低电平。输出速度可配置,有2MHz\25MHz\50MHz\100MHz的选项。此处的输出速度即I/O支持的高低电平状态最高切换频率,支持的频率越高,功耗越大,如果功耗要求不严格,把速度设置成最大即可。

 此时施密特触发器时打开的,即输入可用,通过输入数据寄存器GPIOx_IDR可读取I/O的实际状态。

 用于输出模式时,可使用上拉、下拉或悬空模式。但此时由于输出模式时引脚电平会收到ODR寄存器的影响,而ODR寄存器对应引脚的位为0,即引脚初始化后默认输出低电平,所以在这种情况下,上拉只能起到小幅提高输出电流能力,但不会影响引脚的默认状态。

1.推挽输出
可以输出高,低电平,连接数字器件; 推挽结构一般是指两个三极管分别受两互补信号的控制,总是在一个三极管导通的时候另一个截止。高低电平由 IC 的电源低定。
推挽电路是两个参数相同的三极管或 MOSFET,以推挽方式存在于电路中,各负责正负半周的波形放大任
务,电路工作时,两只对称的功率开关管每次只有一个导通,所以导通损耗小、效率高。输出既可以向负载
灌电流,也可以从负载抽取电流。推拉式输出级既提高电路的负载能力,又提高开关速度。
在这里插入图片描述
推挽输出模式的等效电路
在这里插入图片描述
2.开漏输出
在开漏输出模式时,不论输入是高电平还是低电平,P-MOS 管总处于关闭状态。当给这个单元电路输入低电平时,N-MOS 管导通,输出即为低电平。当输入高电平时,N-MOS 管截止,这个时候引脚状态既不是高电平,又不是低电平,我们称之为高阻态。如果想让引脚输出高电平,那么引脚必须外接一个上拉电阻,由上拉电阻提供高电平。开漏输出模式等效电路图如图所示。
在这里插入图片描述
在开漏输出模式中还有一个特点,引脚具有**“线与”**关系。就是说如果有很多个开漏输出模式的引脚接在一起,只要有一个引脚为低电平,其他所有管脚都为低,即把所有引脚连接在一起的这条总线拉低了。只有当所有引脚输出高阻态时这条总线的电平才由上拉电阻的VDD 决定。如果VDD 连接的是3.3V,那么引脚输出的就是3.3V,如果VDD 连接的是5V,那么引脚输出的就是5V。因此如果想要让STM32 管脚输出5V,可以选择开漏输出模式,然后在外接上拉电阻的电源VDD 选择5V 即可,前提是这个STM32 引脚是容忍5V 的。开漏输出模式一般应用在I2C、SMBUS 通讯等需要“线与”功能的总线电路中。还可以用在电平不匹配的场合中,就如上面说的输出5V 一样。推挽输出模式一般应用在输出电平为0-3.3V 而且需要高速切换开关状态的场合。除了必须要用开漏输出模式的场合,我们一般选择推挽输出模式。要配置引脚是开漏输出还是推挽输出模式可以使用GPIOx_CRL 和GPIOx_CRH 寄存器。

3.复用功能输出
由于STM32 的GPIO 引脚具有第二功能,因此当使用复用功能的时候,也就是通过其他外设复用功能输出信号与GPIO 数据寄存器一起连接到双MOS 管电路的输入,其中梯形结构是用来选择使用复用功能还是普通IO 口功能。
例如我们使用USART 串口通讯时,需要用到某个GPIO 引脚作为通讯发送引脚,这个时候就可以把该GPIO 引脚配置成USART 串口复用功能,由串口外设控制该引脚,发送数据。
复用功能模式中,输出使能,输出速度可配置,可工作在开漏及推挽模式,但是输出信号源于其它外设,输出数据寄存器GPIOx_ODR 无效;输入可用,通过输入数据寄存器可获取I/O 实际状态,但一般直接用外设的寄存器来获取该数据信号。

在 STM32 中选用 IO 模式使用总结
(1) 浮空输入_IN_FLOATING ——浮空输入,可以做 KEY 识别, RX1
(2)带上拉输入_IPU——IO 内部上拉电阻输入
(3)带下拉输入_IPD—— IO 内部下拉电阻输入
(4) 模拟输入_AIN ——应用 ADC 模拟输入,或者低功耗下省电
(5)开漏输出_OUT_OD ——IO 输出 0 接 GND, IO 输出 1,悬空,需要外接上拉电阻,才能实现输出
高电平。当输出为 1 时, IO 口的状态由上拉电阻拉高电平,但由于是开漏输出模式,这样 IO 口也就可以
由外部电路改变为低电平或不变。可以读 IO 输入电平变化,实现 C51 的 IO 双向功能
(6)推挽输出_OUT_PP ——IO 输出 0-接 GND, IO 输出 1 -接 VCC,读输入值是未知的
(7)复用功能的推挽输出_AF_PP ——片内外设功能(I2C 的 SCL,SDA)
(8)复用功能的开漏输出_AF_OD——片内外设功能(TX1,MOSI,MISO.SCK.SS)

三、GPIO的配置

端口位配置
在这里插入图片描述
输出模式位
在这里插入图片描述
1.输入配置
当I/O端口配置为输入时:
● 输出缓冲器被禁止
● 施密特触发输入被激活
● 根据输入配置(上拉,下拉或浮动)的不同,弱上拉和下拉电阻被连接
● 出现在I/O脚上的数据在每个APB2时钟被采样到输入数据寄存器
● 对输入数据寄存器的读访问可得到I/O状态
下图给出了I/O端口位的输入配置
在这里插入图片描述
2.输出配置
当I/O端口被配置为输出时:
● 输出缓冲器被激活
─ 开漏模式:输出寄存器上的’0’激活N-MOS,而输出寄存器上的’1’将端口置于高阻状态(PMOS从不被激活)。 ─ 推挽模式:输出寄存器上的’0’激活N-MOS,而输出寄存器上的’1’将激活P-MOS。
● 施密特触发输入被激活
● 弱上拉和下拉电阻被禁止
● 出现在I/O脚上的数据在每个APB2时钟被采样到输入数据寄存器
● 在开漏模式时,对输入数据寄存器的读访问可得到I/O状态
● 在推挽式模式时,对输出数据寄存器的读访问得到最后一次写的值。
下图给出了I/O端口位的输出配置
在这里插入图片描述
3.复用功能配置
当I/O端口被配置为复用功能时:
● 在开漏或推挽式配置中,输出缓冲器被打开
● 内置外设的信号驱动输出缓冲器(复用功能输出)
● 施密特触发输入被激活
● 弱上拉和下拉电阻被禁止
● 在每个APB2时钟周期,出现在I/O脚上的数据被采样到输入数据寄存器
● 开漏模式时,读输入数据寄存器时可得到I/O口状态
● 在推挽模式时,读输出数据寄存器时可得到最后一次写的值
下图示出了I/O端口位的复用功能配置。一组复用功能I/O寄存器允许用户把一些复用功能重新映象到不同的引脚。
在这里插入图片描述
4.模拟输入配置
当I/O端口被配置为模拟输入配置时:
● 输出缓冲器被禁止;
● 禁止施密特触发输入,实现了每个模拟I/O引脚上的零消耗。施密特触发输出值被强置
为’0’;
● 弱上拉和下拉电阻被禁止;
● 读取输入数据寄存器时数值为’0’。
下图示出了I/O端口位的高阻抗模拟输入配置:
在这里插入图片描述
GPIO相关配置寄存器
每组GPIO端口的寄存器包括:

两个32位配置寄存器(GPIOx_CRL ,GPIOx_CRH) ,

两个32位数据寄存器 (GPIOx_IDR和GPIOx_ODR),

一个32位置位/ 复位寄存器(GPIOx_BSRR),

一个16位复位寄存器(GPIOx_BRR),

一个32位锁定寄存器(GPIOx_LCKR)。

每个I/O端口位可以自由编程,然而I/O端口寄存器必须按32位字被访问(不允许半字或字节访问) 。

是每组IO口含下面7个寄存器。也就是7个寄存器,

一共可以控制一组GPIO的16个IO口。

   -  GPIOx_CRL :端口配置低寄存器

    - GPIOx_CRH:端口配置高寄存器

    - GPIOx_IDR:端口输入寄存器

    - GPIOx_ODR:端口输出寄存器

    - GPIOx_BSRR:端口位设置/清除寄存器

    - GPIOx_BRR :端口位清除寄存器

    - GPIOx_LCKR:端口配置锁存寄存器

(1)端口配置低寄存器(GPIOx_CRL)
在这里插入图片描述
该寄存器的复位值为 0X4444 4444,从图 6.1.4 可以看到,复位值其实就是配置端口为浮空输入模式。从上图还可以得出: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位输出口。这里我们对 CRH 就不做详细介绍了。

下面我们讲解一下怎样通过固件库设置 GPIO的相关参数和输出
GPIO 相关的函数和定义分布在固件库文件 stm32f10x_gpio.c 和头文件 stm32f10x_gpio.h 文件中。

在固件库开发中,操作寄存器 CRH 和 CRL 来配置 IO 口的模式和速度是通过 GPIO 初始化函数完成:

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)

这个函数有两个参数,第一个参数是用来指定 GPIO,取值范围为GPIOA~GPIOG。
第二个参数为初始化参数结构体指针,结构体类型为 GPIO_InitTypeDef。
下面我们看看这个结构体的定义:

typedef struct
{ uint16_t GPIO_Pin; 
 GPIOSpeed_TypeDef GPIO_Speed; 
 GPIOMode_TypeDef GPIO_Mode; 
}GPIO_InitTypeDef;

下面我们通过一个 GPIO 初始化实例来讲解这个结构体的成员变量的含义。
通过初始化结构体初始化 GPIO 的常用格式是:

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度 50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);//根据设定参数配置 GPIO

上面代码的意思是设置 GPIOB 的第 5 个端口为推挽输出模式,同时速度为 50M。从上面初始化代码可以看出,结构体 GPIO_InitStructure 的第一个成员变量 GPIO_Pin 用来设置是要初始化哪个或者哪些 IO 口;第二个成员变量 GPIO_Mode 是用来设置对应 IO 端口的输出输入模式,这些模式是上面我们讲解的 8 个模式,在 MDK 中是通过一个枚举类型定义的:

typedef enum
{ 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 //复用推挽
}GPIOMode_TypeDef;

第三个参数是 IO 口速度设置,有三个可选值,在 MDK 中同样是通过枚举类型定义:

typedef enum
{ 
 GPIO_Speed_10MHz = 1,
 GPIO_Speed_2MHz, 
 GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;

(2)端口输入数据寄存器(GPIOx_IDR)
IDR 是一个端口输入数据寄存器,只用了低 16 位。该寄存器为只读寄存器,并且只能以16 位的形式读出。该寄存器各位的描述如图 6.1.7 所示:
在这里插入图片描述
要想知道某个 IO 口的电平状态,你只要读这个寄存器,再看某个位的状态就可以了。使用起来是比较简单的。
在固件库中操作 IDR 寄存器读取 IO 端口数据是通GPIO_ReadInputDataBit 函数实现的:

uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

比如我要读 GPIOA.5 的电平状态,那么方法是:

GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5);

返回值是 1(Bit_SET)或者 0(Bit_RESET);

(3)端口输出数据寄存器(GPIOx_ODR)
ODR 是一个端口输出数据寄存器,也只用了低 16 位。该寄存器为可读写,从该寄存器读出来的数据可以用于判断当前 IO 口的输出状态。而向该寄存器写数据,则可以控制某个 IO 口的输出电平。该寄存器的各位描述如图 6.1.8 所示:
在这里插入图片描述
在固件库中设置 ODR 寄存器的值来控制 IO 口的输出状态是通过函数 GPIO_Write 来实现的:

void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

该函数一般用来往一次性一个 GPIO 的多个端口设值。

(4)端口位设置/清除寄存器(GPIOx_BSRR)
BSRR 寄存器是端口位设置/清除寄存器。该寄存器和 ODR 寄存器具有类似的作用,都可以用来设置 GPIO 端口的输出位是 1 还是 0。下面我们看看该寄存器的描述如下图:
在这里插入图片描述
该寄存器通过举例子可以很清楚了解它的使用方法。例如你要设置 GPIOA 的第 1 个端口值为 1,那么你只需要往寄存器 BSRR 的低 16 位对应位写 1 即可:

GPIOA->BSRR=1<<1;

如果你要设置 GPIOA 的第 1 个端口值为 0,你只需要往寄存器高 16 位对应为写 1 即可:

GPIOA->BSRR=1<<(16+1)

该寄存器往相应位写 0 是无影响的,所以我们要设置某些位,我们不用管其他位的值。

(5)端口位清除寄存器(GPIOx_BRR)
BRR 寄存器是端口位清除寄存器。该寄存器的作用跟 BSRR 的高 16 位雷同,这里就不做详细讲解。在 STM32 固件库中,通过 BSRR 和 BRR 寄存器设置 GPIO 端口输出是通过函数GPIO_SetBits()和函数 GPIO_ResetBits()来完成的。

void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

在多数情况下,我们都是采用这两个函数来设置 GPIO 端口的输入和输出状态。比如我们要设置 GPIOB.5 输出 1,那么方法为:

GPIO_SetBits(GPIOB, GPIO_Pin_5);

反之如果要设置 GPIOB.5 输出位 0,方法为:

GPIO_ResetBits (GPIOB, GPIO_Pin_5);

虽然 IO 操作步骤很简单,这里我们还是做个概括性的总结,操作步骤为:
1) 使能 IO 口时钟。调用函数为 RCC_APB2PeriphClockCmd()。
2) 初始化 IO 参数。调用函数 GPIO_Init();
3) 操作 IO。操作 IO 的方法就是上面我们讲解的方法。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值