GPIO函数详解(二)

embedded/2025/2/12 23:50:37/

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.ppmy.cn/embedded/161090.html

相关文章

DeepSeek与Vue.js组件开发:解锁AI与前端开发的融合密码

前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…

深度探索未来的搜索引擎 —— DeepSeek

随着信息时代的进步,我们每天都在生成、分享和消费大量的数据,如何从海量的内容中迅速找到有价值的信息,成为了现代社会的重要课题。传统的搜索引擎虽然在很长时间内引领了互联网的发展,但随着技术的进步和用户需求的变化&#xf…

【蓝桥杯嵌入式】8_IIC通信-eeprom读写

全部代码网盘自取 链接:https://pan.baidu.com/s/1PX2NCQxnADxYBQx5CsOgPA?pwd3ii2 提取码:3ii2 1、电路图 这个电路允许通过I2C总线与EEPROM(M24C02-WMN6TP)和数字电位器(MCP4017T-104ELT)进行通信。EEPROM用于存储数据,而数字电位器可以用…

软件工程-分析建模

结构化(传统/面向对象)分析模型 核心是数据字典DD 面向对象分析模型 核心是使用实例(用例) 分析模型描述工具 结构化分析工具 数据流图DFD、数据字典DD和加工说明PSPEC【功能模型】 DFD、DD具体介绍见往期文章 加工说明PS…

【kafka实战】05 Kafka消费者消费消息过程源码剖析

1. 概述 Kafka消费者(Consumer)是Kafka系统中负责从Kafka集群中拉取消息的客户端组件。消费者消费消息的过程涉及多个步骤,包括消费者组的协调、分区分配、消息拉取、消息处理等。本文将深入剖析Kafka消费者消费消息的源码,并结合…

C++使用Json保存配置参数

文章目录 1. **设计配置文件的结构**示例配置文件 `config.json`:2. **解析 JSON 配置文件**解析过程:示例:3. **修改配置**修改流程:示例:4. **保存配置文件**示例:5. **完整的操作流程**6. **示例代码分析**主要部分:7. **优势**8. **总结**使用 JSON 来管理配置文件的…

[权限提升] Linux 提权 — 系统内核溢出漏洞提权

关注这个专栏的其他相关笔记:[内网安全] 内网渗透 - 学习手册-CSDN博客 0x01:系统内核溢出漏洞提权介绍 注意:提权很容易让系统崩溃,所以如果是测试的话,提权前最好做好系统备份。 Linux 系统内核溢出提权漏洞与之前的…

【学Rust写CAD】5 三维转换矩阵解析及应用示例

三维转换矩阵是指将一个三维空间中的坐标系转换为另一个三维空间中的坐标系所需要的矩阵。在计算机图形学、计算机视觉等领域,三维转换矩阵是非常重要的基础知识。完整的三维转换矩阵为一个4x4的方阵。 [ 1 0 0 0 d x x x y x z x d y x y y y z y d z x z y z z z…