STM32学习-GPIO

1. GPIO基本概念
  • GPIO(General Purpose Input/Output):通用输入输出端口,是STM32微控制器与外部设备交互的重要接口。

  • 功能

    • 输入模式:读取外部信号(如按键、传感器)。

    • 输出模式:控制外部设备(如LED、电机)。

    • 中断模式:检测外部信号的变化(如按键按下)。

    • 复用功能模式:将GPIO引脚分配给外设(如USART、SPI)。

    • 模拟模式:将GPIO引脚用作ADC或DAC的输入/输出。


2. GPIO端口结构
  • 端口组:STM32有多个GPIO端口组(如PA、PB、PC等),每个端口组包含多个引脚(如PA0、PA1等)。

  • 引脚配置:每个GPIO引脚可以配置为不同的模式(输入、输出、中断、复用功能等)。

  • 主要寄存器

    • GPIOx_MODER(模式寄存器):配置引脚模式(输入、输出、复用、模拟)。

    • GPIOx_OTYPER(输出类型寄存器):配置输出类型(推挽或开漏)。

    • GPIOx_PUPDR(上拉/下拉寄存器):配置内部上拉/下拉电阻。

    • GPIOx_ODR(输出数据寄存器):控制引脚输出电平。

    • GPIOx_IDR(输入数据寄存器):读取引脚输入电平。


3. GPIO配置模式
3.1 输入模式
  • 浮空输入(Input Floating)

    • 特点:引脚悬空,电平不确定,适合外部已有明确电平信号的场景。

    • 应用实例:连接外部传感器(如光敏传感器)的输出信号。

  • 上拉输入(Input Pull-up)

    • 特点:内部上拉电阻将引脚默认拉高,适合需要默认高电平的场景。

    • 应用实例:按键检测,按键按下时接地,释放时通过上拉电阻保持高电平。

  • 下拉输入(Input Pull-down)

    • 特点:内部下拉电阻将引脚默认拉低,适合需要默认低电平的场景。

    • 应用实例:检测外部信号是否被拉高,例如检测外部设备的使能信号。

3.2 输出模式
  • 推挽输出(Push-Pull Output)

    • 特点:可以直接输出高电平或低电平,适合驱动负载。

    • 应用实例:控制LED的亮灭、继电器的开关。

  • 开漏输出(Open-Drain Output)

    • 特点:输出低电平时有效,高电平需要外部上拉电阻,适合多设备共享引脚。

    • 应用实例:I2C通信,多个设备共用SDA和SCL引脚。

3.3 复用功能模式
  • 复用推挽输出(Alternate Function Push-Pull)

    • 特点:引脚作为外设的推挽输出,适合高速信号传输。

    • 应用实例:SPI通信中的SCK、MOSI引脚,USART的TX引脚。

  • 复用开漏输出(Alternate Function Open-Drain)

    • 特点:引脚作为外设的开漏输出,适合需要高阻态的场景。

    • 应用实例:某些需要多设备共享的外设通信。

3.4 模拟模式
  • 特点:引脚配置为ADC输入,适合采集模拟信号。

  • 应用实例:温度传感器、光敏传感器的信号采集。


4. GPIO初始化(基于Keil)
4.1 使能GPIO端口时钟
使用RCC开启GPIO的时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 启动GPIOA时钟
4.2 配置GPIO引脚
使用GPIO_Init函数初始化

GPIO_InitTypeDef GPIO_InitStructure;

// 配置GPIOA0为推挽输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;             // 选择GPIOA的第0引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      // 推挽输出模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     // 设置速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);                // 初始化GPIOA
4.3 设置输出电平
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); // 输出高电平
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET); // 输出低电平
4.4 读取输入电平
GPIO_PinState pin_state = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
if (pin_state == Bit_SET) {
    // 引脚为高电平
} else {
    // 引脚为低电平
}

5. GPIO中断(基于Keil)
5.1 配置GPIO引脚为中断模式
GPIO_InitTypeDef GPIO_InitStructure;

// 配置GPIOA0为上拉输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);

// 配置中断线和中断请求
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line0; // 选择中断线0
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // 中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE; // 使能中断线
EXTI_Init(&EXTI_InitStructure);

// 配置NVIC
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; // 选择中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能中断通道
NVIC_Init(&NVIC_InitStructure);
5.2 编写中断服务例程(ISR)
void EXTI0_IRQHandler(void) {
    if (EXTI_GetITStatus(EXTI_Line0) != RESET) { // 检查中断标志
        // 按键按下时的操作
        EXTI_ClearITPendingBit(EXTI_Line0);      // 清除中断标志
    }
}

6. 常见问题
  1. 电平兼容性:确保外设的电平与STM32的GPIO电平匹配(如3.3V或5V)。

  2. 上拉/下拉电阻:根据实际需求选择内部或外部上拉/下拉电阻。

  3. 中断去抖动:按键等输入信号可能需要硬件或软件去抖动处理。

  4. 引脚复用冲突:某些引脚可能被多个外设共享,注意避免冲突。


7. 应用实例
功能描述

通过GPIO控制一个LED的闪烁,实现简单的定时闪烁效果。

硬件连接
  • 将一个LED的正极连接到GPIO引脚(如GPIOC的Pin5)。

  • LED的负极通过一个限流电阻连接到GND。

代码实现
#include "stm32f10x.h"

void GPIO_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); // 启用GPIOC时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;             // 选择GPIOC的Pin5
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      // 推挽输出模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     // 输出速度50MHz
    GPIO_Init(GPIOC, &GPIO_InitStructure);                // 初始化GPIOC
}

int main(void) {
    GPIO_Init(); // 初始化GPIO
    while (1) {
        GPIO_WriteBit(GPIOC, GPIO_Pin_5, Bit_SET); // 点亮LED
        for (int i = 0; i < 500000; i++);          // 延时
        GPIO_WriteBit(GPIOC, GPIO_Pin_5, Bit_RESET); // 熄灭LED
        for (int i = 0; i < 500000; i++);          // 延时
    }
}
运行效果

LED每隔一段时间闪烁一次。


应用实例 2:LED流水灯

功能描述

通过GPIO控制多个LED依次点亮和熄灭,形成流水灯效果。

硬件连接
  • 将多个LED的正极分别连接到GPIO引脚(如GPIOC的Pin0~Pin7)。

  • 每个LED的负极通过限流电阻连接到GND。

代码实现
#include "stm32f10x.h"

void GPIO_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); // 启用GPIOC时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | 
                                  GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; // 选择GPIOC的Pin0~Pin7
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      // 推挽输出模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     // 输出速度50MHz
    GPIO_Init(GPIOC, &GPIO_InitStructure);                // 初始化GPIOC
}

int main(void) {
    GPIO_Init(); // 初始化GPIO
    uint16_t led = GPIO_Pin_0; // 从第一个LED开始
    while (1) {
        GPIO_WriteBit(GPIOC, led, Bit_SET); // 点亮当前LED
        for (int i = 0; i < 500000; i++);   // 延时
        GPIO_WriteBit(GPIOC, led, Bit_RESET); // 熄灭当前LED
        led <<= 1; // 移动到下一个LED
        if (led > GPIO_Pin_7) {
            led = GPIO_Pin_0; // 从第一个LED重新开始
        }
    }
}
运行效果

LED依次从第一个点亮到第八个,然后循环。


应用实例 3:蜂鸣器控制

功能描述

通过GPIO控制蜂鸣器发出声音,实现简单的蜂鸣器控制。

硬件连接
  • 将蜂鸣器的正极连接到GPIO引脚(如GPIOA的Pin0)。

  • 蜂鸣器的负极连接到GND。

代码实现
#include "stm32f10x.h"

void GPIO_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 启用GPIOA时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;             // 选择GPIOA的Pin0
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      // 推挽输出模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     // 输出速度50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure);                // 初始化GPIOA
}

void Beep(unsigned int times) {
    for (int i = 0; i < times; i++) {
        GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); // 打开蜂鸣器
        for (int j = 0; j < 100000; j++);          // 延时
        GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET); // 关闭蜂鸣器
        for (int j = 0; j < 100000; j++);          // 延时
    }
}

int main(void) {
    GPIO_Init(); // 初始化GPIO
    while (1) {
        Beep(3); // 蜂鸣器响3次
        for (int i = 0; i < 1000000; i++); // 延时
    }
}
运行效果

蜂鸣器每隔一段时间发出3次短促的“滴”声。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值