STM32F103 学习笔记(2)—— GPIO 初始化/配置

STM32F103微控制器的GPIO引脚具有多种工作模式,包括输入浮空、输入上拉、输入下拉、模拟输入以及开漏和推挽输出等。这些模式用于适应不同的外部设备交互需求。GPIO的配置涉及端口时钟使能、模式选择和电平设置,例如LED初始化通常涉及推挽输出模式和端口速度配置。此外,调试端口如SWIO-PA13和SWCLK-PA14也可复用为GPIO口。
摘要由CSDN通过智能技术生成

一、STM32F103 微控制器的 GPIO 简介

1. GPIO 简介

STM32F103 是 STM32 系列微控制器中的型号,也被称为 STM32F1 系列。它基于 ARM Cortex-M3 内核,以其丰富的外设和低功耗特性而闻名。GPIO(General Purpose Input Output)是 STM32F103 微控制器上的通用输入输出引脚。

STM32F103 微控制器提供了多个 GPIO 引脚,用于与外部设备进行数字信号的输入和输出。每个引脚都可以通过配置来灵活地设置为输入或输出。作为输入引脚时,GPIO 可以读取外部设备的状态,如按钮的按下状态或传感器的测量值。作为输出引脚时,GPIO 可以控制外部设备的操作,如驱动 LED 灯的亮灭。

2. GPIO 内部结构

二、GPIO 的 8 种工作模式

4种输入模式:

  • 输入浮空(GPIO_Mode_IN_FLOATING)
  • 输入上拉  (GPIO_Mode_IPU)
  • 输入下拉  (GPIO_Mode_IPD)
  • 模拟输入  (GPIO_Mode_AIN)

4种输出模式:

  • 开漏输出  (GPIO_Mode_Out_OD)
  • 开漏复用输出  (GPIO_Mode_AF_OD)
  • 推挽式输出  (GPIO_Mode_Out_PP)
  • 推挽式复用输出  (GPIO_Mode_AF_PP)

1. GPIO 的输入工作模式 1——输入浮空模式(GPIO_Mode_IN_FLOATING)

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

2. GPIO 的输入工作模式 2——输入上拉模式  (GPIO_Mode_IPU)

上拉输入状态下是将不确定的信号通过上拉电阻嵌位在高电平,防止输入端悬空,减少外部电流对芯片的干扰,同时起到限流作用,增加高电平输出时的驱动能力。当 GPIO 引脚无输入时,上拉输入在默认状态下为高电平。

3. GPIO 的输入工作模式  3——输入下拉模式  (GPIO_Mode_IPD)

下拉输入状态下是将不确定的信号通过下拉电阻嵌位在低电平,防止输入端悬空,减少外部电流对芯片的干扰,同时起到限流作用,增加低电平输出时的驱动能力。当 GPIO 引脚无输入时,下拉输入在默认状态下为低电平。

4. GPIO 的输入工作模式 4——模拟输入模式  (GPIO_Mode_AIN)

模拟输入状态即关闭施密特触发器,将电压信号传送到片上外设模块(不接上下拉电阻)。与数字输入模式不同,模拟输入模式允许引脚采样并转换模拟电压信号为对应的数字值。

5. GPIO 的输出工作模式 1——开漏输出模式  (GPIO_Mode_Out_OD)

开漏输出模式允许 GPIO 引脚输出低电平,而在高电平时处于高阻抗状态。它常用于共享总线或与其他设备联动的场景,需要外部上拉电阻来实现引脚的高电平输出。开漏输出的输出端相当于三极管的集电极,要得到高电平状态需要上拉电阻才行。适合于做电流型的驱动,其吸收电流的能力相对强(一般 20 ma以内)。

6. GPIO 的输出工作模式 2——开漏复用输出模式  (GPIO_Mode_AF_OD)

开漏复用输出模式允许 STM32 微控制器的 GPIO 引脚以开漏输出的方式连接到外部电路,并通过复用功能与其他外设或功能模块进行共享。

7. GPIO 的输出工作模式 3——推挽式输出模式  (GPIO_Mode_Out_PP)

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

8. GPIO 的输出工作模式 4——推挽式复用输出模式  (GPIO_Mode_AF_PP)

推挽式复用输出模式允许 STM32 微控制器的 GPIO 引脚以推挽输出的方式连接到外部电路,并通过复用功能与其他外设或功能模块进行共享。

9. GPIO 引脚配置方式

通常有 5 种方式使用某个引脚功能,它们的配置方式如下:

(1)作为普通 GPIO 输入:根据需要配置该引脚为浮空输入、带弱上拉输入或带弱下拉输入,同时不要使能该引脚对应的所有复用功能模块。

(2)作为普通 GPIO 输出:根据需要配置该引脚为推挽输出或开漏输出,同时不要使能该引脚对应的所有复用功能模块。

(3)作为普通模拟输入:配置该引脚为模拟输入模式,同时不要使能该引脚对应的所有复用功能模块。

(4)作为内置外设的输入:根据需要配置该引脚为浮空输入、带弱上拉输入或带弱下拉输入,同时使能该引脚对应的某个复用功能模块。

(5)作为内置外设的输出:根据需要配置该引脚为复用推挽输出或复用开漏输出,同时使能该引脚对应的所有复用功能模块。

三、LED 灯初始化/配置(调用库函数)

/*************************************************************************
 * 初始化LED输出端口
 ************************************************************************/
void LED_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能GPIOC端口时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);  
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;         // LED-->PC.13端口
    GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_PP;    // 推挽输出模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  // GPIO口速度为50MHz
    GPIO_Init(GPIOC, &GPIO_InitStructure);             // 初始化PC.13端口
    
    // PC.13端口输出高电平 等同LED=1
    GPIO_SetBits(GPIOC, GPIO_Pin_13);                                   
}      

1. 操作步骤 1——使能端口时钟(调用下列函数)

void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
    assert_param(IS_FUNCTIONAL_STATE(NewState));
    if (NewState != DISABLE)
    {
        RCC->APB2ENR |= RCC_APB2Periph;
    }
    else
    {
        RCC->APB2ENR &= ~RCC_APB2Periph;
    }
}

(1)形参 RCC_APB2Periph 的有效选择项

#define RCC_APB2Periph_AFIO              ((uint32_t)0x00000001)
#define RCC_APB2Periph_GPIOA             ((uint32_t)0x00000004)
#define RCC_APB2Periph_GPIOB             ((uint32_t)0x00000008)
#define RCC_APB2Periph_GPIOC             ((uint32_t)0x00000010)
#define RCC_APB2Periph_GPIOD             ((uint32_t)0x00000020)
#define RCC_APB2Periph_GPIOE             ((uint32_t)0x00000040)
#define RCC_APB2Periph_GPIOF             ((uint32_t)0x00000080)
#define RCC_APB2Periph_GPIOG             ((uint32_t)0x00000100)
#define RCC_APB2Periph_ADC1              ((uint32_t)0x00000200)
#define RCC_APB2Periph_ADC2              ((uint32_t)0x00000400)
#define RCC_APB2Periph_TIM1              ((uint32_t)0x00000800)
#define RCC_APB2Periph_SPI1              ((uint32_t)0x00001000)
#define RCC_APB2Periph_TIM8              ((uint32_t)0x00002000)
#define RCC_APB2Periph_USART1            ((uint32_t)0x00004000)
#define RCC_APB2Periph_ADC3              ((uint32_t)0x00008000)
#define RCC_APB2Periph_TIM15             ((uint32_t)0x00010000)
#define RCC_APB2Periph_TIM16             ((uint32_t)0x00020000)
#define RCC_APB2Periph_TIM17             ((uint32_t)0x00040000)
#define RCC_APB2Periph_TIM9              ((uint32_t)0x00080000)
#define RCC_APB2Periph_TIM10             ((uint32_t)0x00100000)
#define RCC_APB2Periph_TIM11             ((uint32_t)0x00200000)

(2)形参 NewState 的有效选择项

#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))

2. 操作步骤 2——配置 I/O 口状态

// 声明初始化I/O口的结构体并进行配置
GPIO_InitTypeDef  GPIO_InitStructure; 

// GPIO端口初始化函数
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)

结构体定义函数

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;
a. 参数 GPIO_Pin 的有效选择项
#define GPIO_Pin_0                 ((uint16_t)0x0001)  /*!< Pin 0 selected */
#define GPIO_Pin_1                 ((uint16_t)0x0002)  /*!< Pin 1 selected */
#define GPIO_Pin_2                 ((uint16_t)0x0004)  /*!< Pin 2 selected */
#define GPIO_Pin_3                 ((uint16_t)0x0008)  /*!< Pin 3 selected */
#define GPIO_Pin_4                 ((uint16_t)0x0010)  /*!< Pin 4 selected */
#define GPIO_Pin_5                 ((uint16_t)0x0020)  /*!< Pin 5 selected */
#define GPIO_Pin_6                 ((uint16_t)0x0040)  /*!< Pin 6 selected */
#define GPIO_Pin_7                 ((uint16_t)0x0080)  /*!< Pin 7 selected */
#define GPIO_Pin_8                 ((uint16_t)0x0100)  /*!< Pin 8 selected */
#define GPIO_Pin_9                 ((uint16_t)0x0200)  /*!< Pin 9 selected */
#define GPIO_Pin_10                ((uint16_t)0x0400)  /*!< Pin 10 selected */
#define GPIO_Pin_11                ((uint16_t)0x0800)  /*!< Pin 11 selected */
#define GPIO_Pin_12                ((uint16_t)0x1000)  /*!< Pin 12 selected */
#define GPIO_Pin_13                ((uint16_t)0x2000)  /*!< Pin 13 selected */
#define GPIO_Pin_14                ((uint16_t)0x4000)  /*!< Pin 14 selected */
#define GPIO_Pin_15                ((uint16_t)0x8000)  /*!< Pin 15 selected */
#define GPIO_Pin_All               ((uint16_t)0xFFFF)  /*!< All pins selected */
b. 参数 GPIO_Speed 的有效选择项
typedef enum
{ 
    GPIO_Speed_10MHz = 1,
    GPIO_Speed_2MHz, 
    GPIO_Speed_50MHz
} GPIOSpeed_TypeDef;

#define IS_GPIO_SPEED(SPEED) (((SPEED) == GPIO_Speed_10MHz) || ((SPEED) == GPIO_Speed_2MHz) || \
                              ((SPEED) == GPIO_Speed_50MHz))
c. 参数 GPIO_Mode 的有效选择项
typedef enum
{ 
    GPIO_Mode_AIN = 0x00,          //模拟输入
    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;

#define IS_GPIO_MODE(MODE) (((MODE) == GPIO_Mode_AIN) || ((MODE) == GPIO_Mode_IN_FLOATING) || \
                            ((MODE) == GPIO_Mode_IPD) || ((MODE) == GPIO_Mode_IPU) || \
                            ((MODE) == GPIO_Mode_Out_OD) || ((MODE) == GPIO_Mode_Out_PP) || \
                            ((MODE) == GPIO_Mode_AF_OD) || ((MODE) == GPIO_Mode_AF_PP))

3. 操作步骤 3——设置 I/O 口输出电平(调用下列函数)

// 设置I/O口输出低电平
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
    assert_param(IS_GPIO_PIN(GPIO_Pin));
  
    GPIOx->BRR = GPIO_Pin;
}
// 设置I/O口输出高电平
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
    assert_param(IS_GPIO_PIN(GPIO_Pin));
  
    GPIOx->BSRR = GPIO_Pin;
}

(1)参数 GPIOx 有效选择项

#define IS_GPIO_ALL_PERIPH(PERIPH) (((PERIPH) == GPIOA) || \
                                    ((PERIPH) == GPIOB) || \
                                    ((PERIPH) == GPIOC) || \
                                    ((PERIPH) == GPIOD) || \
                                    ((PERIPH) == GPIOE) || \
                                    ((PERIPH) == GPIOF) || \
                                    ((PERIPH) == GPIOG))

(2)参数 GPIO_Pin 有效选择项

#define GPIO_Pin_0                 ((uint16_t)0x0001)  /*!< Pin 0 selected */
#define GPIO_Pin_1                 ((uint16_t)0x0002)  /*!< Pin 1 selected */
#define GPIO_Pin_2                 ((uint16_t)0x0004)  /*!< Pin 2 selected */
#define GPIO_Pin_3                 ((uint16_t)0x0008)  /*!< Pin 3 selected */
#define GPIO_Pin_4                 ((uint16_t)0x0010)  /*!< Pin 4 selected */
#define GPIO_Pin_5                 ((uint16_t)0x0020)  /*!< Pin 5 selected */
#define GPIO_Pin_6                 ((uint16_t)0x0040)  /*!< Pin 6 selected */
#define GPIO_Pin_7                 ((uint16_t)0x0080)  /*!< Pin 7 selected */
#define GPIO_Pin_8                 ((uint16_t)0x0100)  /*!< Pin 8 selected */
#define GPIO_Pin_9                 ((uint16_t)0x0200)  /*!< Pin 9 selected */
#define GPIO_Pin_10                ((uint16_t)0x0400)  /*!< Pin 10 selected */
#define GPIO_Pin_11                ((uint16_t)0x0800)  /*!< Pin 11 selected */
#define GPIO_Pin_12                ((uint16_t)0x1000)  /*!< Pin 12 selected */
#define GPIO_Pin_13                ((uint16_t)0x2000)  /*!< Pin 13 selected */
#define GPIO_Pin_14                ((uint16_t)0x4000)  /*!< Pin 14 selected */
#define GPIO_Pin_15                ((uint16_t)0x8000)  /*!< Pin 15 selected */
#define GPIO_Pin_All               ((uint16_t)0xFFFF)  /*!< All pins selected */

四、STM32 调试端口复用为 IO 口

当 IO 口不够用时,可以复用调试端口:SWIO-PA13,SWCLK-PA14

{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);      // 端口重映射配置
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	  // 使能GPIOA端口时钟

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;  // 端口引脚配置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		  // 推挽输出模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		  // IO口速度为50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure);					  // 根据设定参数初始化PA.13、PA.14
}

  • 33
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值