STM32单片机GPIO编程实战:点亮LED,开启单片机之旅
发布时间: 2024-07-04 15:29:38 阅读量: 4 订阅数: 9 ![](https://csdnimg.cn/release/wenkucmsfe/public/img/col_vip.0fdee7e1.png)
![](https://csdnimg.cn/release/wenkucmsfe/public/img/col_vip.0fdee7e1.png)
![STM32单片机GPIO编程实战:点亮LED,开启单片机之旅](https://img-blog.csdnimg.cn/b317671e530d49f0b28415e923c7eb29.png)
# 1. STM32单片机GPIO基础**
GPIO(通用输入/输出)是STM32单片机中重要的外设之一,它允许与外部器件进行交互。GPIO引脚可以配置为输入或输出模式,并支持中断功能。
GPIO的配置和初始化涉及设置引脚模式、引脚配置(如推挽输出或开漏输出)以及中断配置。输入模式下,GPIO引脚可以检测外部信号,而输出模式下,GPIO引脚可以驱动外部器件。中断功能允许在GPIO引脚状态发生变化时触发中断,从而实现对外部事件的快速响应。
# 2. GPIO编程实战
### 2.1 GPIO配置和初始化
#### 2.1.1 GPIO模式设置
STM32的GPIO引脚可以配置为多种模式,包括输入、输出、推挽输出、开漏输出等。具体模式的设置可以通过寄存器进行配置。
```c
// 设置GPIOA第0引脚为输入模式
GPIOA->MODER &= ~(3 << (0 * 2));
GPIOA->MODER |= (0 << (0 * 2));
```
**代码逻辑分析:**
* `GPIOA->MODER`寄存器用于设置GPIO引脚的模式。
* `(3 << (0 * 2))`用于清除第0引脚模式位的两位,将其置为0。
* `(0 << (0 * 2))`用于将第0引脚模式位设置为0,即输入模式。
#### 2.1.2 GPIO引脚配置
除了模式设置外,GPIO引脚还可以配置其他属性,如上拉/下拉电阻、输出速度等。这些属性的配置同样可以通过寄存器进行设置。
```c
// 设置GPIOA第0引脚为上拉输入模式
GPIOA->PUPDR &= ~(3 << (0 * 2));
GPIOA->PUPDR |= (1 << (0 * 2));
```
**代码逻辑分析:**
* `GPIOA->PUPDR`寄存器用于设置GPIO引脚的上拉/下拉电阻。
* `(3 << (0 * 2))`用于清除第0引脚上拉/下拉电阻位的两位,将其置为0。
* `(1 << (0 * 2))`用于将第0引脚上拉/下拉电阻位设置为1,即上拉电阻模式。
### 2.2 GPIO输入输出操作
#### 2.2.1 GPIO输入模式
在输入模式下,GPIO引脚可以读取外部信号。读取信号可以通过寄存器进行操作。
```c
// 读取GPIOA第0引脚的输入状态
uint8_t input_state = GPIOA->IDR & (1 << 0);
```
**代码逻辑分析:**
* `GPIOA->IDR`寄存器用于读取GPIO引脚的输入状态。
* `(1 << 0)`用于获取第0引脚的输入状态位。
* `input_state`变量存储读取到的输入状态,0表示低电平,1表示高电平。
#### 2.2.2 GPIO输出模式
在输出模式下,GPIO引脚可以输出信号。输出信号可以通过寄存器进行设置。
```c
// 设置GPIOA第0引脚输出高电平
GPIOA->ODR |= (1 << 0);
```
**代码逻辑分析:**
* `GPIOA->ODR`寄存器用于设置GPIO引脚的输出状态。
* `(1 << 0)`用于获取第0引脚的输出状态位。
* `|=`运算符用于将第0引脚输出状态位设置为1,即输出高电平。
#### 2.2.3 GPIO中断配置
GPIO引脚可以配置中断功能,当引脚状态发生变化时触发中断。中断配置可以通过寄存器进行设置。
```c
// 配置GPIOA第0引脚为下降沿中断
GPIOA->EXTICR[0] |= (0 << (0 * 4));
GPIOA->RTSR |= (1 << 0);
```
**代码逻辑分析:**
* `GPIOA->EXTICR[0]`寄存器用于设置GPIO引脚的中断线。
* `(0 << (0 * 4))`用于将第0引脚的中断线设置为0,即EXTI0线。
* `GPIOA->RTSR`寄存器用于使能GPIO引脚的下降沿中断。
* `(1 << 0)`用于使能第0引脚的下降沿中断。
### 2.3 GPIO高级应用
#### 2.3.1 GPIO多路复用
GPIO引脚可以配置为多路复用功能,即同时支持多个外设功能。多路复用功能可以通过寄存器进行配置。
```c
// 配置GPIOA第0引脚为USART1_TX功能
GPIOA->AFR[0] &= ~(0xF << (0 * 4));
GPIOA->AFR[0] |= (1 << (0 * 4));
```
**代码逻辑分析:**
* `GPIOA->AFR[0]`寄存器用于设置GPIO引脚的多路复用功能。
* `(0xF << (0 * 4))`用于清除第0引脚多路复用功能位的四位,将其置为0。
* `(1 << (0 * 4))`用于将第0引脚多路复用功能位设置为1,即USART1_TX功能。
#### 2.3.2 GPIO模拟功能
GPIO引脚可以配置为模拟功能,即可以作为模拟输入或输出。模拟功能的配置可以通过寄存器进行设置。
```c
// 配置GPIOA第0引脚为模拟输入功能
GPIOA->MODER &= ~(3 << (0 * 2));
GPIOA->MODER |= (3 << (0 * 2));
```
**代码逻辑分析:**
* `GPIOA->MODER`寄存器用于设置GPIO引脚的模式。
* `(3 << (0 * 2))`用于清除第0引脚模式位的两位,将其置为0。
* `(3 << (0 * 2))`用于将第0引脚模式位设置为3,即模拟输入模式。
# 3. 点亮LED实战
### 3.1 LED硬件连接
点亮LED需要将LED与单片机的GPIO引脚连接。常见的LED连接方式有两种:
1. **共阳极连接:**将LED的正极连接到单片机的GPIO引脚,负极连接到地线。
2. **共阴极连接:**将LED的负极连接到单片机的GPIO引脚,正极连接到电源。
本实战中,我们采用共阳极连接方式。具体连接步骤如下:
1. 选择一个单片机的GPIO引脚,例如PA0。
2. 将LED的正极连接到PA0引脚。
3. 将LED的负极连接到地线(GND)。
### 3.2 GPIO配置和初始化
在点亮LED之前,需要对GPIO引脚进行配置和初始化。具体步骤如下:
```c
// 1. 启用GPIOA时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
// 2. 设置PA0引脚为输出模式
GPIOA->CRH &= ~GPIO_CRH_MODE0;
GPIOA->CRH |= GPIO_CRH_MODE0_0;
// 3. 设置PA0引脚为推挽输出
GPIOA->CRH &= ~GPIO_CRH_CNF0;
GPIOA->CRH |= GPIO_CRH_CNF0_0;
```
**参数说明:**
* `RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;`:启用GPIOA时钟。
* `GPIOA->CRH &= ~GPIO_CRH_MODE0;`:清除PA0引脚的模式位。
* `GPIOA->CRH |= GPIO_CRH_MODE0_0;`:设置PA0引脚为输出模式。
* `GPIOA->CRH &= ~GPIO_CRH_CNF0;`:清除PA0引脚的配置位。
* `GPIOA->CRH |= GPIO_CRH_CNF0_0;`:设置PA0引脚为推挽输出。
### 3.3 GPIO输出控制
配置和初始化完成后,即可通过GPIO寄存器控制LED的亮灭。具体步骤如下:
```c
// 1. 设置PA0引脚为高电平,点亮LED
GPIOA->BSRR = GPIO_BSRR_BS0;
// 2. 设置PA0引脚为低电平,熄灭LED
GPIOA->BSRR = GPIO_BSRR_BR0;
```
**参数说明:**
* `GPIOA->BSRR = GPIO_BSRR_BS0;`:设置PA0引脚为高电平。
* `GPIOA->BSRR = GPIO_BSRR_BR0;`:设置PA0引脚为低电平。
### 3.4 常见问题及解决
在点亮LED的过程中,可能会遇到一些常见问题。常见问题及解决方法如下:
* **LED不亮:**
* 检查LED硬件连接是否正确。
* 检查GPIO引脚配置是否正确。
* 检查GPIO输出控制代码是否正确。
* **LED闪烁:**
* 检查电源电压是否稳定。
* 检查GPIO引脚与LED之间是否存在电容或电感。
* **LED亮度不一致:**
* 检查LED的正负极是否连接正确。
* 检查LED的阻值是否合适。
# 4. 单片机基础应用**
**4.1 按键输入检测**
**4.1.1 按键硬件连接**
将按键的一端连接到单片机的GPIO引脚,另一端连接到地线。
**4.1.2 GPIO中断配置**
```c
// 配置GPIO引脚为输入模式
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_x;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOx, &GPIO_InitStructure);
// 配置GPIO中断
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Linex;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStructure);
// 使能GPIO中断
NVIC_EnableIRQ(EXTIx_IRQn);
```
**4.1.3 按键状态检测**
在GPIO中断服务函数中,读取GPIO引脚的状态,判断按键是否按下。
```c
void EXTIx_IRQHandler(void)
{
if (GPIO_ReadInputDataBit(GPIOx, GPIO_PIN_x) == 0)
{
// 按键按下
}
else
{
// 按键释放
}
// 清除中断标志位
EXTI_ClearITPendingBit(EXTI_Linex);
}
```
**4.2 定时器应用**
**4.2.1 定时器原理和配置**
定时器是单片机中用于产生定时脉冲或测量时间的模块。它可以用来生成周期性中断或测量时间间隔。
```c
// 配置定时器
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Prescaler = 7200 - 1; // 分频系数
TIM_TimeBaseStructure.TIM_Period = 1000 - 1; // 计数周期
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);
// 使能定时器
TIM_Cmd(TIMx, ENABLE);
```
**4.2.2 定时器中断应用**
在定时器中断服务函数中,可以执行需要定时执行的任务。
```c
void TIMx_IRQHandler(void)
{
// 执行定时任务
// 清除中断标志位
TIM_ClearITPendingBit(TIMx, TIM_IT_Update);
}
```
**4.2.3 PWM波形生成**
PWM(脉宽调制)波形是一种周期性波形,其脉冲宽度可变。它可以用来控制电机速度、亮度等。
```c
// 配置PWM输出
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 500; // 脉冲宽度
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIMx, &TIM_OCInitStructure);
// 使能PWM输出
TIM_OC1PreloadConfig(TIMx, TIM_OCPreload_Enable);
```
# 5.1 串口通信
### 5.1.1 串口硬件连接
STM32单片机上的串口通信通常使用USART(通用同步异步收发器)模块。USART模块与外部设备通过RX(接收)和TX(发送)引脚进行连接。
对于不同的STM32型号,USART模块的引脚定义可能不同。例如,STM32F103系列的USART1模块的RX引脚为PA10,TX引脚为PA9。
### 5.1.2 串口配置和初始化
在使用串口通信之前,需要对USART模块进行配置和初始化。以下是一个基本的串口配置和初始化代码示例:
```c
#include "stm32f103xb.h"
void USART1_Init(void) {
// 使能 USART1 时钟
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
// 配置 USART1 引脚
GPIOA->CRH &= ~(GPIO_CRH_MODE9 | GPIO_CRH_CNF9);
GPIOA->CRH |= GPIO_CRH_MODE9_1 | GPIO_CRH_CNF9_1;
// 配置 USART1 波特率
USART1->BRR = 0x341; // 9600 波特率
// 配置 USART1 控制寄存器
USART1->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
}
```
### 5.1.3 串口数据收发
配置和初始化串口后,就可以进行数据收发操作。
**数据发送:**
```c
void USART1_SendByte(uint8_t data) {
// 等待发送寄存器为空
while (!(USART1->SR & USART_SR_TXE));
// 将数据写入发送寄存器
USART1->DR = data;
}
```
**数据接收:**
```c
uint8_t USART1_ReceiveByte(void) {
// 等待接收寄存器非空
while (!(USART1->SR & USART_SR_RXNE));
// 读取接收寄存器中的数据
return USART1->DR;
}
```
0
0
相关推荐
![pdf](https://img-home.csdnimg.cn/images/20210720083512.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)