STM32单片机I_O端口详解:输入输出操作的权威宝典
发布时间: 2024-07-03 15:36:55 阅读量: 194 订阅数: 42
STM32.zip_STM32单片机_STM32教程_stm32 tutorial_stm32优秀教材_stm单片机教程
5星 · 资源好评率100%
![STM32单片机I_O端口详解:输入输出操作的权威宝典](https://img-blog.csdnimg.cn/2020101710235492.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dzcV82NjY=,size_16,color_FFFFFF,t_70)
# 1. STM32 I_O端口基础**
STM32单片机I/O端口是与外部世界交互的桥梁,负责输入和输出数据。每个I/O端口都可以被配置为不同的模式,如输入、输出、中断或模拟输入/输出。
I/O端口的配置通过GPIO(通用输入输出)寄存器进行,包括模式寄存器(MODER)、输出数据寄存器(ODR)和输入数据寄存器(IDR)。模式寄存器决定了端口的输入或输出模式,而ODR和IDR分别用于设置和读取端口的逻辑电平。
# 2. STM32 I_O端口配置**
STM32 I_O端口配置是控制和管理单片机输入输出操作的关键。本章将深入探讨GPIO模式和配置寄存器、GPIO中断和事件以及GPIO高级特性,为开发者提供全面了解STM32 I_O端口配置的权威指南。
## 2.1 GPIO模式和配置寄存器
### GPIO模式
GPIO模式定义了I_O端口的电气特性和功能。STM32单片机支持多种GPIO模式,包括:
- **输入模式(Input mode):**将I_O端口配置为输入,接收外部信号。
- **输出模式(Output mode):**将I_O端口配置为输出,驱动外部设备。
- **推挽输出模式(Push-pull output mode):**在输出高电平时提供拉电流,在输出低电平时提供下拉电流。
- **开漏输出模式(Open-drain output mode):**仅提供下拉电流,需要外部上拉电阻才能输出高电平。
- **模拟输入模式(Analog input mode):**将I_O端口配置为模拟输入,用于测量外部模拟信号。
### 配置寄存器
GPIO配置寄存器用于控制和配置GPIO端口。STM32单片机中,每个GPIO端口都有以下配置寄存器:
- **GPIO模式寄存器(GPIOx_MODER):**设置GPIO模式。
- **GPIO输出数据寄存器(GPIOx_ODR):**设置GPIO输出数据。
- **GPIO输入数据寄存器(GPIOx_IDR):**读取GPIO输入数据。
- **GPIO中断屏蔽寄存器(GPIOx_IMR):**使能或禁止GPIO中断。
- **GPIO上升沿中断屏蔽寄存器(GPIOx_IER):**使能或禁止GPIO上升沿中断。
- **GPIO下降沿中断屏蔽寄存器(GPIOx_DER):**使能或禁止GPIO下降沿中断。
## 2.2 GPIO中断和事件
### GPIO中断
GPIO中断允许当GPIO端口发生特定事件(例如,输入信号变化)时触发中断服务程序。STM32单片机支持以下GPIO中断:
- **上升沿中断:**当GPIO输入端口从低电平变为高电平时触发。
- **下降沿中断:**当GPIO输入端口从高电平变为低电平时触发。
- **电平中断:**当GPIO输入端口保持特定电平(高电平或低电平)时触发。
### GPIO事件
GPIO事件与中断类似,但不会触发中断服务程序。相反,它们会触发DMA传输或其他事件。STM32单片机支持以下GPIO事件:
- **上升沿事件:**当GPIO输入端口从低电平变为高电平时触发。
- **下降沿事件:**当GPIO输入端口从高电平变为低电平时触发。
- **电平事件:**当GPIO输入端口保持特定电平(高电平或低电平)时触发。
## 2.3 GPIO高级特性
### 复用功能
GPIO端口可以复用为其他功能,例如:
- **定时器输入/输出:**用于连接到定时器外设。
- **ADC输入:**用于连接到ADC外设。
- **DAC输出:**用于连接到DAC外设。
### 上拉/下拉电阻
GPIO端口可以配置为具有上拉或下拉电阻,以提供默认电平或防止浮空状态。
### 滤波器
GPIO端口可以配置为具有滤波器,以消除输入信号中的噪声。
### 举例:配置GPIO端口为输出模式
```c
// 配置GPIO端口A的第5位为输出模式
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; // 使能GPIOA时钟
GPIOA->MODER &= ~GPIO_MODER_MODE5; // 清除MODER5位
GPIOA->MODER |= GPIO_MODER_MODE5_0; // 设置MODER5位为0,配置为输出模式
```
**代码逻辑分析:**
1. 使能GPIOA时钟,确保GPIOA外设已供电。
2. 清除GPIOA->MODER寄存器的MODE5位,将MODE5位复位为0。
3. 设置GPIOA->MODER寄存器的MODE5位为0,配置GPIOA的第5位为输出模式。
### 举例:配置GPIO端口中断
```c
// 配置GPIO端口A的第5位为上升沿中断
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; // 使能GPIOA时钟
GPIOA->MODER &= ~GPIO_MODER_MODE5; // 清除MODER5位
GPIOA->MODER |= GPIO_MODER_MODE5_0; // 设置MODER5位为0,配置为输出模式
GPIOA->PUPDR |= GPIO_PUPDR_PUPD5_0; // 设置PUPDR5位为0,配置为上拉
GPIOA->IMR |= GPIO_IMR_IM5; // 使能GPIOA的第5位中断
```
**代码逻辑分析:**
1. 使能GPIOA时钟,确保GPIOA外设已供电。
2. 清除GPIOA->MODER寄存器的MODE5位,将MODE5位复位为0。
3. 设置GPIOA->MODER寄存器的MODE5位为0,配置GPIOA的第5位为输出模式。
4. 设置GPIOA->PUPDR寄存器的PUPD5位为0,配置GPIOA的第5位为上拉。
5. 设置GPIOA->IMR寄存器的IM5位为1,使能GPIOA的第5位中断。
# 3.1 GPIO输入模式
**GPIO输入模式概述**
GPIO输入模式允许外部信号通过I/O端口输入到MCU。它有以下几种类型:
- **浮空输入模式 (GPIO_MODE_INPUT)**:端口悬空,无拉/下拉电阻,输入信号由外部设备提供。
- **下拉输入模式 (GPIO_MODE_INPUT_PU)**:端口连接下拉电阻,当没有外部信号输入时,端口输出低电平。
- **上拉输入模式 (GPIO_MODE_INPUT_PD)**:端口连接上拉电阻,当没有外部信号输入时,端口输出高电平。
**配置GPIO输入模式**
要配置GPIO输入模式,需要使用以下寄存器:
```c
GPIOx_MODER (x = A, B, C, D, E, F, G, H)
```
**寄存器结构:**
| 位 | 名称 | 描述 |
|---|---|---|
| 0-1 | MODER0 | 第0引脚模式 |
| 2-3 | MODER1 | 第1引脚模式 |
| ... | ... | ... |
| 14-15 | MODER7 | 第7引脚模式 |
**配置步骤:**
1. 清除相应引脚的MODER位(置0)。
2. 设置相应引脚的MODER位为输入模式。
**代码示例:**
```c
// 配置GPIOA第0引脚为浮空输入模式
GPIOA->MODER &= ~(3 << (0 * 2));
GPIOA->MODER |= (0 << (0 * 2));
// 配置GPIOB第1引脚为下拉输入模式
GPIOB->MODER &= ~(3 << (1 * 2));
GPIOB->MODER |= (1 << (1 * 2));
```
### 3.2 GPIO中断输入
**GPIO中断输入概述**
GPIO中断输入允许在外部信号发生变化时触发中断。它有以下几种触发方式:
- **上升沿触发 (GPIO_EXTI_TRIGGER_RISING)**:当输入信号从低电平变为高电平时触发中断。
- **下降沿触发 (GPIO_EXTI_TRIGGER_FALLING)**:当输入信号从高电平变为低电平时触发中断。
- **双边沿触发 (GPIO_EXTI_TRIGGER_RISING_FALLING)**:当输入信号发生任何变化时触发中断。
**配置GPIO中断输入**
要配置GPIO中断输入,需要使用以下寄存器:
- **EXTIx_IMR (x = 0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15)**:中断屏蔽寄存器,设置位为1表示使能中断。
- **EXTIx_RTSR (x = 0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15)**:上升沿触发寄存器,设置位为1表示使能上升沿触发。
- **EXTIx_FTSR (x = 0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15)**:下降沿触发寄存器,设置位为1表示使能下降沿触发。
**配置步骤:**
1. 使能中断:设置EXTIx_IMR相应位为1。
2. 选择触发方式:设置EXTIx_RTSR或EXTIx_FTSR相应位为1。
**代码示例:**
```c
// 配置GPIOA第0引脚为上升沿触发中断
EXTI0->IMR |= (1 << 0);
EXTI0->RTSR |= (1 << 0);
// 配置GPIOB第1引脚为双边沿触发中断
EXTI1->IMR |= (1 << 1);
EXTI1->RTSR |= (1 << 1);
EXTI1->FTSR |= (1 << 1);
```
### 3.3 GPIO模拟输入
**GPIO模拟输入概述**
GPIO模拟输入允许将外部模拟信号转换为数字信号。它有以下特点:
- **12位分辨率**:ADC转换结果为12位数据。
- **可编程采样时间**:采样时间可从2.5μs到239.5μs进行配置。
- **多通道**:每个STM32 MCU都有多个ADC通道,允许同时转换多个模拟信号。
**配置GPIO模拟输入**
要配置GPIO模拟输入,需要使用以下寄存器:
- **ADCx_CR1 (x = 1, 2, 3)**:ADC控制寄存器1,用于配置采样时间和转换模式。
- **ADCx_CR2 (x = 1, 2, 3)**:ADC控制寄存器2,用于配置通道选择和触发源。
- **ADCx_SQR1 (x = 1, 2, 3)**:ADC序列寄存器1,用于配置转换顺序。
- **ADCx_DR (x = 1, 2, 3)**:ADC数据寄存器,用于存储转换结果。
**配置步骤:**
1. 使能ADC:设置ADCx_CR2的ADON位为1。
2. 配置采样时间:设置ADCx_CR1的TSV01位和TSV00位。
3. 选择通道:设置ADCx_SQR1的SQ1位和SQ0位。
4. 启动转换:设置ADCx_CR2的SWSTART位为1。
**代码示例:**
```c
// 配置GPIOA第0引脚为模拟输入
ADC1->CR2 |= (1 << 0); // 使能ADC1
ADC1->CR1 &= ~(7 << 16); // 设置采样时间为2.5μs
ADC1->CR1 |= (0 << 16);
ADC1->SQR1 &= ~(0x1F << 6); // 选择GPIOA第0引脚作为通道1
ADC1->SQR1 |= (0 << 6);
ADC1->CR2 |= (1 << 30); // 启动转换
```
# 4. STM32 I_O端口输出操作
STM32 I/O端口输出操作是通过配置GPIO端口为输出模式并设置输出电平来实现的。本章节将详细介绍GPIO输出模式、中断输出和模拟输出。
### 4.1 GPIO输出模式
GPIO输出模式允许STM32 I/O端口驱动外部设备或电路。有两种主要的GPIO输出模式:推挽输出和开漏输出。
**推挽输出**
推挽输出模式下,GPIO端口可以输出高电平(VCC)或低电平(GND)。当GPIO端口配置为推挽输出时,它内部集成了一个推挽式驱动器,该驱动器可以将输出电平切换到高电平或低电平。
**代码块:**
```c
/* 配置GPIOA引脚0为推挽输出 */
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
GPIOA->MODER &= ~GPIO_MODER_MODE0;
GPIOA->MODER |= GPIO_MODER_MODE0_0;
```
**逻辑分析:**
* RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN:使能GPIOA时钟。
* GPIOA->MODER &= ~GPIO_MODER_MODE0:清除GPIOA引脚0的模式位。
* GPIOA->MODER |= GPIO_MODER_MODE0_0:将GPIOA引脚0配置为推挽输出模式。
**开漏输出**
开漏输出模式下,GPIO端口只能输出低电平(GND)。当GPIO端口配置为开漏输出时,它内部集成了一个开漏式驱动器,该驱动器可以将输出电平切换到低电平,但不能切换到高电平。要输出高电平,需要外部上拉电阻将输出电平拉高到VCC。
**代码块:**
```c
/* 配置GPIOA引脚1为开漏输出 */
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
GPIOA->MODER &= ~GPIO_MODER_MODE1;
GPIOA->MODER |= GPIO_MODER_MODE1_0;
```
**逻辑分析:**
* RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN:使能GPIOA时钟。
* GPIOA->MODER &= ~GPIO_MODER_MODE1:清除GPIOA引脚1的模式位。
* GPIOA->MODER |= GPIO_MODER_MODE1_0:将GPIOA引脚1配置为开漏输出模式。
### 4.2 GPIO中断输出
GPIO中断输出允许STM32 I/O端口在输出电平发生变化时触发中断。有两种类型的GPIO中断输出:下降沿中断和上升沿中断。
**下降沿中断**
下降沿中断在GPIO端口输出电平从高电平切换到低电平时触发。要使能下降沿中断,需要配置GPIO端口的中断控制寄存器(EXTI)。
**代码块:**
```c
/* 配置GPIOA引脚2为下降沿中断 */
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
GPIOA->MODER &= ~GPIO_MODER_MODE2;
GPIOA->MODER |= GPIO_MODER_MODE2_0;
EXTI->IMR |= EXTI_IMR_MR2;
EXTI->RTSR |= EXTI_RTSR_TR2;
```
**逻辑分析:**
* RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN:使能GPIOA时钟。
* GPIOA->MODER &= ~GPIO_MODER_MODE2:清除GPIOA引脚2的模式位。
* GPIOA->MODER |= GPIO_MODER_MODE2_0:将GPIOA引脚2配置为输出模式。
* EXTI->IMR |= EXTI_IMR_MR2:使能GPIOA引脚2的中断。
* EXTI->RTSR |= EXTI_RTSR_TR2:配置GPIOA引脚2为下降沿触发。
**上升沿中断**
上升沿中断在GPIO端口输出电平从低电平切换到高电平时触发。要使能上升沿中断,需要配置GPIO端口的中断控制寄存器(EXTI)。
**代码块:**
```c
/* 配置GPIOA引脚3为上升沿中断 */
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
GPIOA->MODER &= ~GPIO_MODER_MODE3;
GPIOA->MODER |= GPIO_MODER_MODE3_0;
EXTI->IMR |= EXTI_IMR_MR3;
EXTI->FTSR |= EXTI_FTSR_TR3;
```
**逻辑分析:**
* RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN:使能GPIOA时钟。
* GPIOA->MODER &= ~GPIO_MODER_MODE3:清除GPIOA引脚3的模式位。
* GPIOA->MODER |= GPIO_MODER_MODE3_0:将GPIOA引脚3配置为输出模式。
* EXTI->IMR |= EXTI_IMR_MR3:使能GPIOA引脚3的中断。
* EXTI->FTSR |= EXTI_FTSR_TR3:配置GPIOA引脚3为上升沿触发。
### 4.3 GPIO模拟输出
GPIO模拟输出允许STM32 I/O端口输出模拟电压。有两种类型的GPIO模拟输出:DAC输出和PWM输出。
**DAC输出**
DAC(数字模拟转换器)输出允许STM32 I/O端口输出模拟电压,该电压由数字值控制。DAC输出可以通过软件配置,以输出不同范围的模拟电压。
**代码块:**
```c
/* 配置GPIOA引脚4为DAC输出 */
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
GPIOA->MODER &= ~GPIO_MODER_MODE4;
GPIOA->MODER |= GPIO_MODER_MODE4_0;
DAC->CR |= DAC_CR_EN1;
DAC->DHR12R1 = 0x0FFF;
```
**逻辑分析:**
* RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN:使能GPIOA时钟。
* GPIOA->MODER &= ~GPIO_MODER_MODE4:清除GPIOA引脚4的模式位。
* GPIOA->MODER |= GPIO_MODER_MODE4_0:将GPIOA引脚4配置为模拟输出模式。
* DAC->CR |= DAC_CR_EN1:使能DAC1。
* DAC->DHR12R1 = 0x0FFF:将DAC1输出电压设置为最大值。
**PWM输出**
PWM(脉宽调制)输出允许STM32 I/O端口输出模拟电压,该电压由脉冲宽度调制。PWM输出可以通过软件配置,以输出不同频率和占空比的模拟电压。
**代码块:**
```c
/* 配置GPIOA引脚5为PWM输出 */
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
GPIOA->MODER &= ~GPIO_MODER_MODE5;
GPIOA->MODER |= GPIO_MODER_MODE5_1;
TIM2->CR1 |= TIM_CR1_CEN;
TIM2->CCR1 = 0x0FFF;
TIM2->ARR = 0x3FFF;
```
**逻辑分析:**
* RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN:使能GPIOA时钟。
* GPIOA->MODER &= ~GPIO_MODER_MODE5:清除GPIOA引脚5的模式位。
* GPIOA->MODER |= GPIO_MODER_MODE5_1:将GPIOA引脚5配置为交替功能模式。
* TIM2->CR1 |= TIM_CR1_CEN:使能定时器2。
* TIM2->CCR1 = 0x0FFF:设置定时器2通道1的比较值。
* TIM2->ARR = 0x3FFF:设置定时器2的自动重装载值。
# 5.1 LED控制
LED(发光二极管)是一种广泛使用的半导体器件,常用于指示灯、显示屏和照明等应用。STM32单片机具有丰富的GPIO功能,可以轻松控制LED。
### 配置GPIO引脚
要使用GPIO引脚控制LED,首先需要配置引脚为输出模式。可以使用以下代码:
```c
// 将GPIOA的第5个引脚配置为输出模式
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = GPIO_PIN_5;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
```
### 控制LED
配置好GPIO引脚后,就可以使用HAL库函数控制LED。以下代码将LED点亮:
```c
// 点亮LED
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
```
### 熄灭LED
要熄灭LED,可以使用以下代码:
```c
// 熄灭LED
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
```
### 闪烁LED
通过交替点亮和熄灭LED,可以实现闪烁效果。以下代码每500ms闪烁一次LED:
```c
while (1) {
// 点亮LED
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
HAL_Delay(500);
// 熄灭LED
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
HAL_Delay(500);
}
```
0
0