当前位置: 首页 > article >正文

GPIO函数详解(二)

GPIO引脚操作函数

GPIO_ReadInputDataBit 

GPIO_ReadInputDataBit 是 STM32 标准库中用于读取指定 GPIO 引脚的电平状态(高电平或低电平)。该函数适用于配置为输入模式的 GPIO 引脚。

uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

参数

  1. GPIOx

    • 类型:GPIO_TypeDef*

    • 说明:GPIO 端口(如 GPIOAGPIOBGPIOC 等)。

    • 示例:GPIOA 表示 GPIO 端口 A。

  2. GPIO_Pin

    • 类型:uint16_t

    • 说明:目标引脚编号(如 GPIO_Pin_0GPIO_Pin_1 等)。

    • 示例:GPIO_Pin_5 表示 GPIO 的第 5 个引脚。


返回值

  • 类型:uint8_t

  • 说明:返回引脚的电平状态,可能为以下值之一:

    • Bit_SET:引脚为高电平(1)。

    • Bit_RESET:引脚为低电平(0)。


示例

以下代码演示如何使用 GPIO_ReadInputDataBit 读取 GPIO 引脚的状态:

#include "stm32f10x.h"

int main(void) {
    // 1. 启用 GPIOB 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    // 2. 配置 PB3 为浮空输入模式
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;  // 浮空输入
    GPIO_Init(GPIOB, &GPIO_InitStruct);

    while (1) {
        // 3. 读取 PB3 的电平状态
        uint8_t pinState = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_3);

        if (pinState == Bit_SET) {
            // PB3 为高电平
        } else {
            // PB3 为低电平
        }
    }
}

注意事项

  1. 输入模式

    该函数仅适用于配置为输入模式的 GPIO 引脚(如浮空输入、上拉输入、下拉输入)。如果引脚配置为输出模式,读取的值可能无效。
  2. 时钟使能

    在使用 GPIO 之前,必须通过 RCC_APB2PeriphClockCmd() 使能对应 GPIO 端口的时钟。示例:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  3. 浮空输入

    如果引脚配置为浮空输入模式(GPIO_Mode_IN_FLOATING),且外部没有上拉或下拉电阻,引脚电平可能不稳定。
  4. 上拉/下拉输入

    如果需要稳定的电平状态,可以将引脚配置为上拉输入(GPIO_Mode_IPU)或下拉输入(GPIO_Mode_IPD)。
  5. 返回值类型

    返回值是 uint8_t 类型,但实际值只能是 Bit_SET 或 Bit_RESET,分别表示高电平和低电平。

GPIO_ReadInputData

GPIO_ReadInputData 用于读取指定 GPIO 端口的所有引脚的电平状态(16 位值,每位对应一个引脚)。该函数适用于配置为输入模式的 GPIO 引脚。

uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);

参数

  1. GPIOx

    • 类型:GPIO_TypeDef*

    • 说明:GPIO 端口(如 GPIOAGPIOBGPIOC 等)。

    • 示例:GPIOA 表示 GPIO 端口 A。


返回值

  • 类型:uint16_t

  • 说明:返回一个 16 位的值,表示 GPIO 端口所有引脚的电平状态。

    • 每一位对应一个引脚的状态:

      • 1:对应引脚为高电平。

      • 0:对应引脚为低电平。

    • 示例:返回值 0x0005 表示引脚 0 和引脚 2 为高电平,其余引脚为低电平。(十六进制转换二进制0101)


示例

以下代码演示如何使用 GPIO_ReadInputData 读取 GPIO 端口的状态:

#include "stm32f10x.h"

int main(void) {
    // 1. 启用 GPIOB 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    // 2. 配置 PB0~PB15 为浮空输入模式
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.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 |
                               GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 |
                               GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;  // 浮空输入
    GPIO_Init(GPIOB, &GPIO_InitStruct);

    while (1) {
        // 3. 读取 GPIOB 的所有引脚状态
        uint16_t portState = GPIO_ReadInputData(GPIOB);

        // 4. 判断 PB0 和 PB1 的状态
        if (portState & GPIO_Pin_0) {
            // PB0 为高电平
        }
        if (portState & GPIO_Pin_1) {
            // PB1 为高电平
        }
    }
}

注意事项

  1. 输入模式

    • 该函数仅适用于配置为输入模式的 GPIO 引脚(如浮空输入、上拉输入、下拉输入)。

    • 如果引脚配置为输出模式,读取的值可能无效。

  2. 时钟使能

    • 在使用 GPIO 之前,必须通过 RCC_APB2PeriphClockCmd() 使能对应 GPIO 端口的时钟。

    • 示例:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

  3. 浮空输入

    • 如果引脚配置为浮空输入模式(GPIO_Mode_IN_FLOATING),且外部没有上拉或下拉电阻,引脚电平可能不稳定。

  4. 上拉/下拉输入

    • 如果需要稳定的电平状态,可以将引脚配置为上拉输入(GPIO_Mode_IPU)或下拉输入(GPIO_Mode_IPD)。

  5. 返回值解析

    • 返回值是一个 16 位的值,每位对应一个引脚的状态。可以通过位操作(如 &|)来解析具体引脚的状态。

  6. 多引脚读取

    • 该函数适合同时读取多个引脚的状态,避免多次调用 GPIO_ReadInputDataBit

GPIO_ReadOutputDataBit

GPIO_ReadOutputDataBit 用于读取指定 GPIO 引脚的输出状态(高电平或低电平)。该函数适用于配置为输出模式的 GPIO 引脚。

uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

参数

  1. GPIOx

    • 类型:GPIO_TypeDef*

    • 说明:GPIO 端口(如 GPIOAGPIOBGPIOC 等)。

    • 示例:GPIOA 表示 GPIO 端口 A。

  2. GPIO_Pin

    • 类型:uint16_t

    • 说明:目标引脚编号(如 GPIO_Pin_0GPIO_Pin_1 等)。

    • 示例:GPIO_Pin_5 表示 GPIO 的第 5 个引脚。


返回值

  • 类型:uint8_t

  • 说明:返回引脚的输出状态,可能为以下值之一:

    • Bit_SET:引脚输出高电平(1)。

    • Bit_RESET:引脚输出低电平(0)。


示例

以下代码演示如何使用 GPIO_ReadOutputDataBit 读取 GPIO 引脚的输出状态:

#include "stm32f10x.h"

int main(void) {
    // 1. 启用 GPIOA 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    // 2. 配置 PA5 为推挽输出模式
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;  // 推挽输出
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    // 3. 设置 PA5 为高电平
    GPIO_SetBits(GPIOA, GPIO_Pin_5);

    while (1) {
        // 4. 读取 PA5 的输出状态
        uint8_t pinState = GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_5);

        if (pinState == Bit_SET) {
            // PA5 输出高电平
        } else {
            // PA5 输出低电平
        }
    }
}

注意事项

  1. 输出模式

    • 该函数仅适用于配置为输出模式的 GPIO 引脚(如推挽输出、开漏输出)。

    • 如果引脚配置为输入模式,读取的值可能无效。

  2. 时钟使能

    • 在使用 GPIO 之前,必须通过 RCC_APB2PeriphClockCmd() 使能对应 GPIO 端口的时钟。

    • 示例:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

  3. 读取的是输出寄存器值

    • 该函数读取的是输出数据寄存器(ODR)的值,而不是实际引脚的电平状态。

    • 如果外部电路影响了引脚电平(如短路),读取的值可能与实际电平不一致。

  4. 开漏输出

    • 如果引脚配置为开漏输出模式(GPIO_Mode_Out_OD),且外部没有上拉电阻,读取的值可能不准确。

  5. 返回值类型

    • 返回值是 uint8_t 类型,但实际值只能是 Bit_SET 或 Bit_RESET,分别表示高电平和低电平。

GPIO_ReadOutputData

GPIO_ReadOutputData 用于读取指定 GPIO 端口的所有引脚的输出状态(16 位值,每位对应一个引脚)。该函数适用于配置为输出模式的 GPIO 引脚。

uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);

参数

  1. GPIOx

    • 类型:GPIO_TypeDef*

    • 说明:GPIO 端口(如 GPIOAGPIOBGPIOC 等)。

    • 示例:GPIOA 表示 GPIO 端口 A。


返回值

  • 类型:uint16_t

  • 说明:返回一个 16 位的值,表示 GPIO 端口所有引脚的输出状态。

    • 每一位对应一个引脚的状态:

      • 1:对应引脚输出高电平。

      • 0:对应引脚输出低电平。

    • 示例:返回值 0x0005 表示引脚 0 和引脚 2 输出高电平,其余引脚输出低电平。


示例

以下代码演示如何使用 GPIO_ReadOutputData 读取 GPIO 端口的输出状态:

#include "stm32f10x.h"

int main(void) {
    // 1. 启用 GPIOB 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    // 2. 配置 PB0~PB15 为推挽输出模式
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.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 |
                               GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 |
                               GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;  // 推挽输出
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStruct);

    // 3. 设置 PB0 和 PB1 为高电平
    GPIO_SetBits(GPIOB, GPIO_Pin_0 | GPIO_Pin_1);

    while (1) {
        // 4. 读取 GPIOB 的所有引脚输出状态
        uint16_t portState = GPIO_ReadOutputData(GPIOB);

        // 5. 判断 PB0 和 PB1 的状态
        if (portState & GPIO_Pin_0) {
            // PB0 输出高电平
        }
        if (portState & GPIO_Pin_1) {
            // PB1 输出高电平
        }
    }
}

注意事项

  1. 输出模式

    • 该函数仅适用于配置为输出模式的 GPIO 引脚(如推挽输出、开漏输出)。

    • 如果引脚配置为输入模式,读取的值可能无效。

  2. 时钟使能

    • 在使用 GPIO 之前,必须通过 RCC_APB2PeriphClockCmd() 使能对应 GPIO 端口的时钟。

    • 示例:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

  3. 读取的是输出寄存器值

    • 该函数读取的是输出数据寄存器(ODR)的值,而不是实际引脚的电平状态。

    • 如果外部电路影响了引脚电平(如短路),读取的值可能与实际电平不一致。

  4. 开漏输出

    • 如果引脚配置为开漏输出模式(GPIO_Mode_Out_OD),且外部没有上拉电阻,读取的值可能不准确。

  5. 返回值解析

    • 返回值是一个 16 位的值,每位对应一个引脚的状态。可以通过位操作(如 &|)来解析具体引脚的状态。

  6. 多引脚读取

    • 该函数适合同时读取多个引脚的输出状态,避免多次调用 GPIO_ReadOutputDataBit

GPIO_PinLockConfig

GPIO_PinLockConfig 用于锁定指定 GPIO 引脚的配置。锁定后,GPIO 引脚的工作模式、速度等参数将无法被修改,直到下次复位。

void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

参数

  1. GPIOx

    • 类型:GPIO_TypeDef*

    • 说明:GPIO 端口(如 GPIOAGPIOBGPIOC 等)。

    • 示例:GPIOA 表示 GPIO 端口 A。

  2. GPIO_Pin

    • 类型:uint16_t

    • 说明:目标引脚编号(如 GPIO_Pin_0GPIO_Pin_1 等,或组合 GPIO_Pin_0 | GPIO_Pin_1)。

    • 示例:GPIO_Pin_5 表示 GPIO 的第 5 个引脚。


示例

以下代码演示如何使用 GPIO_PinLockConfig 锁定 GPIO 引脚的配置:

#include "stm32f10x.h"

int main(void) {
    // 1. 启用 GPIOA 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    // 2. 配置 PA5 为推挽输出模式
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;  // 推挽输出
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    // 3. 锁定 PA5 的配置
    GPIO_PinLockConfig(GPIOA, GPIO_Pin_5);

    // 4. 尝试修改 PA5 的配置(此操作无效,因为配置已锁定)
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;  // 尝试修改为浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    while (1) {
        // 主循环
    }
}

注意事项

  1. 锁定机制

    • 锁定后,GPIO 引脚的工作模式、速度等配置将无法被修改,直到下次复位。

    • 锁定是通过设置 GPIO 端口配置锁定寄存器(LCKR)实现的。

  2. 锁定范围

    • 可以锁定单个引脚或多个引脚的配置。

    • 示例:GPIO_PinLockConfig(GPIOA, GPIO_Pin_5 | GPIO_Pin_6); 锁定 PA5 和 PA6 的配置。

  3. 锁定生效条件

    • 锁定操作需要按照特定顺序写入 LCKR 寄存器:

      1. 写入 LCKR[16] = 1(锁定键)。

      2. 写入 LCKR[16] = 0

      3. 写入 LCKR[16] = 1

      4. 读取 LCKR[16] 确认锁定成功。

    • 标准库的 GPIO_PinLockConfig 函数已经实现了这一流程。

  4. 复位后解锁

    • 锁定状态在复位后会被清除,GPIO 引脚的配置可以重新修改。

  5. 适用场景

    • 锁定功能适用于需要防止程序意外修改 GPIO 配置的场景,例如在多任务环境中保护关键引脚的配置。


http://www.kler.cn/a/541639.html

相关文章:

  • 代码随想录day11
  • Linux服务管理操作命令-systemctl命令
  • 普通用户授权docker使用权限
  • 【论文笔记】Are Self-Attentions Effective for Time Series Forecasting? (NeurIPS 2024)
  • 81页精品PPT | 华为流程与信息化实践与架构规划分享
  • 数组与指针1
  • pytest测试专题 - 1.2 如何获得美观的测试报告
  • 【Vue中BUG解决】npm error path git
  • ThreadLocal 原理?需要注意什么?
  • 自动控制视频讲解
  • CCFCSP备考第二天
  • 2.协同过滤算法
  • 第四期书生大模型实战营-第4关-L2G4000
  • 【RabbitMQ的监听器容器Simple和Direct】 实现和场景区别
  • 计算机视觉的研究方向、发展历程、发展前景介绍
  • Java网络编程学习(一)
  • 【leetcode 28】27.移除元素==双指针==
  • 【系统架构设计师】面向架构评估的质量属性
  • malloc底层原理 brk,sbrk,mmap
  • Spark 源码 | 脚本分析总结
  • 【Qt之·类QTextCursor】
  • 深入浅出:图解Vue 3生命周期的全流程
  • 红外皮秒激光器:开启超快激光技术新时代
  • 算法03-基数排序
  • 【AI知识点】苦涩的教训 The Bitter Lesson by Rich Sutton(2019)
  • Vite打包路径base配置项设置