【STM32单片机管脚大全】:一文掌握STM32管脚功能、配置、中断、模拟等核心知识
发布时间: 2024-07-03 04:46:48 阅读量: 121 订阅数: 39
![【STM32单片机管脚大全】:一文掌握STM32管脚功能、配置、中断、模拟等核心知识](https://img-blog.csdnimg.cn/99a7843e6028468c9ed2fcc6263c707c.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA77ys77yq77y4,size_20,color_FFFFFF,t_70,g_se,x_16)
# 1. STM32单片机管脚概述
STM32单片机管脚是连接外部器件和内部模块的接口,其功能丰富,可用于实现各种应用。STM32管脚具有以下特点:
- **多功能性:**每个管脚可以配置为不同的功能,例如GPIO、定时器、通信等。
- **可配置性:**管脚的模式、输出类型、中断触发方式等参数都可以通过寄存器配置。
- **可复用性:**某些管脚可以复用,同时连接多个外设,提高资源利用率。
# 2. STM32管脚功能配置
STM32管脚功能配置是指将STM32单片机的管脚配置为不同的功能,以实现不同的功能。STM32管脚的功能配置主要包括GPIO管脚功能配置、定时器管脚功能配置和通信管脚功能配置。
### 2.1 GPIO管脚功能配置
GPIO管脚是通用输入输出管脚,可以配置为不同的功能,如输入、输出、中断等。GPIO管脚功能配置主要包括GPIO管脚模式选择和GPIO管脚输出类型选择。
#### 2.1.1 GPIO管脚模式选择
GPIO管脚模式选择是指将GPIO管脚配置为不同的模式,如输入模式、输出模式、模拟输入模式等。不同的模式对应不同的功能。
| 模式 | 功能 |
|---|---|
| 输入模式 | GPIO管脚作为输入管脚,可以读取外部信号 |
| 输出模式 | GPIO管脚作为输出管脚,可以输出信号 |
| 模拟输入模式 | GPIO管脚作为模拟输入管脚,可以读取模拟信号 |
GPIO管脚模式选择可以通过寄存器配置来实现。以下代码展示了如何将GPIOA的第0个管脚配置为输入模式:
```c
// 1. 启用GPIOA时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
// 2. 设置GPIOA第0个管脚为输入模式
GPIOA->MODER &= ~(3 << (0 * 2));
```
#### 2.1.2 GPIO管脚输出类型选择
GPIO管脚输出类型选择是指将GPIO管脚配置为不同的输出类型,如推挽输出、开漏输出等。不同的输出类型对应不同的驱动能力。
| 输出类型 | 功能 |
|---|---|
| 推挽输出 | GPIO管脚可以输出高电平或低电平 |
| 开漏输出 | GPIO管脚只能输出低电平,需要外接上拉电阻才能输出高电平 |
GPIO管脚输出类型选择可以通过寄存器配置来实现。以下代码展示了如何将GPIOA的第0个管脚配置为推挽输出:
```c
// 1. 启用GPIOA时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
// 2. 设置GPIOA第0个管脚为推挽输出
GPIOA->OTYPER &= ~(1 << 0);
```
### 2.2 定时器管脚功能配置
定时器管脚可以配置为不同的功能,如输入捕捉功能、输出比较功能等。不同的功能对应不同的定时器操作。
#### 2.2.1 定时器输入捕捉功能配置
定时器输入捕捉功能是指将定时器管脚配置为输入捕捉功能,可以捕捉外部信号的上升沿或下降沿。
定时器输入捕捉功能配置可以通过寄存器配置来实现。以下代码展示了如何将TIM2的通道1配置为输入捕捉功能:
```c
// 1. 启用TIM2时钟
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
// 2. 设置TIM2通道1为输入捕捉模式
TIM2->CCMR1 &= ~(3 << (0 * 2));
TIM2->CCMR1 |= (1 << (0 * 2));
// 3. 设置TIM2通道1输入捕捉极性
TIM2->CCER &= ~(1 << 0);
```
#### 2.2.2 定时器输出比较功能配置
定时器输出比较功能是指将定时器管脚配置为输出比较功能,可以输出一个与定时器计数器值比较的结果。
定时器输出比较功能配置可以通过寄存器配置来实现。以下代码展示了如何将TIM2的通道1配置为输出比较功能:
```c
// 1. 启用TIM2时钟
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
// 2. 设置TIM2通道1为输出比较模式
TIM2->CCMR1 &= ~(3 << (0 * 2));
TIM2->CCMR1 |= (2 << (0 * 2));
// 3. 设置TIM2通道1输出比较极性
TIM2->CCER &= ~(1 << 0);
```
### 2.3 通信管脚功能配置
通信管脚可以配置为不同的通信功能,如UART功能、SPI功能等。不同的通信功能对应不同的通信协议。
#### 2.3.1 UART管脚功能配置
UART管脚可以配置为UART功能,实现串口通信。
UART管脚功能配置可以通过寄存器配置来实现。以下代码展示了如何将USART1的TX管脚和RX管脚配置为UART功能:
```c
// 1. 启用USART1时钟
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
// 2. 设置USART1的TX管脚和RX管脚为UART功能
GPIOA->AFR[1] &= ~(0xF << (4 * 0));
GPIOA->AFR[1] |= (1 << (4 * 0));
GPIOA->AFR[1] &= ~(0xF << (4 * 1));
GPIOA->AFR[1] |= (1 << (4 * 1));
```
#### 2.3.2 SPI管脚功能配置
SPI管脚可以配置为SPI功能,实现串行通信。
SPI管脚功能配置可以通过寄存器配置来实现。以下代码展示了如何将SPI1的SCK管脚、MOSI管脚和MISO管脚配置为SPI功能:
```c
// 1. 启用SPI1时钟
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
// 2. 设置SPI1的SCK管脚、MOSI管脚和MISO管脚为SPI功能
GPIOA->AFR[0] &= ~(0xF << (4 * 5));
GPIOA->AFR[0] |= (5 << (4 * 5));
GPIOA->AFR[0] &= ~(0xF << (4 * 6));
GPIOA->AFR[0] |= (5 << (4 * 6));
GPIOA->AFR[0] &= ~(0xF << (4 * 7));
GPIOA->AFR[0] |= (5 << (4 * 7));
```
# 3. STM32管脚中断配置
中断是一种硬件机制,允许外部事件或设备请求CPU的关注,从而暂停当前正在执行的任务并处理中断请求。STM32微控制器提供了广泛的中断功能,包括管脚中断。管脚中断允许外部事件或设备通过特定管脚触发中断请求,从而提高系统的响应能力和实时性。
### 3.1 GPIO管脚中断配置
GPIO(通用输入/输出)管脚中断是STM32微控制器中最常用的中断类型之一。GPIO管脚中断允许外部事件或设备通过连接到GPIO管脚的信号触发中断请求。
#### 3.1.1 GPIO管脚中断触发方式选择
GPIO管脚中断可以配置为以下四种触发方式:
- **上升沿触发:**当GPIO管脚电平从低电平变为高电平时触发中断。
- **下降沿触发:**当GPIO管脚电平从高电平变为低电平时触发中断。
- **电平触发:**当GPIO管脚电平保持高电平或低电平时触发中断。
- **任意沿触发:**当GPIO管脚电平发生任何变化时触发中断。
触发方式的选择取决于外部事件或设备的信号特性。例如,如果外部事件或设备产生上升沿或下降沿信号,则应选择相应的触发方式。
#### 3.1.2 GPIO管脚中断优先级配置
STM32微控制器支持多级中断优先级。中断优先级决定了当多个中断同时发生时,哪个中断请求将被优先处理。GPIO管脚中断可以配置为以下四种优先级:
- **最高优先级:**中断请求将被立即处理,优先于所有其他中断请求。
- **高优先级:**中断请求将被优先于低优先级中断请求处理。
- **中优先级:**中断请求将被优先于低优先级中断请求处理,但低于高优先级中断请求。
- **低优先级:**中断请求将被最后处理,低于所有其他中断请求。
优先级的选择取决于外部事件或设备的实时性要求。例如,如果外部事件或设备需要立即处理,则应选择最高优先级。
### 3.2 定时器管脚中断配置
定时器管脚中断允许外部事件或设备通过连接到定时器管脚的信号触发中断请求。定时器管脚中断可以用于实现定时器相关的功能,例如输入捕捉、输出比较和脉冲宽度调制(PWM)。
#### 3.2.1 定时器输入捕捉中断配置
定时器输入捕捉中断允许外部事件或设备通过连接到定时器输入捕捉管脚的信号触发中断请求。当外部信号发生变化时,定时器将捕获当前计时器值并触发中断请求。
#### 3.2.2 定时器输出比较中断配置
定时器输出比较中断允许外部事件或设备通过连接到定时器输出比较管脚的信号触发中断请求。当定时器计数器值与输出比较寄存器值匹配时,定时器将触发中断请求。
# 4. STM32管脚模拟功能配置
### 4.1 ADC管脚配置
ADC(模数转换器)是将模拟信号转换为数字信号的器件。STM32单片机内置了多个ADC模块,可以对外部模拟信号进行采样和转换。
#### 4.1.1 ADC通道选择
ADC模块有多个通道,每个通道对应一个模拟输入引脚。通过配置ADC通道选择寄存器(ADCx_CHSELR),可以选择要采样的模拟输入通道。
```c
// 选择ADC1通道1
ADC1->CHSELR |= ADC_CHSELR_CHSEL1;
```
#### 4.1.2 ADC采样率配置
ADC采样率是指ADC每秒钟采样模拟信号的次数。通过配置ADC采样率寄存器(ADCx_SMPR),可以设置ADC的采样率。
```c
// 设置ADC1采样率为100Hz
ADC1->SMPR |= ADC_SMPR_SMP_1;
```
### 4.2 DAC管脚配置
DAC(数模转换器)是将数字信号转换为模拟信号的器件。STM32单片机内置了多个DAC模块,可以输出模拟电压或电流。
#### 4.2.1 DAC输出电压设置
通过配置DAC输出数据寄存器(DACx_DHR),可以设置DAC输出的电压值。
```c
// 设置DAC1输出电压为1.5V
DAC1->DHR = 0x7FFF;
```
#### 4.2.2 DAC输出波形选择
DAC模块可以输出多种波形,包括正弦波、三角波和方波。通过配置DAC波形生成寄存器(DACx_CR),可以选择DAC输出的波形。
```c
// 设置DAC1输出波形为正弦波
DAC1->CR |= DAC_CR_WAVE1_1;
```
# 5. STM32管脚应用实例
### 5.1 GPIO管脚控制LED灯
**目的:**利用GPIO管脚控制LED灯的亮灭。
**步骤:**
1. **硬件连接:**将LED灯的正极连接到STM32单片机的GPIO管脚,负极连接到地线。
2. **代码实现:**
```c
// 包含头文件
#include "stm32f10x.h"
// 定义GPIO管脚
#define LED_PIN GPIO_Pin_13
// 初始化GPIO管脚
void GPIO_Init(void)
{
// 使能GPIOC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
// 配置GPIOC13为输出模式
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = LED_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
// 控制LED灯亮灭
void LED_Control(uint8_t state)
{
if (state == 1)
{
// LED灯亮
GPIO_SetBits(GPIOC, LED_PIN);
}
else
{
// LED灯灭
GPIO_ResetBits(GPIOC, LED_PIN);
}
}
// 主函数
int main(void)
{
// 初始化系统
SystemInit();
// 初始化GPIO管脚
GPIO_Init();
// 循环控制LED灯亮灭
while (1)
{
// LED灯亮
LED_Control(1);
// 延时
Delay(500);
// LED灯灭
LED_Control(0);
// 延时
Delay(500);
}
}
```
**代码逻辑分析:**
* 初始化GPIOC时钟,并配置GPIOC13为输出模式。
* 在主函数中,循环控制LED灯亮灭,每隔500ms切换一次状态。
### 5.2 定时器管脚产生PWM波
**目的:**利用定时器管脚产生PWM波,控制电机转速。
**步骤:**
1. **硬件连接:**将电机的正极连接到STM32单片机的定时器管脚,负极连接到地线。
2. **代码实现:**
```c
// 包含头文件
#include "stm32f10x.h"
// 定义定时器管脚
#define PWM_PIN GPIO_Pin_8
// 初始化定时器管脚
void TIM_Init(void)
{
// 使能TIM3时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
// 配置TIM3为PWM模式
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 999;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// 配置TIM3的PWM输出
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
// 使能TIM3
TIM_Cmd(TIM3, ENABLE);
}
// 设置PWM占空比
void PWM_SetDuty(uint16_t duty)
{
TIM_SetCompare1(TIM3, duty);
}
// 主函数
int main(void)
{
// 初始化系统
SystemInit();
// 初始化定时器管脚
TIM_Init();
// 循环设置PWM占空比
while (1)
{
// 设置PWM占空比为50%
PWM_SetDuty(500);
// 延时
Delay(500);
// 设置PWM占空比为25%
PWM_SetDuty(250);
// 延时
Delay(500);
}
}
```
**代码逻辑分析:**
* 初始化TIM3时钟,并配置TIM3为PWM模式。
* 配置TIM3的PWM输出,设置PWM占空比为0。
* 在主函数中,循环设置PWM占空比为50%和25%,每隔500ms切换一次。
### 5.3 UART管脚实现串口通信
**目的:**利用UART管脚实现串口通信,与PC机进行数据交换。
**步骤:**
1. **硬件连接:**将串口线连接到STM32单片机的UART管脚和PC机的串口。
2. **代码实现:**
```c
// 包含头文件
#include "stm32f10x.h"
// 定义UART管脚
#define TX_PIN GPIO_Pin_9
#define RX_PIN GPIO_Pin_10
// 初始化UART管脚
void UART_Init(void)
{
// 使能UART1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// 配置UART1管脚
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = TX_PIN | RX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置UART1
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
// 使能UART1
USART_Cmd(USART1, ENABLE);
}
// 发送数据
void UART_SendData(uint8_t data)
{
// 等待发送缓冲区为空
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
// 发送数据
USART_SendData(USART1, data);
}
// 接收数据
uint8_t UART_ReceiveData(void)
{
// 等待接收缓冲区不为空
while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
// 接收数据
return USART_ReceiveData(USART1);
}
// 主函数
int main(void)
{
// 初始化系统
SystemInit();
// 初始化UART管脚
UART_Init();
// 循环发送和接收数据
while (1)
{
// 发送数据
UART_SendData('A');
// 延时
Delay(500);
// 接收数据
uint8_t data = UART_ReceiveData();
// 显示接收到的数据
printf("Received data: %c\n", data);
}
}
```
**代码逻辑分析:**
* 初始化UART1时钟,并配置UART1管脚为复用功能。
* 配置UART1为8位数据位、1个停止位、无校验位、接收和发送使能的模式。
* 在主函数中,循环发送字符'A',并接收和显示接收到的数据。
# 6.1 管脚复用技术
### 6.1.1 管脚复用原理
STM32单片机支持管脚复用技术,即同一个物理管脚可以映射到多个功能模块。这使得单片机可以实现更多的功能,节省资源。
管脚复用通过配置管脚复用寄存器(AFIO_EXTICR)来实现。该寄存器包含4个字节,每个字节对应一个管脚组(4个管脚)。每个字节的4位对应于该管脚组的4个管脚,每位可以配置为0~15,表示该管脚映射到哪个功能模块。
### 6.1.2 管脚复用配置
管脚复用配置需要以下步骤:
1. 确定要复用的管脚。
2. 查询管脚复用寄存器AFIO_EXTICR的地址。
3. 根据管脚编号计算管脚组和管脚位。
4. 将管脚位对应的值写入AFIO_EXTICR寄存器。
**代码示例:**
```c
// 将GPIOA的第8个管脚复用为定时器2的CH1输入捕捉功能
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // 使能AFIO时钟
AFIO->EXTICR[1] |= AFIO_EXTICR1_PA8_TIM2; // 配置PA8管脚复用为TIM2_CH1
```
## 6.2 管脚保护机制
### 6.2.1 管脚保护原理
STM32单片机提供了管脚保护机制,防止管脚被意外写入或输出高电平。管脚保护通过配置管脚保护寄存器(GPIOx_ODR)来实现。
GPIOx_ODR寄存器包含16位,每位对应一个管脚。当某一位被置1时,表示该管脚被保护。
### 6.2.2 管脚保护配置
管脚保护配置需要以下步骤:
1. 确定要保护的管脚。
2. 查询管脚保护寄存器GPIOx_ODR的地址。
3. 根据管脚编号设置管脚保护位。
**代码示例:**
```c
// 将GPIOA的第8个管脚设置为输出保护
GPIOA->ODR |= GPIO_ODR_ODR8;
```
0
0