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

STM32F1 GPIO介绍及应用

第一章 GPIO介绍及应用

1. GPIO简介

GPIO 是通用输入输出端口的简称,简单来说就是 STM32 可控制的引脚, STM32 芯片的 GPIO 引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。 STM32 芯片的 GPIO被分成很多组,每组有 16 个引脚,如型号为 STM32F103VET6 型号的芯片有 GPIOA、 GPIOB、GPIOC 至 GPIOE 共 5 组 GPIO,芯片一共 100 个引脚,其中 GPIO 就占了一大部分,所有的 GPIO引脚都有基本的输入输出功能。

最基本的输出功能是由 STM32 控制引脚输出高、低电平,实现开关控制,如把 GPIO 引脚接入到 LED 灯,那就可以控制 LED 灯的亮灭,引脚接入到继电器或三极管,那就可以通过继电器或三极管控制外部大功率电路的通断。

最基本的输入功能是检测外部输入电平,如把 GPIO 引脚连接到按键,通过电平高低区分按键是否被按下。

2. GPIO工作模式

总结一下,由 GPIO 的结构决定了 GPIO 可以配置成以下模式:

typedef enum
{GPIO_Mode_AIN = 0x0, // 模拟输入GPIO_Mode_IN_FLOATING = 0x04, // 浮空输入GPIO_Mode_IPD = 0x28, // 下拉输入GPIO_Mode_IPU = 0x48, // 上拉输入GPIO_Mode_Out_OD = 0x14, // 开漏输出    GPIO_Mode_Out_PP = 0x10, // 推挽输出GPIO_Mode_AF_OD = 0x1C, // 复用开漏输出GPIO_Mode_AF_PP = 0x18 // 复用推挽输出
} GPIOMode_TypeDef;

在标准库中, GPIO 总共有 8 种细分的工作模式,稍加整理可以大致归类为以下三类:

2.2.1 输入模式(模拟/浮空/上拉/下拉)

在输入模式时,施密特触发器打开,输出被禁止,可通过输入数据寄存器 GPIOx_IDR 读取 I/O 状态。其中输入模式,可设置为上拉、下拉、浮空和模拟输入四种。上拉和下拉输入很好理解,默认的电平由上拉或者下拉决定。浮空输入的电平是不确定的,完全由外部的输入决定,一般接按键的时候用的是这个模式。模拟输入则用于 ADC 采集。

2.2.2 输出模式(推挽/开漏)

在输出模式中,推挽模式时双 MOS 管以轮流方式工作,输出数据寄存器 GPIOx_ODR 可控制 I/O输出高低电平。开漏模式时,只有 N-MOS 管工作,输出数据寄存器可控制 I/O 输出高阻态或低电平。输出速度可配置,有 2MHz10MHz50MHz 的选项。此处的输出速度即 I/O 支持的高低电平状态最高切换频率,支持的频率越高,功耗越大,如果功耗要求不严格,把速度设置成最大即可

在输出模式时施密特触发器是打开的,即输入可用,通过输入数据寄存器 GPIOx_IDR 可读取 I/O的实际状态。

2.2.3 复用功能(推挽/开漏)

复用功能模式中,输出使能,输出速度可配置,可工作在开漏及推挽模式,但是输出信号源于其它外设,输出数据寄存器 GPIOx_ODR 无效;输入可用,通过输入数据寄存器可获取 I/O 实际状态,但一般直接用外设的寄存器来获取该数据信号。

3. GPIO使用示例

3.1 GPIO输出-点亮LED

在这里插入图片描述

3.1.1 led相关参数宏定义
#ifndef __LED_H__
#define __LED_H__#include "stm32f10x.h"#define LED_GPIO_Port GPIOB
#define LED_GPIO_CLK RCC_APB2Periph_GPIOB
#define RED_LED_Pin GPIO_Pin_5
#define GREEN_LED_Pin GPIO_Pin_0
#define BLUE_LED_Pin GPIO_Pin_1#define LED_ON(x)    GPIO_SetBits(LED_GPIO_Port, (x))
#define LED_OFF(x)   GPIO_ResetBits(LED_GPIO_Port, (x))#endif /* __LED_H__ */
3.1.2 GPIO初始化
#include "led.h"void BSP_LED_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(LED_GPIO_CLK, ENABLE); // 打开GPIO时钟// 初始化红色 LED 引脚GPIO_InitStructure.GPIO_Pin = RED_LED_Pin; // 选择引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 输出速度GPIO_Init(LED_GPIO_Port, &GPIO_InitStructure);// 初始化绿色 LED 引脚GPIO_InitStructure.GPIO_Pin = GREEN_LED_Pin;GPIO_Init(LED_GPIO_Port, &GPIO_InitStructure);// 初始化蓝色 LED 引脚GPIO_InitStructure.GPIO_Pin = BLUE_LED_Pin;GPIO_Init(LED_GPIO_Port, &GPIO_InitStructure);// 初始LED全灭LED_OFF(RED_LED_Pin);LED_OFF(GREEN_LED_Pin);LED_OFF(BLUE_LED_Pin);
}
3.1.3 主函数测试
#include "stm32f10x.h"
#include "led.h"#define led_delay delay(0x0FFFFF);void delay(__IO uint32_t nCount)
{for(; nCount != 0; nCount--);
}int main()
{BSP_LED_Init();while(1){LED_ON(RED_LED_Pin);led_delay;LED_OFF(RED_LED_Pin);led_delay;LED_ON(GREEN_LED_Pin);led_delay;LED_OFF(GREEN_LED_Pin);led_delay;LED_ON(BLUE_LED_Pin);led_delay;LED_OFF(BLUE_LED_Pin);led_delay;}
}

3.2 GPIO输出-控制蜂鸣器

在这里插入图片描述

3.2.1 蜂鸣器相关参数宏定义
#ifndef __BEEP_H__
#define __BEEP_H__ #include "stm32f10x.h"#define Beep_GPIO_Port GPIOA
#define Beep_GPIO_CLK RCC_APB2Periph_GPIOA
#define Beep_GPIO_Pin GPIO_Pin_8#define BEEP_ON() GPIO_SetBits(Beep_GPIO_Port, Beep_GPIO_Pin)
#define BEEP_OFF() GPIO_ResetBits(Beep_GPIO_Port, Beep_GPIO_Pin)void BSP_Beep_Init(void);#endif /* __BEEP_H__ */
3.2.2 GPIO初始化
#include "beep.h"void BSP_Beep_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(Beep_GPIO_CLK, ENABLE);GPIO_InitStructure.GPIO_Pin = Beep_GPIO_Pin;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(Beep_GPIO_Port, &GPIO_InitStructure);BEEP_OFF();
}
3.2.3 主函数测试
#include "stm32f10x.h"
#include "beep.h"#define beep_delay delay(0x0FFFFF);void delay(__IO uint32_t nCount)
{for(; nCount != 0; nCount--);
}int main()
{BSP_Beep_Init();while(1){BEEP_ON();beep_delay;BEEP_OFF();beep_delay;}
}

3.3 GPIO输入-按键控制LED

在这里插入图片描述

3.3.1 按键相关参数宏定义
#ifndef __KEY_H__
#define __KEY_H__#include "stm32f10x.h"#define KEY1_GPIO_CLK RCC_APB2Periph_GPIOA
#define KEY1_GPIO_Port GPIOA
#define KEY1_GPIO_Pin GPIO_Pin_0
#define KEY2_GPIO_CLK RCC_APB2Periph_GPIOC
#define KEY2_GPIO_Port GPIOC
#define KEY2_GPIO_Pin GPIO_Pin_13#define KEY_OFF 0
#define KEY_ON 1void BSP_KEY_Init(void);
uint8_t KEY_Scan(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);#endif /* __KEY_H__ */
3.3.2 GPIO初始化
void BSP_KEY_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(KEY1_GPIO_CLK|KEY2_GPIO_CLK, ENABLE);GPIO_InitStructure.GPIO_Pin = KEY1_GPIO_Pin;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入GPIO_Init(KEY1_GPIO_Port, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = KEY2_GPIO_Pin;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(KEY2_GPIO_Port, &GPIO_InitStructure);
}
3.3.3 按键扫描函数
uint8_t KEY_Scan(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{if(GPIO_ReadInputDataBit(GPIOx, GPIO_Pin) == KEY_ON) // 读取按键电平{while(GPIO_ReadInputDataBit(GPIOx, GPIO_Pin) == KEY_ON); // 判断按键是否长时间按下return KEY_ON;}else{return KEY_OFF;}
}
3.3.4 主函数测试
#include "stm32f10x.h"
#include "led.h"
#include "key.h"int main()
{BSP_LED_Init();BSP_KEY_Init();while(1){if(KEY_Scan(KEY1_GPIO_Port, KEY1_GPIO_Pin) == KEY_ON){LED_ON(RED_LED_Pin);}if(KEY_Scan(KEY2_GPIO_Port, KEY2_GPIO_Pin) == KEY_ON){LED_OFF(RED_LED_Pin);}}
}

4. GPIO常见函数(STD库)

4.1 初始化与配置

  • 使能GPIO时钟
    使用RCC_APB2PeriphClockCmd()开启对应GPIO端口的时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟
  • GPIO初始化
    通过GPIO_Init()配置引脚模式、速度等参数:
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;          // 配置PA0
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;   // 推挽输出模式
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;  // 速度50MHz
GPIO_Init(GPIOA, &GPIO_InitStruct);             // 应用配置

4.2 输出操作

  • 设置引脚为高电平
    GPIO_SetBits()将指定引脚置高:
GPIO_SetBits(GPIOA, GPIO_Pin_0); // PA0输出高电平
  • 设置引脚为低电平
    GPIO_ResetBits()将指定引脚置低:
GPIO_ResetBits(GPIOA, GPIO_Pin_0); // PA0输出低电平
  • 按位写入引脚状态
    GPIO_WriteBit()灵活设置单个引脚状态(Bit_SETBit_RESET):
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); // PA0输出高
  • 写入整个端口
    GPIO_Write()一次性设置所有引脚状态:
GPIO_Write(GPIOA, 0x01); // PA0置高,其余置低

4.3 输入操作

  • 读取单个引脚输入状态
    GPIO_ReadInputDataBit()获取输入引脚的电平:
uint8_t value = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0); // 读取PA0输入值
  • 读取整个端口输入值
    GPIO_ReadInputData()返回端口的16位输入数据:
uint16_t port_value = GPIO_ReadInputData(GPIOA); // 读取GPIOA所有输入引脚

4.4 输出状态读取

  • 读取输出寄存器状态
    GPIO_ReadOutputDataBit()GPIO_ReadOutputData()用于读取输出寄存器的值(可能与实际引脚状态不同):
uint8_t output_bit = GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_0); // 读取PA0输出寄存器状态
uint16_t output_port = GPIO_ReadOutputData(GPIOA);              // 读取GPIOA输出寄存器全部状态

4.5 其他函数

  • 引脚配置锁定
    GPIO_PinLockConfig()锁定引脚配置,防止意外修改:
GPIO_PinLockConfig(GPIOA, GPIO_Pin_0); // 锁定PA0配置

文中工程下载:https://github.com/hazy1k/STM32F1-Quick-Start-Guide-STD/tree/master/2.code

http://www.xdnf.cn/news/18538.html

相关文章:

  • C/C++三方库移植到HarmonyOS平台详细教程(补充版so库和头文件形式)
  • 凌霄飞控开发日志兼新手教程——基础篇:认识基本的文件内容和相关函数作用(25电赛备赛版)
  • 【序列晋升】12 Spring Boot 约定优于配置
  • Spring发布订阅模式详解
  • Python 调用 sora_image模型 API 实现图片生成与垫图
  • 【论文】Zotero文献管理
  • 为什么应用会突然耗尽所有数据库连接
  • 轮廓检测技术不仅能精确计算图像中的轮廓数量,还能完整记录每个轮廓包含的所有像素点坐标
  • 【0基础3ds Max】捕捉工具详解
  • 宋红康 JVM 笔记 Day06|虚拟机栈
  • [激光原理与应用-318]:结构设计 - Solidworks - 草图
  • 损耗源:导线电阻与趋肤效应
  • 深度学习②【优化算法(重点!)、数据获取与模型训练全解析】
  • 线上日志排查问题
  • MCP 与 Function Calling 打开真实世界的两种“母体”方式
  • Spring 框架深度解析:从核心原理到实战应用
  • GitLab CI :深入剖析 gl-sbom-report.cdx.json 解码“数字身份证”
  • linux下的网络编程
  • 快速入门Vue3——初体验
  • 6020角度双环控制一种用于电机控制的策略
  • 智能合约漏洞检测技术综述:守护区块链世界的“自动售货机”
  • 在通义灵码中配置MCP服务
  • uniapp使用map打包app后自定义气泡不显示解决方法customCallout
  • JavaWeb前端05(Vue工程化,Vue组件两种风格:组合式API 和 选项式API)及简单案例)
  • 豆包 + 蘑兔,破解写歌难题!
  • 知识蒸馏 Knowledge Distillation 论文 Generalized Knowledge Distillation (GKD) 目标函数的演化
  • 【Cmake】Cmake概览
  • 使用GMail API 发送邮箱
  • OpenSCA开源社区每日安全漏洞及投毒情报资讯|21th Aug. , 2025
  • 前端github-workflows部署腾讯云轻量服务器