stm32中的GPIO

stm32中的八种输入、输出模式总结

GPIO的电气特性

不同的芯片的GPIO电气特性不同,需要去数据手册中查找。

各GPIO输入输入模式

对于 F1 系列芯片来说,其 IO 端口的内部上拉电阻的里面;而对于 F4 等以上的芯片来说其是在外面的:

F1 系列:

F4 系列:

一般的上下拉电阻的阻值是:30Ω-50Ω

  1. 模拟输入:GPIO_Mode_AIN,专用于 ADC和 DAC 这两个数字、模拟转换器
  2. 浮空输入:GPIO_Mode_IN_FLOATING,空闲时电平未知,由外部环境决定
  3. 上拉输入:GPIO_Mode_IPU,空闲时呈现出高电平
  4. 下拉输入:GPIO_Mode_IPD,空闲时呈现出低电平
  5. 推挽输出:GPIO_Mode_Out_PP,既可以输出高电平,也可以输出低电平
  6. 开漏输出:GPIO_Mode_Out_OD,只可以输出低电平,如果有内部或外部上拉电阻则可以输出高电平
  7. 复用推挽输出:GPIO_Mode_AF_OD
  8. 复用开漏输出:GPIO_Mode_AF_OD

各个模式适用的情况:

模拟输入:关闭施密特触发器,将电压信号传送到片上外设模块(不接上下拉电阻)。应用ADC模拟输入,或者低功耗下省电。

浮空输入:浮空输入状态下,IO的电平状态是不确定的,完全由外部输入决定,如果在该引脚悬空的情况下,读取该端口的电平是不确定的。可以做KEY识别,RX1。

上拉输入、下拉输入:当GPIO引脚无输入时,上拉输入在默认状态下为高电平,下拉输入在默认状态下为低电平。电阻的作用:防止输入端悬空,减少外部电流对芯片的干扰,限流,增加高电平输出时的驱动能力。IO内部上拉电阻输入。 IO内部下拉电阻输入。 当接在这个引脚的外部模块的默认输出高电平的话就是选择上拉输出,否则选择下拉输入。如果不确定外部模块默认是高电平还是低电平则选择浮空输入。一般选择上拉电平

推挽输出:想要输出高电平就输出高电平,想要输出低电平就输出低电平。
一般都是使用这个

开漏输出:输出端相当于三极管的集电极。要得到高电平状态需要上拉电阻才行。适合于做电流型的驱动,其吸收电流的能力相对较强,一般20mA以内。开漏输出是没有能力输出高电平驱动负载的。一般情况下开漏输出只可以输出低电平,要输出高电平则需要接上拉电阻。

复用开漏输出推挽输出模式:可以理解为GPIO口被用作第二功能时的配置情况,即并非作为通用IO口使用。片内外设功能,复用推挽输出:I2C的SCL、SDA。复用开漏输出:片内外设功能,TX1,MOSI,MISO.SCK.SS。
给片上外设使用的,其他情况下如GPIO则不需要使用这种复用模式。

寄存器相关

在使用各种函数库的时候,它们的底层其实都是对于寄存器的配置。所以我们需要了解一些寄存器的相关知识。

对于 Stm 不同系列的芯片来说,拥有的寄存器种类、个数等等都不同,我们需要根据具体的芯片来进行寄存器的配置。

F1系列寄存器介绍

F1系列的寄存器主要有以下几类:

  • 端口配置低寄存器(GPIOx_CRL) (x=A..E)
  • 端口配置高寄存器(GPIOx_CRH) (x=A..E)
  • 端口输入数据寄存器(GPIOx_IDR) (x=A..E)
  • 端口输出数据寄存器(GPIOx_ODR) (x=A..E)
  • 端口位设置/清除寄存器(GPIOx_BSRR) (x=A..E)
  • 端口位清除寄存器(GPIOx_BRR) (x=A..E)
  • 端口配置锁定寄存器(GPIOx_LCKR) (x=A..E)
  1. 其中,对于端口配置低寄存器来说,其作用是用来配置输入输出模式和输出速度的(输入时无需配置速度)
  2. 输入、输出寄存器就是用来读取和写入GPIO端口的电平状态的
  3. 位设置/清除寄存器(GPIOx_BSRR)用于复位(设置为0)置位(设置为1)的,实际上这个寄存器是用来控制输出寄存器的,其和输出寄存器相比的优势在于这个寄存器的操作是原子操作,并且只可以写无法读,同时输出寄存器的操作不是原子操作,可以读也可以写。
  4. 位清除寄存器(GPIOx_BRR)用于清除GPIO端口的某一位的状态,需要注意这个寄存器由于兼容性太差所以一般都不使用,而使用 BSRR 寄存器来取代。
  5. 配置锁定寄存器(GPIOx_LCKR)用来锁定端口位的配置,被设置的端口为被上锁之后无法在下一次复位前被重新配置,这个寄存器用的很少。

注意点

在野火霸道中需要注意的是,当你直接配置好led灯的gpio后,这个led灯就会亮。这是因为,霸道的原理图中的led灯是低位点亮。而刚刚复位的gpio的数据输出寄存器的默认值就是0。所以会被点亮,想要关闭我们应该在led的配置函数中使用:

1
2
GPIO_SetBits(GPIOA,GPIO_Pin); //关闭led灯
GPIO_ResetBits(GPIOA,GPIO_Pin); //开启led灯

关于GPIO_SetBits()这个函数是写BSRR这个寄存器,通过写1,对应的数据输出寄存器会被写为1

关于GPIO_ResetBits()这个函数是写BRR寄存器,通过写1,对应的数据寄存器会被写为0。

所以我们可以知道,在霸道V2中如果想要打开led灯,则需要使用GPIO_ResetBits函数。想要关闭则使用另一个函数。当然我们也可以使用GPIO_WriteBit()来写BRRBSRR两个寄存器。

stm32f4xx系列中的GPIO编程

f4系列的GPIO编程将原来的GPIO口给拆开了,提高了灵活性。

GP = 通用、PP = 推挽、PU = 上拉、PD = 下拉、OD = 开漏、AF = 复用功能。

推挽输出和开漏输出的区别就是,前者可以输出高电平和低电平;但是后者只可以输出低电平,如果想要输出高电平的话需要外接一个上拉电阻。其中模拟接口是对于ADC或者是DAC来使用的

可配置多达 16 个 I/O。GPIOx_MODER 寄存器用于选择 I/O 方向(输入、输出、AF(就是复用)、模拟)。GPIOx_OTYPER 和 GPIOx_OSPEEDR 寄存器分别用于选择输出类型(推挽或开漏)和速度 (无论采用哪种 I/O 方向,都会直接将 I/O 速度引脚连接到相应的 GPIOx_OSPEEDR 寄存器位)。无论采用哪种 I/O 方向,GPIOx_PUPDR 寄存器都用于选择上拉/下拉。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
typedef struct {
uint16_t GPIO_Pin; /* 选择要配置的GPIO引脚 */
uint8_t GPIO_Mode; /* 选择GPIO引脚的工作模式 */
uint8_t GPIO_Speed; /* 选择GPIO引脚的速率 */
uint8_t GPIO_OType; /* 选择GPIO引脚输出类型 */
uint8_t GPIO_PuPd; /* <选择GPIO引脚的上/下拉模式 */
} GPIO_InitTypeDef;

//其中:

/**
* GPIO端口配置模式的枚举定义
*/
typedef enum {
GPIO_Mode_IN = 0x00, /*!< 输入模式 */
GPIO_Mode_OUT = 0x01, /*!< 输出模式 */
GPIO_Mode_AF = 0x02, /*!< 复用模式 */
GPIO_Mode_AN = 0x03 /*!< 模拟模式 */
} GPIOMode_TypeDef;

/**
* GPIO输出类型枚举定义
*/
typedef enum {
GPIO_OType_PP = 0x00, /*!< 推挽模式 */
GPIO_OType_OD = 0x01 /*!< 开漏模式 */
} GPIOOType_TypeDef;

/**
* GPIO输出速率枚举定义
*/
typedef enum {
GPIO_Speed_2MHz = 0x00, /*!< 2MHz */
GPIO_Speed_25MHz = 0x01, /*!< 25MHz */
GPIO_Speed_50MHz = 0x02, /*!< 50MHz */
GPIO_Speed_100MHz = 0x03 /*!<100MHz */
} GPIOSpeed_TypeDef;

/**
*GPIO上/下拉配置枚举定义
*/
typedef enum {
GPIO_PuPd_NOPULL = 0x00,/*浮空*/
GPIO_PuPd_UP = 0x01, /*上拉*/
GPIO_PuPd_DOWN = 0x02 /*下拉*/
} GPIOPuPd_TypeDef;

映射和复用的关系

stm32f1系列中,有复用和重新映射的区别:

stm32f4系列中,有复用和附加功能的区别:

Additionalfunctions:附加,辅助功能,引脚被连接到其他模块使用,使用时直接普通配置即可,例如ADC的采用输入通道,配置为模拟输入。

Alternate functions:复用功能,即将IO口用作普通输入输出以外的功能,例如串口输入输出,使用时需要配置复用模式。

在编程上的区别

实际上,在f1系列芯片中有重映射,但是在f4系列中是没有重映射的,取而代之的是附加功能

f1系列在GPIO中最大的不同就是这个复用功能。F1系列有默认复用,F4没有默认复用,所以F4在配置复用功能时需要给Alternate变量赋值,F1没有这个变量。

f4中,每组I/O口都对应着一个复用器,如GPIOA对应着一个复用器、GPIOB对应着一个复用器……每个复用器分为两部分,如GPIOA对应的复用器分为GPIOA_AFRL、GPIOA_AFRH两部分,其中GPIOx_AFRL负责低8位引脚,即PA0 ~ PA7;而GPIOx_AFRH负责高8位引脚,即PA8 ~ PA15。不是所有的PA引脚都有复用功能,具体的可以去数据手册中查看。

上面这个图就是GPIOA所连接的复用器,这个图标需要和标准库中的函数void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)有关系:

1
2
3
void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)

//引脚复用函数,将前两个参数提供的引脚复用至GPIO_AF,这个GPIO_AF的选择就是通过上面这个表来的。

复用上:

1
2
3
4
5
6
7
1. 打开GPIO外设的时钟,如 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
2. 打开复用外设的时钟,如
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
3. 使用复用器函数,如
void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)

附加功能上(就是f1系列的重映射):

附加功能配置,可以从手册中看到,附加功能几乎是ADC或是DAC,在使用对应引脚时只需要将引脚模式设置为GPIO_MODE_ANALOG模拟即可,不需要设置Alternate复用变量,还有对应外设的初始化即可。

也就是说,f4系列的附加功能的使用就是将GPIO的方向改为模拟

GPIO_HAL库

配置步骤:

  1. 初始化
  2. 编写读函数
  3. 编写写函数
  4. 编写中断服务函数
1
2
3
4
5
6
7
8
9
10
11
12
GPIO_InitTypeDef GPIO_InitStructure;
__HAL_RCC_GPIOE_CLK_ENABLE(); //使能GPIOE时钟

HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);

GPIO_InitStructure.GPIO_Pin = LED1_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(LED1_GPIO_Port, &GPIO_InitStruct);

HAL_NVIC_SetPriority(EXTI1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(EXTI1_IRQn);

以上就是 GPIO HAL 库的基本配置步骤。

引脚复用

由于 stm32 中的引脚实际上是有限的,每一个引脚都不是仅仅只有一个单一的功能,所以 stm32 提供了一个 AFIO 的外设来实现引脚的复用,但是只有在 F4 之后的芯片才加入了这个外设(复用器)

复用器的特点:

  1. 每一个引脚都有一个复用器
  2. 复用器使用的是 16 路复用功能输入(AF0-AF15)

参考资料

https://blog.51cto.com/u_15315240/3229581

http://news.eeworld.com.cn/mcu/ic557652.html?ipcity__1865=CqfxR7D%3DPxuDlxGgx%2BOewnq0KDtGCb98eD&alichlgref=http%3A%2F%2Fnews.eeworld.com.cn%2Fmcu%2Fic557652.html

https://blog.csdn.net/plmm__/article/details/132045377?spm=1001.2014.3001.5502

https://blog.csdn.net/plmm__/article/details/132045377?spm=1001.2014.3001.5502


stm32中的GPIO
https://ysc2.github.io/ysc2.github.io/2023/11/17/stm32中的GPIO/
作者
Ysc
发布于
2023年11月17日
许可协议