STM32F1的IO口简介

STM32F1的IO口简介

基本介绍

STM32的引脚可设置为可设置为:普通IO功能、复用功能、重映射功能。不过普通IO功能、复用功能用得比较多。

  1. 普通 IO 功能一般需要使能 GPIOAGPIOBGPIOC 时钟
  2. 需要使用复用功能,如 STM32F103RCT6 的串口1功能,需要使用 PA9PA10 两个引脚,此时需要使用串口1时钟 USART1
  3. 需要用到外设的重映射功能时需要使能 AFIO 的时钟。

关于重映射功能举例如下:

1
2
3
4
重映射USART2
USART2的TX/RX在PA.2/3
PA.2已经被Timer2的channel3使用
需要把USART2的TX/RX重映射到PD.5/6

库函数的调用步骤如下:

  1. 使能被重新映射到的I/O端口时钟

    1
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);

  2. 使能被重新映射的外设时钟

    1
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

  3. 使能AFIO功能的时钟(勿忘!)

    1
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

  4. 进行重映射

    1
    GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);

初始化步骤

  1. 使用 RCC_APB2PeriphClockCmd 函数使能相关 APB2 外设时钟
  2. 通过 GPIO_Init 函数初始化并配置各IO口
  3. 使用 GPIO_ReadInputDataBit 读取IO口电平状态,使用 GPIO_SetBitsGPIO_ResetBits 来设置各IO口的值 (实际我们使用 PAout(0)=1, PBout(2)=0; 这种写法去设置 IO 口的电平状态)

相关函数定义和说明如下:

1. GPIO_Init 初始化函数: 配置IO口的模式和速度

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
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);

typedef enum {
GPIOA,
GPIOB,
GPIOC
} GPIO_TypeDef;

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

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;

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

示例:

1
2
3
4
5
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; // PB5 端口设置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 速度 50MHz
GPIO_Init(GPIOB, &GPIO_InitSture); // 根据参数配置IO口 PB5

2. GIPO_ReadInputDataBit: 读取IO口的电平状态

1
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, unit16_t GPIO_Pin);

示例:

1
2
// 返回值是 1(Bit_SET) 或者 0(Bit_RESET)
GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1); // 读取IO口 PA1 的电平状态

3. GPIO_Write: 一次性设置GPIO的多个端口值(通过ODR寄存器实现)

1
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

4. 通过 GPIO_SetBits 和 GPIO_ResetBits 来操作各IO口的值

1
2
void GPIO_SetBits(GPIO_TypeDef* GPIOx, unit16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, unit16_t GPIO_Pin);

示例:

1
2
GPIO_SetBits(GPIOC, GPIO_Pin_3); // 设置IO口 PC3 输出 1
GPIO_ReSetBits(GPIOC, GPIO_Pin_3); // 设置IO口 PC3 输出 0

5. 通过 RCC_APB2PeriphClockCmd 使能IO时钟

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* RCC_APB2Periph_AFIO 功能复用IO时钟
* 需要用到外设的重映射功能时才需要使能AFIO时钟
*
* RCC_APB2Periph_GPIOA GPIOA时钟
* RCC_APB2Periph_GPIOB GPIOB时钟
* RCC_APB2Periph_GPIOC GPIOC时钟
* RCC_APB2Periph_USART1 USART1时钟(串口1时钟)PA9(TX)、PA10(RX)
*/
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
typedef enum {
Enable = 1,
Disable = 0
} FunctionalState;

参考链接

  1. STM32端口复用和重映射
  2. 什么情况下需要使能AFIO的时钟呢?