STM32速成笔记—GPIO

news2025/2/12 0:59:31

文章目录

  • 一、什么是GPIO
  • 二、GPIO的输入/输出模式
  • 三、GPIO初始化配置
  • 四、Boot引脚
  • 五、一些特殊的GPIO
  • 六、点亮LED
    • 1. 硬件电路
    • 2. 拉高/拉低GPIO
    • 3. 程序设计
  • 七、GPIO的位带操作

一、什么是GPIO

GPIO(英语:General-purpose input/output),通用型之输入输出的简称,可以用来输入高低电平或者输出高低电平。这里的高电平指的是3.3V,低电平指的是0V。通常称GPIO为IO口,或者引脚。

STM32F103ZET6有GPIOx_0~GPIOx_15,其中x = A,B,C,D,E,F,G。

二、GPIO的输入/输出模式

GPIO有多种输入输出模式,输入模式有

  • 输入浮空
    输入浮空指的是GPIO与外设之间既不接高电平,也不接低电平,呈高阻态。除了类似于在数据传输时将GPIO配置为输入浮空外,一般不配置为该模式。因为输入浮空状态的GPIO电压具有不确定性,可能是0V,也可能是VCC,或者是介于0V和VCC之间的某一个值。
  • 输入上拉
    输入上拉是通过一个上拉电阻,将GPIO拉至高电平状态,不受外接电路的影响。
  • 输入下拉
    输入下拉是通过一个下拉电阻,将GPIO拉至低电平,不受外接电路的影响。
  • 模拟输入
    模拟输入模式通常用在ADC采集,采集模拟信号。

输出模式有

  • 开漏输出
  • 推挽式输出
  • 推挽式复用功能
  • 开漏复用功能

对于一些输出模式这里就不再做详细介绍了,贴一篇大佬的文章深刻理解GPIO。这些模式在接下来的学习过程中会慢慢的介绍这些模式需要在什么时候使用,这里只需要知道就够了。

三、GPIO初始化配置

本专栏介绍的是使用库函数进行开发,很多内容都是库函数提供的,相对来讲非常方便。在初始化GPIO时有一个结构体,只需要对这个结构体进行配置即可。结构体中包括想要配置的GPIO引脚,GPIO速度,GPIO工作模式。

初始化GPIO的步骤主要有

  • 定义GPIO结构体
  • 开启时钟
    GPIO工作需要提供时钟信号,在初始化结构体之前需要将时钟打开
  • 配置结构体成员
    GPIO_Pin是想要配置的IO,GPIO_Speed,通常写GPIO_Speed_50MHz,GPIO_Mode是IO的工作模式
  • 写入配置

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的例程如下

void Drv_Gpio_Init (void)
{
	GPIO_InitTypeDef GPIO_InitStructure;   // 定义结构体
	// 开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB,ENABLE);

    // 配置结构体
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	// 配置结构体
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

这里初始化的是PA0,PA8和PB1,PB2。在开启时钟不必要写两遍相同的代码用来初始化GPIOA和GPIOB的时钟。写一句,用“ | ”同时开启两个GPIO的时钟。写Pin时也同理。

四、Boot引脚

这里简单介绍一下Boot引脚的配置,对于只是利用核心板编写程序的小伙伴来说Boot引脚的存在感较低,但是当我们需要绘制硬件电路图时,Boot引脚怎么连接就显得很重要。
中文参考手册中介绍如下
中文参考手册Boot引脚介绍

这里简单说一下本人经历得来的经验。如果想使用USB转TTL通过串口下载程序,Boot0需要通过KΩ级电阻接VCC,Boot1接地。下载完程序后再将Boot0接地。需要注意的是这个KΩ级别的电阻最好用10KΩ左右电阻,如果电阻太大会导致下载失败。

由于本人在使用自制板时只使用过串口下载,所以对于用调试器下载需要怎么配置Boot引脚,未测试。

五、一些特殊的GPIO

在使用GPIO时需要注意一些特殊的GPIO,否则你会疑惑,为什么一些引脚的高低电平无法控制。其实有些GPIO在上电后就有自己的默认设置,会稳定在高电平或者低电平。比如用作JTAG的几个GPIO——PB3,PB4,PA13,PA14和PA15。这几个GPIO在上电后就已经默认用作JTAG,即使用上面的GPIO初始化程序将这几个引脚初始化后,依旧无法控制(无法正常用程序拉高拉低)。

这个时候我们需要对这几个GPIO进行复用重映射,关掉其默认的功能,才能作为普通的GPIO使用。针对JTAG/SWD复用功能重映射,中文参考手册描述如下
中文参考手册关于JTAG/SWD引脚的描述
图中说明这几个GPIO有几种模式,完全SWJ,表中的五个IO均不可作为普通IO使用。完全SWJ但是没有JNTRST,PB3和PB4可用,依此解读。上图是针对寄存器开发描述的内容,使用库函数开发时有封装好的函数,但是需要注意的是需要提前开启AFIO时钟(对于AFIO是指什么,大家可以自行了解)。使用库函数开发时针对特殊引脚进行重映射的操作步骤为

  • 定义GPIO结构体
  • 开启GPIO时钟和AFIO时钟
  • 重映射引脚(根据所需情况设定引脚模式)
  • 配置GPIO结构体初始化GPIO

库函数中提供了可以选择的三种引脚模式

GPIO_Remap_SWJ_NoJTRST          // 完全SWJ(恢复引脚的默认功能)
GPIO_Remap_SWJ_JTAGDisable      // 关闭JTAG,启用SW-DP
GPIO_Remap_SWJ_Disable          // 关闭JTAG-DP,关闭SW-DP

提供了一个函数,可以进行重映射操作

void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);

当需要使用到上述的五个GPIO时,初始化程序需要修改,举例如下

void Drv_Gpio_Init (void)
{
	GPIO_InitTypeDef GPIO_InitStructure;   // 定义结构体
	// 开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | 
	                       RCC_APB2Periph_AFIO,ENABLE);

    // 关闭JTAG-DP,关闭SW-DP
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);
    
    // 配置结构体
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	// 配置结构体
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

STM32F103ZET6芯片GPIO资源较为丰富,平时开发时尽量不要使用这几个特殊引脚。

六、点亮LED

学习完GPIO后我们就可以利用GPIO进行一些简单的操作,比如点亮LED,使用蜂鸣器,用IO驱动小黄电机,检测按键等。

点亮LED比较简单,但是也有一些需要注意的点

  • 根据硬件电路确定LED是高电平点亮还是低电平点亮
  • 初始化GPIO后要先将所有的LED

1. 硬件电路

下图所示电路中,LED右侧接3.3V,左侧接IO口。此时如果想点亮LED,需要将对应的IO电平拉低。相反如果右侧接的是地,如果想要点亮LED,需要将对应IO电平拉高。
LED电路

2. 拉高/拉低GPIO

如何将GPIO电平拉高拉低?库函数提供了封装好的函数

// 设置为高电平
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

// 设置为低电平
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

3. 程序设计

点亮LED很简单,只需要初始化相应的GPIO,输入模式设置为推挽式输出,然后设定电平即可。

这里给出点亮LED的例程,LED电路为一侧接3.3V,另一侧接GPIO。
这里给出的只是一些必要的函数,如果需要工程模板可私信联系。

/*
 *==============================================================================
 *函数名称:Drv_Led_Init 
 *函数功能:初始化LED的GPIO
 *输入参数:无
 *返回值:无
 *============================================================================*/
*/
void Drv_Led_Init (void)
{
	GPIO_InitTypeDef GPIO_InitStructure;   // 定义结构体
	// 开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

    // 配置结构体
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_SetBits(GPIOA,GPIO_Pin_1);   // 熄灭LED
}

/*
 *==============================================================================
 *函数名称:Med_Led_On 
 *函数功能:点亮LED
 *输入参数:无
 *返回值:无
 备注:如果有多个LED可以定义一个结构体或者使用swtich,增加一个输入变量
      来确定开启哪个LED
 *============================================================================*/
*/
void Med_Led_On (void)
{
    GPIO_ResetBits(GPIOA,GPIO_Pin_1);   // 熄灭LED
}

七、GPIO的位带操作

对于什么是“位带”这里就不做解释了,大家可以自行搜索。这里只介绍如何使用。位带操作可以使操作GPIO变得更加简单。在模板程序的sys.h文件中已经定义好了各个IO的位带操作所需内容

//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入

有了位带操作后,就不需要再使用前面介绍的拉高拉低函数来操作GPIO。比如需要拉d低PA1

PAout(1) = 0;   // 拉低PA1

有了位带操作后也可以对GPIO进行宏定义,用自己想要的名字来操作它。还是拿上面的拉低PA1举例

#define LED   PAout(1)   // 将PA1宏定义为LED

LED = 1;   // 拉高PA1
LED = 0;   // 拉低PA1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/645895.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【算法与数据结构】142、LeetCode环形链表 II

文章目录 一、题目二、哈希法三、完整代码 所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、哈希法 思路分析:这道题也可以用双指针法去解,这里我介绍一种哈希法。利用set集合的值不可重复的特性。…

什么触控笔好用又便宜?性价比高的苹果笔推荐

而对于一些将IPAD作为学习工具的人来说,这款苹果Pencil无疑是必不可少的。不过,苹果版Pencil的价格实在是太高了,很多人都买不起。所以,最好的办法就是使用平替的电容笔。我是在前几年就开始使用ipad了,同时也是一位数…

快速入门教程:神经常微分方程 (Neural ODE)

神经常微分方程(Neural Ordinary Differential Equations,简称 Neural ODE)是一种基于常微分方程(Ordinary Differential Equations,ODEs)的深度学习方法,它结合了传统的ODE数值求解技术和神经网络模型。通过使用ODE来建模数据的演化过程,Neural ODE可以自动地学习数据…

项目管理专业人员能力评价(CSPM)对比PMP哪个好考?

2021年10月,中共中央、国务院发布的《国家标准化发展纲要》明确提出构建多层次从业人员培养培训体系,开展专业人才培养培训和国家质量基础设施综合教育。建立健全人才的职业能力评价和激励机制。由中国标准化协会(CAS)组织开展的项…

编译opencv环境搭建:vs2019 + cmake-3.25 + opencv-4.5.5

一 下载vs2019 链接:Downloads - Visual Studio Subscriptions Portal 下载社区版本,因为是免费的,大家随便用 下载成功后直接安装就可以了。 有的环境安装好后在属性管理器中可能没有 Microsoft.Cpp.x64 文件 从如下链接下载 Microsoft.C…

三、OkHttp_缓存

一、OKHttp的缓存逻辑 OKHttp 把重复请求的数据缓存在本地,并设置超时时间,在规定时间内,客户端不再向远程请求数据,而是直接从本地缓存中取数据。 一来提高了响应速度,二来节省了网络带宽(也就是节省了钱…

如何使用uni-app开发微信小程序

web前端-基于uniapp的微信小程序项目 起步uni-app简介开发工具下载 HBuilderX安装 HBuilderX安装 scss/sass 编译快捷键方案切换修改编辑器的基本设置新建uni-app项目把项目运行到微信开发者工具 scss语法学习安装相关插件和配置基础格式选择器的嵌套父选择器后面添加内容 &…

麒麟系统在线安装docker(x86/arm)

文章目录 一、查看系统版本,确认版本二、查看系统架构三、下载安装docker-ceX86架构安装aarch64架构 一、查看系统版本,确认版本 [rootlocalhost ~]# cat /etc/kylin-release Kylin Linux Advanced Server release V10 (Sword)二、查看系统架构 [root…

Windows内存诊断工具卡住无响应怎么办?

Windows内存诊断工具是一个有用的程序,用于检查您的RAM是否存在潜在问题。当系统性能降低、频繁冻结或者蓝屏时,用户可以通过内存诊断工具检查和修复内存方面的问题。该工具具有三种测试模式,基本、标准和扩展模式,其中扩展模式下…

在UOS上安装及更新恒辉桌面软件

UOS作为一颗冉冉升起的新星,吸引了众多国内用户及厂商的目光。 而新的系统势必面临着一个问题——软件及应用的适配性。各个软件厂商需要单独为此适配产品。 2022年2月,支持全四路国产CPU(x86架构、arm架构、龙芯、申威)的数据库…

chatgpt赋能python:Python如何打印结果

Python如何打印结果 Python是一种高级编程语言, 它也是一种解释型语言,也就是说,程序员不必把Python代码编译成机器码或者字节码。它利用缩进来表示块结构,同时使用一些特殊的关键字来定义变量和类等。 在Python中,有多种方式来…

算法课设 戳气球问题实验报告 动态规划

戳气球实验报告 目录 一、题目 二、分析原问题并做调整 三、分析子问题及其递推关系 四、确定dp数组的计算顺序 五、复杂度分析 六、具体实现代码 七、填表示例寻找最优解和最优方案 八、总结 九、致谢 一、题目 有n个气球,编号为0到n-1,每个…

管理类联考——逻辑——知识篇——第三章 三段论(考2题)(以性质命题为基础,最常用推理)

第三章 三段论(考2题)(以性质命题为基础,最常用推理) 一、三段论的基本结构 基本结构1(最简单,不考): 所有A是B 所有B是C 得:所有A是C 基本结构2&#xff…

网络安全系统教程+学习路线(自学笔记)

一、什么是网络安全 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域,都有攻与防两面…

MySQL查询优化大揭秘!看这些关键数据,让你的数据库速度飞起来!

大家好,我是小米,今天给大家分享一些关于MySQL查询优化的干货。在数据库开发和维护中,优化查询是至关重要的一环。通过合理的优化,我们可以让数据库的查询速度事半功倍。那么,在MySQL的查询计划中,有哪些关…

Spring五大类注解和方法注解

1.配置(重要)2.添加五大类注解2.1 Controller(控制器存储)2.2 Service(服务存储)2.3 repository(仓库存储)2.4 Component(组件存储)2.5 Configuration(配置存储&#xff…

【Python】基础内容

简介 面向对象,解释型的编程语言使用缩进作为逻辑层次 运行效率较低 单行注释:以#开头:#注释内容多行注释:以一对三个双引号引起来的内容: “”“注释内容”“” 数据类型 type(被查看类型的数据):查看…

KETTLE Driver class ‘org.gjt.mm.mysql.Driver‘ could not be found

kettle链接mysql:抛出异常 Driver class org.gjt.mm.mysql.Driver could not be found 这是因为你没有下载对应的mysql驱动程序包(DRIVER.jar)到你的kettle下: 1 查看你的mysql版本 C:\Users\22077>mysql --version mysql …

快速拼接字符串的新类StringJoiner~

初识StringJoiner类: StringJoiner 是 Java 8 新增的一个类,它不仅提供了一种快速、方便地将多个字符串拼接成一个字符串的方法,并且在拼接之时还可以指定分隔符、前缀和后缀,以及添加多个字符串,最终输出拼接后的字符…

9-基于stm32的MAX31865铂电阻PT100测温全套资料(原理图+教程+程序)

编号: 009 本项目可以通过PT100测温,测温范围为: -200~420C,采用1.8寸OLED显示该资料已经过实物验证,实物中是通过触发GPIO来测量当前的温度,程序注释非常详细,容易上手 经过实验验证,切实可行!配备详细代码…