Bootstrap

STM32系统的GPIO原理与结构

一、GPIO接口原理

  原理概述:GPIO是通用输入输出接口,是单片机的一些引脚,可以控制LED灯、蜂鸣器,也可用于按键输入、ADC采样等,从而实现STM32单片机与外部硬件之间的连接与数据交互。通用I/O(GPIO)是STM32微处理器非常重要的一种接口,具有使用灵活、可配置、多功能等优点。

  STM32系列微处理器最多可以有7组GPIO端口,每组端口有16个I/O接口,每个接口包含下列四种寄存器:

二、GPIO的基本结构

2.1 四种输入模式

输入模式应用特点
模拟输入直接连接到内部ADC模块,可以实现对模拟信号的采样。
浮空输入优点:输入阻抗高,MCU采集的状态是单纯的外部信号;缺点:完全浮空,状态不稳定。由于浮空阻抗大,一般由于IIC\USART等通信协议。
上拉输入I/O信号线连接到一个电阻到VCC上,当外部不接信号的时候,管脚默认为高电平。当输入信号比较弱时,容易受到干扰不稳定,选择上拉。
下拉输入I/O信号线连接到一个电阻到地上,当外部不接信号的时候,管脚默认为低电平。

2.2 四种输出模式

输出模式应用特点
开漏输出优点:可实现电平转换,输出电平取决于上拉电阻电源;缺点:高电平驱动能力差,取决于外部上拉电阻。
推挽输出输出高低电平与电源电压j基本没有压差,可以提供较强的高电平与低电平驱动能力。
复用开漏

片上外设功能,比如IIC的SDL、SCL引脚等。

复用推挽片上外设功能,比如SPI的SCK、MISO、MOSI引脚,串口等。

2.3 GPIO内部结构原理

GPIO每个I/O口都有上拉和下拉二极管,当外部电压过高时,上拉二极管导通,从而起到保护端口的作用;反之同理。

1. 输入模式

GPIO支持4种输入模式:浮空输入、上拉输入、下拉输入、模拟输入,所有模式有寄存器CNFy[1:0]控制,该寄存器和控制着对应开关。

(1)模拟输入

打开输入通道上拉和下拉开关,施密特触发器关闭,信号从模拟通道输入到内部AD采样电路。

(2)浮空输入

打开输入通道上拉和下拉开关,模拟通道关闭,施密特触发器能把输入畸形信号转换成标准的方波输入高低电平。浮空输入模式下,I/O的电平状态是不确定的,完全由外部输入决定;如果在该引脚悬空(在无信号输入)的情况下,读取该端口的电平是不确定的。

(3)上拉输入

上拉输入模式下,I/O端口的电平信号直接进入输入数据寄存器。默认情况下,上拉电阻连接VDD,无信号输入时,IDR读入高电平。

(4)下拉输入

下拉输入模式下,I/O端口的电平信号直接进入输入数据寄存器。无信号输入时,IDR读入低电平。

2. 输出模式

4种输出模式:开漏输出、复用开漏输出、推挽输出、复用推挽输出。输出控制电路和MOS驱动关都有相应速度,因此,输出模式有10Hz,2MHz,50MHz三种频率可选择。

(1)开漏输出

如图,输出端口上拉P-MOS管截止,下拉N-MOS管受数据的控制。当ODR寄存器的数据为0时,下拉N-MOS管导通,输出低电平;当ODR寄存器输出数据为1时,下拉N-MOS管截止,端口出现浮空模式,因此,需要外接上拉电阻。优点是:可以实现线与功能,如IIC通信。

(2)复用开漏输出

复用开漏输出模式与开漏输出类似。输出的高低电平的来源,不是让CPU直接写输出数据寄存器,取而代之利用片上外设模块的复用功能输出来决定的。

(3)推挽输出

上拉P-MOS管和下拉N-MOS管交替工作。当ODR寄存器输出为0时,下拉N-MOS管导通,P-MOS管截止,输出0;当ODR寄存器输出为1时,下拉N-MOS管截止,P-MOS管导通,输出1。这样即提高电路的负载能力,又提高开关速度,且导通损耗小,效率高。

(4)复用推挽输出

复用推挽输出模式与推挽输出类似。输出的高低电平的来源,不是让CPU直接写输出数据寄存器,取而代之利用片上外设模块的复用功能输出来决定的。

三、GPIO库函数

函数名描述
GPIO_DeInit将外设GPIO寄存器重设为缺省值
GPIO_AFIODeInit将复用功能(重映射事件控制和EXTI设置)重设为缺省值
GPIO_Init根据GPIO_StructInit中指定的参数初始化外设GPIOx寄存器
GPIO_StructInit把GPIO_StructInit中的每一个参数按缺省值填入
GPIO_ReadInputDataBit读取指定端口管脚的输入
GPIO_ReadInputData读取指定的GPIO端口输入
GPIO_ReadOutputDataBit读取指定端口管脚的输出
GPIO_ReadOutputData读取指定的GPIO端口输出
GPIO_SetBits设置指定的数据端口位
GPIO_ResetBits清除指定的数据端口位
GPIO_WriteBit设置或清除指定的数据端口位
GPIO_Write向指定的GPIO数据端口写入数据
GPIO_PinLockConfig锁定GPIO管脚设置寄存器
GPIO_EventOutputConfig选择GPIO管脚用作事件输出
GPIO_EventOutputCmd使能或使能事件输出
GPIO_PinRemapConfig改变指定管脚的映射
GPIO_EXTILineConfig选择GPIO管脚用作外部中断线路

(1)GPIO_SetBits()(与 GPIO_ResetBits函数相同)

功能描述:设置指定的数据端口位;

函数原形:GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

输入参数1:GPIOx可以是A、B、C、D或E,该参数用来选择GPIO外设;

输入参数2:GPIO_Pin,待设定的端口位,该参数可以取GPIO_Pin_x(x可以是0~15)的任意组合;

例如:把GPIOA端口的第1和第5引脚置1

GPIO_SetBits(GPIOA, GPIO_Pin_1 | PIO_Pin_5); //置 1

GPIO_ResetBits(GPIOA, GPIO_Pin_1 | PIO_Pin_5); //清 0

(2)根据GPIO_InitStruct中指定的参数初始化外设GPIOx寄存器的函数GPIO_Init();

函数原形:GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);

输入参数1:GPIOx可以是A、B、C、D或E,该参数用来选择GPIO外设;

输入参数2:GPIO_InitStruc,指向结构体GPIO_InitTypeDef的指针,包含了外设GPIO的配置信息,GPIO_InitTypeDef 定义于文件"stm32f10x_gpio.h"中;

typedef struct
{
  uint16_t GPIO_Pin;             /*!< Specifies the GPIO pins to be configured.
                                      This parameter can be any value of @ref GPIO_pins_define */

  GPIOSpeed_TypeDef GPIO_Speed;  /*!< Specifies the speed for the selected pins.
                                      This parameter can be a value of @ref GPIOSpeed_TypeDef */

  GPIOMode_TypeDef GPIO_Mode;    /*!< Specifies the operating mode for the selected pins.
                                      This parameter can be a value of @ref GPIOMode_TypeDef */
}GPIO_InitTypeDef;

GPIO_Pin:该参数选择待设置的GPIO管脚,使用操作符" | "可以一次选中多个管脚,该参数有:

  • GPIO_Pin_0:选中管脚0;
  • GPIO_Pin_All:选中所有管脚;
  • GPIO_Pin_None:无管脚被选中;

GPIO_Speed:用以设置选中管脚的频率,取值有:

  •   GPIO_Speed_10MHz:最高输出频率10MHz;
  •   GPIO_Speed_2MHz:最高输出频率2MHz;
  •   GPIO_Speed_50MHz:最高输出频率50MHz;

GPIO_Mode:用以设置选中管脚的工作状态,取值有:

  • GPIO_Mode_AIN :模拟输入
  • GPIO_Mode_IN_FLOATING :浮空输入
  • GPIO_Mode_IPD :下拉输入
  • GPIO_Mode_IPU :上拉输入
  • GPIO_Mode_Out_OD :开漏输出
  • GPIO_Mode_Out_PP :推挽输出
  • GPIO_Mode_AF_OD :复用开漏输出
  • GPIO_Mode_AF_PP :复用推挽输出

例如,配置GPIOB为推挽输出模式

GPIO_InitTypeDef GPIO_InitStructure;            // 定义结构体

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; // 管脚5  
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   // 推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  // 输出频率为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);        // 把参数写入寄存器

;