第四章 GPIO
GPIO全名为General Purpose Input Output,即通用输入输出接口。简称“IO口”。既能当输入口使用,又能当输出口使用。
MCU通常都采用引脚复位技术,即一个GPIO有多种功能,既可以直接控制输出高低电平又可以作为某些协议的引脚之一或者用于模拟信号输入/输出。
4.1 工作模式
STM32F103ZET6共有144个引脚,除去电源引脚、晶振时钟引脚、复位引脚、启动选择引脚、程序下载引脚(大部分为最小系统必须引脚),剩下的则是GPIO引脚。
STM32将这些众多按GPIOx(x为A—G)分组,每组包含16个引脚,编号为0~15。
STM32F103系列GPIO的基本结构,左侧连接MCU内部,中间上半部分为输入,中间下半部分为输出,右侧为MCU引出的外设I/O引脚。
4.1.1 输出模式
1、推挽输出
1)普通推挽输出
通过控制寄存器,让输出控制部分输出一定的电压,当输出控制部分有了一定的电压之后,P-MOS导通,N-MOS截止,此时IO引脚与VDD直接连接即输出高电平;当输出控制部分不施加电压,P-MOS截止,N-MOS导通,此时IO引脚与VSS直接连接即低电平。
这种模式的高电平就是VDD(3.3V),低电平就是VSS,输出电流增大,引脚驱动能力和电路负载能力变大,开关速度提高。
2)复用推挽输出
复用功能下的推挽输出和普通功能下的推挽输出是一样的,只不过一个是普通IO一个是复用IO,他们对输出控制部分的输入来源不同。
2、开漏输出
1)普通开漏输出
在开漏输出中,输出控制模块不会操作P-MOS,只操作N-MOS。
输出控制施加电压时,两个MOS管都截止, 两个漏极都处在悬空状态,此时IO口处在悬空状态。输出控制不施加电压时,P-MOS截止,N-MOS导通,此时IO口对外输出低电平。
在不加外部上拉电阻的情况下,IO口只能输出一个低电平或者处于浮空状态。所以要向外输出高电平,必须要外部加上拉电阻,此时输出的电平取决于VCC的大小。
这种模式的高电平取决于VCC,低电平就是VSS。VCC不限制在3.3V,可以改变大小,提高外部电路的驱动能力同时也可以实现电平转换;同时可以实现逻辑与的功能,多个开漏引脚并在一起使用,统一接在一个上拉电阻上,这样只有当全部的引脚输出高电平的时候,输出才为高电平。
2)复用开漏输出
复用功能下的开漏和普通功能下的开漏是一样的,只不过一个是普通IO一个是复用IO,同样也是输出控制部分的输入来源与普通模式不同。
4.1.2 输入模式
1、浮空输入
引脚电平是真实的外部连接器件电压,电平有不确定性。
此模式下,内部上拉、下拉电阻开关都断开。此时读取到的电平是不确定的,引脚电平是真实的外部连接器件电压,外部信号是什么电平,读取到的就是什么电平。MCU在复位状态时,IO引脚就处于此模式。浮空输入一般用来做ADC输入用,这样可以减少上下拉电阻对结果的影响。
2、上拉输入
此模式下,VDD的开关闭合,外部没有输入信号时,默认输入为高电平。
3、下拉输入
此模式与上拉输入相反,外部没有输入信号时,默认低电平输入。
4、模拟输入
此模式下TTL肖奈特触发器、上拉、下拉电阻都断开,IO引脚直接和模拟输入连接,将外部信号直接传输到数模转换通道上。
4.2 输出速度
IO口工作在输出模式下,可以配置其输出速度大小。该输出速度不是输出信号的速度,而是I/O口驱动电路的响应速度。
STM32提供三个输出速度:2MHz、10MHz、50MHz。实际开发中需要结合实际情况选择合适的相应速度。一般来说对于点灯、按键等简单操作,设置为低速就行;若IO口作为一些协议的数据传输引脚,通常速度设置高点。
4.2 GPIO实验
通过LED闪烁实验,了解GPIO配置的一般步骤。
4.2.1原理
1、通过原理图,确定LED与单片机的引脚连接,分析如何实现灯闪烁。
简单分析可知,三个LED灯分别与单片机的PB0,PB1,PB5引脚连接。当引脚输出高电平时,LED不导通,灯灭;输出低电平时,LED导通,灯亮,所以通过控制三个GPIO口的输出电平即可控制LED亮灭。
2、编写程序
程序设计思路(GPIO部分):
1)打开GPIOB时钟;
2)定义GPIO初始化构体。
3) 配置结构体成员;
4)初始化结构体;
5)调用函数控制IO口输出;
前面已经知道了,HAL库已经为用户封装了许多函数,用户只需要调用即可,那么在这里具体使用到了哪些库函数以及如何初始化时钟和GPIO口呢?
4.2.2 GPIO相关结构体和函数
关于GIPO的配置和调用函数,HAL库已经做得非常完善了。
HAL库提供了一个结构体GPIO_InitTypeDef
,用户可以自定义这样的一个结构体进行配置,然后用HAL_GPIO_Init
这个函数将结构体中的值传递到寄存器中,即可完成GPIO配置。
4.2.3程序代码
根据官方提供的注释,可以总结出如何使用官方库函数实现GPIO的初始化及输入输出等功能。
下面是根据注释编写的代码。
注意使能GPIO具体引脚的时候,是可以进行或操作的,即一次使能多个引脚,前提是这些引脚在同一组中。
HAL库中对于函数和结构体的封装做的非常细致,绝大部分结构体成员的参数,HAL库中都做了宏定义,用户只需要根据他们的宏定义来设置即可,不需要自己计算参数。在配置结构体成员的时候,如果不知道该成员的参数范围是什么,可以右键Go To Definition Of XXX来查找。
可以看到关于Mode的所有能用到的参数都在这里了,用户根据需要自己选择即可。
对于其他的参数这里就不一一罗列了,跟上述方法一样,可自行查找。