STM32单片机GPIO编程:掌握引脚配置、模式和中断的精髓
发布时间: 2024-07-02 15:23:04 阅读量: 10 订阅数: 15 ![](https://csdnimg.cn/release/wenkucmsfe/public/img/col_vip.0fdee7e1.png)
![](https://csdnimg.cn/release/wenkucmsfe/public/img/col_vip.0fdee7e1.png)
![STM32单片机GPIO编程:掌握引脚配置、模式和中断的精髓](https://img-blog.csdnimg.cn/20210122101349507.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1Njk5MTk1,size_16,color_FFFFFF,t_70)
# 1. STM32 GPIO 简介**
GPIO(通用输入输出)是 STM32 微控制器上一个重要的外设,它允许与外部设备进行交互。GPIO 引脚可以配置为输入或输出,并具有各种电气特性,使其适用于各种应用。本章将介绍 STM32 GPIO 的基本概念、引脚配置和输入输出操作。
# 2. GPIO 编程基础
### 2.1 GPIO 引脚配置
#### 2.1.1 引脚模式设置
GPIO 引脚的模式设置决定了引脚的功能,可以配置为输入、输出、模拟输入或模拟输出。
```c
// 设置 GPIOA 引脚 0 为输出模式
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
```
**参数说明:**
* `GPIO_PIN_0`:引脚编号,范围为 0~15
* `GPIO_MODE_OUTPUT_PP`:输出模式,推挽输出
#### 2.1.2 引脚电气特性配置
GPIO 引脚的电气特性配置包括电阻、速度和下拉/上拉电阻。
```c
// 设置 GPIOA 引脚 1 为输入模式,带下拉电阻
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
```
**参数说明:**
* `GPIO_MODE_INPUT`:输入模式
* `GPIO_PULLDOWN`:下拉电阻
### 2.2 GPIO 输入输出操作
#### 2.2.1 数字输入输出
GPIO 引脚可以作为数字输入或输出使用,通过设置或读取引脚电平来实现。
```c
// 设置 GPIOA 引脚 2 为高电平
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
// 读取 GPIOA 引脚 3 的电平
uint8_t pin_level = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_3);
```
**参数说明:**
* `GPIO_PIN_SET`:设置高电平
* `GPIO_PIN_RESET`:设置低电平
* `HAL_GPIO_ReadPin`:读取引脚电平,返回 0 或 1
#### 2.2.2 模拟输入输出
GPIO 引脚也可以作为模拟输入或输出使用,通过 ADC 或 DAC 模块实现。
```c
// 设置 GPIOA 引脚 4 为模拟输入
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 设置 GPIOA 引脚 5 为模拟输出
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_OUT;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
```
**参数说明:**
* `GPIO_MODE_ANALOG`:模拟输入模式
* `GPIO_MODE_ANALOG_OUT`:模拟输出模式
# 3.1 GPIO 中断配置
#### 3.1.1 中断源选择
STM32 的 GPIO 中断源可以分为外部中断和内部中断。外部中断是由外部信号触发,而内部中断是由 GPIO 引脚本身的状态变化触发。
**外部中断**
外部中断源有 16 个,对应于 GPIOA 到 GPIOF 的 16 个引脚。每个引脚可以配置为中断源,并可以设置中断触发方式,包括上升沿、下降沿、双沿、低电平和高电平触发。
**内部中断**
内部中断源有 8 个,对应于 GPIOA 到 GPIOF 的 8 个端口。每个端口可以配置为中断源,并可以设置中断触发方式,包括上升沿、下降沿、双沿、低电平和高电平触发。
#### 3.1.2 中断优先级设置
STM32 的 GPIO 中断优先级分为 4 级,从 0 到 3,其中 0 级优先级最高,3 级优先级最低。中断优先级可以通过寄存器配置,每个中断源可以单独设置优先级。
### 3.2 GPIO 中断处理函数
#### 3.2.1 中断服务函数编写
中断服务函数是当 GPIO 中断发生时执行的代码。中断服务函数的编写需要遵循以下步骤:
1. **声明中断服务函数:**中断服务函数需要声明为 `void EXTIx_IRQHandler(void)`,其中 `x` 为中断源号。
2. **保存寄存器:**在中断服务函数的开头,需要保存寄存器,以避免寄存器被其他中断或异常修改。
3. **清除中断标志:**中断发生后,需要清除中断标志,以防止中断重复触发。
4. **执行中断处理:**在中断处理函数中,需要执行中断处理代码,例如读取 GPIO 引脚状态、控制 LED 等。
5. **恢复寄存器:**在中断服务函数的结尾,需要恢复寄存器,以恢复中断前的状态。
#### 3.2.2 中断处理流程
GPIO 中断处理流程如下:
1. **中断源触发:**当 GPIO 引脚的状态发生变化时,会触发中断源。
2. **中断控制器响应:**中断控制器收到中断源信号后,会根据中断优先级决定是否响应中断。
3. **中断服务函数执行:**如果中断控制器响应中断,则会执行对应的中断服务函数。
4. **中断处理:**在中断服务函数中,执行中断处理代码,例如读取 GPIO 引脚状态、控制 LED 等。
5. **中断返回:**中断处理完成后,中断服务函数返回,中断控制器恢复中断前的状态。
# 4. GPIO 实践应用
### 4.1 LED 控制
#### 4.1.1 LED 初始化
**代码块:**
```c
// 初始化 LED 引脚
void LED_Init(void)
{
// 使能 GPIOA 时钟
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
// 设置 PA5 为输出模式
GPIOA->MODER &= ~GPIO_MODER_MODE5;
GPIOA->MODER |= GPIO_MODER_MODE5_0;
// 设置 PA5 为推挽输出
GPIOA->OTYPER &= ~GPIO_OTYPER_OT5;
}
```
**逻辑分析:**
* 首先,使能 GPIOA 时钟,确保 GPIOA 可以正常工作。
* 然后,将 PA5 引脚配置为输出模式,允许它输出信号。
* 最后,将 PA5 引脚配置为推挽输出,使它能够驱动外部负载。
**参数说明:**
* `RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;`:使能 GPIOA 时钟。
* `GPIOA->MODER &= ~GPIO_MODER_MODE5;`:清除 PA5 引脚的模式位。
* `GPIOA->MODER |= GPIO_MODER_MODE5_0;`:设置 PA5 引脚为输出模式。
* `GPIOA->OTYPER &= ~GPIO_OTYPER_OT5;`:清除 PA5 引脚的输出类型位。
#### 4.1.2 LED 闪烁控制
**代码块:**
```c
// LED 闪烁控制
void LED_Blink(void)
{
while (1)
{
// 点亮 LED
GPIOA->ODR |= GPIO_ODR_OD5;
// 延时 500ms
HAL_Delay(500);
// 熄灭 LED
GPIOA->ODR &= ~GPIO_ODR_OD5;
// 延时 500ms
HAL_Delay(500);
}
}
```
**逻辑分析:**
* 在一个无限循环中,不断点亮和熄灭 LED。
* `GPIOA->ODR |= GPIO_ODR_OD5;`:点亮 LED。
* `HAL_Delay(500);`:延时 500ms。
* `GPIOA->ODR &= ~GPIO_ODR_OD5;`:熄灭 LED。
* `HAL_Delay(500);`:延时 500ms。
**参数说明:**
* `GPIOA->ODR |= GPIO_ODR_OD5;`:设置 PA5 引脚为高电平,点亮 LED。
* `HAL_Delay(500);`:调用 HAL 库函数延时 500ms。
* `GPIOA->ODR &= ~GPIO_ODR_OD5;`:清除 PA5 引脚为低电平,熄灭 LED。
### 4.2 按键检测
#### 4.2.1 按键初始化
**代码块:**
```c
// 按键初始化
void Button_Init(void)
{
// 使能 GPIOC 时钟
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
// 设置 PC13 为输入模式
GPIOC->MODER &= ~GPIO_MODER_MODE13;
// 设置 PC13 为上拉输入
GPIOC->PUPDR |= GPIO_PUPDR_PUPD13_1;
}
```
**逻辑分析:**
* 首先,使能 GPIOC 时钟,确保 GPIOC 可以正常工作。
* 然后,将 PC13 引脚配置为输入模式,允许它接收外部信号。
* 最后,将 PC13 引脚配置为上拉输入,使它在没有外部信号时保持高电平。
**参数说明:**
* `RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;`:使能 GPIOC 时钟。
* `GPIOC->MODER &= ~GPIO_MODER_MODE13;`:清除 PC13 引脚的模式位。
* `GPIOC->PUPDR |= GPIO_PUPDR_PUPD13_1;`:设置 PC13 引脚为上拉输入。
#### 4.2.2 按键状态检测
**代码块:**
```c
// 按键状态检测
uint8_t Button_GetState(void)
{
// 读取 PC13 引脚电平
uint8_t state = (GPIOC->IDR & GPIO_IDR_ID13) >> 13;
// 返回按键状态
return state;
}
```
**逻辑分析:**
* 读取 PC13 引脚的电平,并将其存储在 `state` 变量中。
* 如果 PC13 引脚电平为高,则 `state` 为 1,表示按键未按下。
* 如果 PC13 引脚电平为低,则 `state` 为 0,表示按键已按下。
**参数说明:**
* `(GPIOC->IDR & GPIO_IDR_ID13) >> 13;`:读取 PC13 引脚的电平,并右移 13 位,得到按键状态。
* `state`:按键状态,1 表示未按下,0 表示已按下。
# 5. GPIO 高级应用**
### 5.1 GPIO 复用功能
**5.1.1 复用功能介绍**
GPIO 引脚除了基本的输入输出功能外,还具有复用功能,即可以连接到不同的外设模块,如串口、I2C、SPI 等。复用功能的配置允许用户灵活地使用 GPIO 引脚,满足不同的系统需求。
**5.1.2 复用功能配置**
复用功能的配置需要修改 GPIO 寄存器中的 Alternate Function(AF)位域。AF 位域指定了引脚连接到哪个外设模块。以下代码展示了如何配置 GPIOA 引脚 0 的复用功能为串口 1:
```c
// 启用 GPIOA 时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
// 设置 GPIOA 引脚 0 的复用功能为 AF1(串口 1)
GPIOA->AFR[0] &= ~(0xF << (0 * 4));
GPIOA->AFR[0] |= (0x1 << (0 * 4));
```
### 5.2 GPIO 时钟配置
**5.2.1 GPIO 时钟源选择**
GPIO 外设的时钟源可以是系统时钟(SYSCLK)或高速时钟(HCLK)。系统时钟的频率通常为 16 MHz,而高速时钟的频率则取决于系统配置。
**5.2.2 GPIO 时钟频率设置**
GPIO 时钟的频率可以通过修改 RCC 寄存器中的 AHB1ENR 和 AHB2ENR 位域来设置。以下代码展示了如何将 GPIOA 外设的时钟源设置为高速时钟:
```c
// 启用 GPIOA 时钟
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
// 设置 GPIOA 时钟源为高速时钟
RCC->CFGR |= RCC_CFGR_PPRE1_1;
```
0
0
相关推荐
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)