学习STM32的GPIO输入输出控制
GPIO(General Purpose Input/Output)即通用输入输出端口,是一种用于连接外部设备的通用接口,可以通过软件控制来读写外部设备的状态。在STM32系列的单片机中,GPIO是非常重要和常用的功能,可以用来连接各种模块和外设,如按键、LED灯、数码管、传感器等。
本文将详细介绍STM32的GPIO输入输出控制,并给出一些代码案例,帮助读者更好地理解和掌握相关知识。以下是本文的大纲:
-
GPIO的基本概念和功能
-
GPIO的寄存器和相关配置
-
输入模式的配置与使用
-
输出模式的配置与使用
-
中断模式的配置与使用
-
实践案例:使用GPIO控制LED灯
-
实践案例:使用GPIO读取按键状态
-
实践案例:使用GPIO控制数码管显示
-
GPIO的基本概念和功能
GPIO即通用输入输出端口,是单片机与外部设备进行数据交换的接口。它具有以下基本功能:
- 输入功能:用于读取外部设备(如按键、传感器等)的状态。
- 输出功能:用于控制外部设备(如LED灯、数码管等)的状态。
- GPIO的寄存器和相关配置
在STM32中,每个GPIO端口都与一组寄存器相关联,主要包括:
- GPIOx_MODER:GPIO端口模式寄存器,用于配置GPIO端口的工作模式。
- GPIOx_OTYPER:GPIO端口输出类型寄存器,用于配置GPIO端口的输出类型(推挽输出或开漏输出)。
- GPIOx_OSPEEDR:GPIO端口输出速度寄存器,用于配置GPIO端口的输出速度。
- GPIOx_PUPDR:GPIO端口上拉/下拉寄存器,用于配置GPIO端口的上拉/下拉电阻。
- GPIOx_IDR:GPIO端口输入数据寄存器,用于读取GPIO端口的输入状态。
- GPIOx_ODR:GPIO端口输出数据寄存器,用于设置GPIO端口的输出状态。
- 输入模式的配置与使用
GPIO的输入模式用于读取外部设备的状态,配置方式如下:
- 配置GPIO模式:通过将GPIOx_MODER寄存器对应的位设置为0b00,表示输入模式。
- 配置GPIO上拉/下拉:通过将GPIOx_PUPDR寄存器对应的位设置为0b01,表示上拉输入模式;设置为0b10,表示下拉输入模式。
- 读取GPIO输入数据:通过读取GPIOx_IDR寄存器来获取GPIO输入的状态。
下面是一个示例代码,实现了读取一个按键的状态并通过串口打印:
#include "stm32f10x.h"
int main(void)
{
// 打开GPIOA的时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
// 配置PA0为输入模式
GPIOA->CRL &= ~GPIO_CRL_CNF0; // 清零
GPIOA->CRL &= ~GPIO_CRL_MODE0; // 清零
// 配置PA0的上拉输入模式
GPIOA->CRL |= GPIO_CRL_CNF0_1;
GPIOA->CRL &= ~GPIO_CRL_CNF0_0;
GPIOA->CRL |= GPIO_CRL_MODE0_0;
// 打开串口1的时钟
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
// 配置USART1的GPIO引脚
GPIOA->CRH |= GPIO_CRH_MODE9_1 | GPIO_CRH_CNF9_1; // TX引脚
GPIOA->CRH &= ~(GPIO_CRH_CNF9_0 | GPIO_CRH_MODE9_0);
// 配置USART1的波特率
USART1->BRR = 0x1D4C; // 9600
// 打开USART1
USART1->CR1 |= USART_CR1_UE;
while (1) {
// 读取PA0的输入状态
uint8_t state = (GPIOA->IDR >> 0) & 0x01;
// 发送状态到串口
USART1->DR = state;
while (!(USART1->SR & USART_SR_TC)); // 等待发送完成
// 延时一段时间
for (int i = 0; i < 1000000; i++);
}
}
- 输出模式的配置与使用
GPIO的输出模式用于控制外部设备的状态,配置方式如下:
- 配置GPIO模式:通过将GPIOx_MODER寄存器对应的位设置为0b01,表示输出模式。
- 配置GPIO输出类型:通过将GPIOx_OTYPER寄存器对应的位设置为0b0,表示推挽输出;设置为0b1,表示开漏输出。
- 配置GPIO输出速度:通过将GPIOx_OSPEEDR寄存器对应的位设置为0b11,表示最高速度。
- 设置GPIO输出状态:通过写入GPIOx_ODR寄存器的对应位来设置GPIO的输出状态。
下面是一个示例代码,实现了通过串口指令控制一个LED的亮灭:
#include "stm32f10x.h"
void GPIO_Init(void)
{
// 打开GPIOC的时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
// 配置PC13为输出模式
GPIOC->CRH |= GPIO_CRH_MODE13; // 设置为输出模式
GPIOC->CRH &= ~GPIO_CRH_CNF13; // 设置为推挽输出
// 熄灭LED灯
GPIOC->BSRR = GPIO_BSRR_BR13; // 设置GPIOC13为低电平
}
int main(void)
{
// 初始化GPIO
GPIO_Init();
while (1) {
// 通过串口读取指令
uint8_t command = 0; // 假设读取到的指令为0
// 根据指令控制LED灯
if (command == 1) {
GPIOC->BSRR = GPIO_BSRR_BS13; // 设置GPIOC13为高电平
} else if (command == 0) {
GPIOC->BSRR = GPIO_BSRR_BR13; // 设置GPIOC13为低电平
}
}
}
- 中断模式的配置与使用
GPIO的中断模式用于在输入电平发生变化时触发中断,配置方式如下:
- 配置GPIO模式:同输入模式一样,将GPIOx_MODER寄存器对应的位设置为0b00,表示输入模式。
- 配置GPIO上拉/下拉:同输入模式一样,将GPIOx_PUPDR寄存器对应的位设置为0b01,表示上拉输入模式或下拉输入模式。
- 配置GPIO中断触发方式:通过将GPIOx_EXTICR寄存器对应的位设置为正确的值,来选择外部中断的触发引脚。
- 配置NVIC中断向量表:通过设置NVIC_ISER寄存器的相应位来使能对应的中断。
- 编写中断处理函数:通过编写中断处理函数来实现对中断事件的处理。
下面是一个示例代码,实现了通过按键触发中断,并将按键的状态通过串口打印:
#include "stm32f10x.h"
void EXTI0_IRQHandler(void)
{
// 清除中断标志位
EXTI->PR |= EXTI_PR_PR0;
// 读取PA0的输入状态
uint8_t state = (GPIOA->IDR >> 0) & 0x01;
// 发送状态到串口
USART1->DR = state;
while