GPIO函数详解(二)

devtools/2025/2/12 20:13:02/

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/devtools/158304.html

相关文章

人工智能应用实例-自动驾驶

自动驾驶是一个极其复杂的系统工程,包含环境感知、决策规划、控制执行等多个环节,很难用一个完整的代码示例来呈现整个自动驾驶系统。不过,我们可以通过 Python 结合一些开源库,模拟实现自动驾驶中的部分关键逻辑,比如…

SQL Server 逻辑查询处理阶段及其处理顺序

在 SQL Server 中,查询的执行并不是按照我们编写的 SQL 语句的顺序进行的。相反,SQL Server 有自己的一套逻辑处理顺序,这个顺序决定了查询的执行方式和结果集的生成。了解这些处理阶段和顺序对于优化查询性能和调试复杂查询非常重要。 SQL …

字节跳动后端一面

📍1. Gzip压缩技术详解 Gzip是一种流行的无损数据压缩格式,它使用DEFLATE算法来减少文件大小,广泛应用于网络传输和文件存储中以提高效率。 🚀 使用场景: • 网站优化:通过压缩HTML、CSS、JavaScript文件来…

使用PyCharm进行Django项目开发环境搭建

如果在PyCharm中创建Django项目 1. 打开PyCharm,选择新建项目 2.左侧选择Django,并设置项目名称 3.查看项目解释器初始配置 4.新建应用程序 执行以下操作之一: 转到工具| 运行manage.py任务或按CtrlAltR 在打开的manage.pystartapp控制台…

【场景题】架构优化 - 解耦Redis缓存与业务逻辑

1. 需求分析 某公司需要将原有的Redis缓存抽离出来,并且还要要实现: 可配置热拔插高可用高通用 请问你会如何实现? 2. 思路 话不多说直接上思路: 自定义缓存注解,当容器扫描到该注解自动调用AOP想应的增强方法为…

electron.vite 项目创建以及better-sqlite3数据库使用

1.安装electron.vite npm create quick-start/electronlatest中文官网:https://cn.electron-vite.org/ 2. 安装项目依赖 npm i3.修改 electron-builder 配置文件 appId: com.electron.app productName: text33 directories:buildResources: build files:- !**/.v…

在ArcGIS JS API中使用WebGL实现波纹扩散特效

在现代WebGIS开发中,ArcGIS JS API 是一个非常强大的工具,它允许开发者创建丰富的地理信息应用。结合WebGL技术,我们可以实现更加复杂和炫酷的可视化效果。本文将介绍如何使用ArcGIS JS API结合WebGL实现一个波纹扩散特效。 波纹扩散效果 1 概…

Rust 文件读取:实现我们的 “迷你 grep”

1. 准备示例文件 首先,在项目根目录(与 Cargo.toml 同级)下新建一个名为 poem.txt 的文件。示例内容可参考 Emily Dickinson 的诗: Im nobody! Who are you? Are you nobody, too? Then theres a pair of us — dont tell! Th…