一.GPIO简介
GPIO(general porpose intput output):通用输入输出端口的简称。可以通过软件控制其输出和输入。stm32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通信,控制以及数据采集的功能。
1.可配置为8种输入输出模式
2.引脚电平:0V~3.3V,部分引脚可容忍5V
3.输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等
4.输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等
二.GPIO基本结构
如下图,这就是GPIO的整体构造,其中左边是APB2外设总线,在stm32中,所有的GPIO都是挂载在APB2外设总线上的,其中GPIO外设的名称是按照GPIOA,GPIOB,GPIOC等等这样来命名的,每个GPIO外设总共有16个引脚,编号从0到15,那GPIOA的第0号引脚,称作PA0,接着第2号引脚就是PA1,然后PA2以此类推一直到PA15。
在每个GPIO模块内主要包含寄存器和驱动器,寄存器就是一段特殊的存储器,内核通过APB2总线对寄存器进行读写,来完成输出电平和读取电平的功能,寄存器的每一位对应一个引脚,其中输出寄存器写1,对应的引脚就会输出高电平;写0,就输出低电平输。输入寄存器读取为1,就证明对应的端口目前是高电平;读取为0,就是低电平。
因为stm32是32位的单片机,所以stm32内部的寄存器都是32位的,但端口只有16位,所以这个寄存器只有低16位对应的有端口,高16位是没有用到的。这个驱动器是用来增加信号的驱动能力的,寄存器只负责存储数据,如果要进行点灯这样的操作的话是需要驱动器来负责增大驱动能力。
三.GPIO位结构
下图就是stm32参考手册中的GPIO位结构的电路图,其中左边三个就是寄存器,中间部分是驱动器,右边是某一个io引脚,整体结构可以分为两个部分,上面是输入部分,下面是输出部分。
先来看输入部分,io引脚这里接了两个保护二极管,是对输入电压进行限幅的,上面这个二极管接vdd 3.3伏,下面接vss 0伏,如果输入电压比3.3伏还要高,那上方这个二极管就会导通,输入电压产生的电流就会直接流入VDD而不会流入内部电路,可以避免过高的电压对内部这些电路产生的伤害。如果输入电压比零伏还要低,这个电压是相当于vss的电压,所以是可以有负电压的,这时下方这个二极管就会导通,电流会从vss直接流出去,而不会从内部电路汲取电流,也是可以保护内部电路的,如果输入电压在0到3.3伏之间,那两个二极管都不会导通,这时二极管对电路没有影响,这就是保护二极管的用途。
接下来这根线就到了开关这个地方,这里连接了一个上拉电阻和一个下拉电阻,上拉电阻是vdd,下拉电阻是vss,这个开关是可以通过程序进行配置的,如果上面导通,下面断开,打开又是上拉输入模式,如果下面导通,上面断开就是下拉输入模式,如果两个都断开就是浮空输入模式,那这个上拉和下拉有什么作用呢?这个其实是为了给输入提供一个默认的输入电平,因为对于一个数字的端口,输入不是高电平就是低电平,那如果输入引脚啥都不接,那到底是算高电平还是低电平呢?这就不好说了,实际情况是如果输入啥都不接,这时输入就会处于一种浮空的状态,引脚的输入电平极易受外界干扰而改变,就像是一个物体悬浮在太空一样,它的位置是不确定的,受到一点扰动就会变化,为了避免引脚悬空而导致的输入数据不确定,我们就需要在这里加上上拉或者下拉电阻了,如果接入上拉电阻,当引角悬空时,还有上拉电阻来保证引脚的高电平。所以上拉输入又可以称作是默认为高电平的输入模式,下拉也是同理,就是默认为低电平的输入方式,这就像是在太空的物体来到了地球上,如果不施加外力,由于重力的下拉作用,默认还是回到地面,这个上拉电阻和下拉电阻的阻值都是比较大的,是一种弱上拉和弱下拉,目的是尽量不影响正常的输入操作。
接着我们继续往下看,这里是一个肖特基触发器,这里写的是施密特触发器的英文,这个斯密特触发器的作用就是对输入电压进行整形,它的执行逻辑是如果输入电压大于某一阈值,输出就会瞬间升为高电平,如果输入电压小于某一阈值,输出就会瞬间变为低电平。
最后左上面这还有两路线路,这些就是连接到片上外设的一些端口,其中有模拟输入,这个是连接到ADC上的,因为ADC需要接收模拟量,所以这根线是接到施密特触发器前面的,另一个是复用功能输入,这个是连接到其他需要读取端口的外设上的,比如串口的输入引脚等,这根线接收的是数字量,所以在施密特触发器后面。
接着我们再来看一下输出的部分,输出部分可以由输出数据寄存器或片上外设控制。两种控制方式通过数据选择器接到了输出控制部分,如果选择通过输出数据寄存器进行控制,就是普通的io口输出,写这个数据寄存器的某一位就可以操作对应的某个端口了,左边还有位设置/清除寄存器,这个可以用来单独操作输出数据寄存器的某一位,而不影响其他位,因为这个输出数据寄存器同时控制16个端口,并且这个寄存器只能整体读写,所以如果想单独控制其中某一个端口而不影响其他端口的话,就需要一些特殊的操作方式,常用的方式是通过设置位设置和位清除寄存器,我们需要对某一位进行置1的操作,在位设置寄存器的对应位写1即可,剩下不需要操作的位写0,这样它内部就会有电话,自动将输出数据寄存器对应位置为1,而剩下写0的位则保持不变,这样就保证了只操作其中某一位而不影响其他位,并且这是一步到位的操作,如果想对某一位进行清零的操作,就在位清除寄存器的对应位写1即可,这样内部电路就会把这一位清零了,这也是这个位设置和位清除寄存器的作用。
继续看,接下来输出控制之后就接到了两个MOS管,上面是P-MOS,下面是N-MOS,这个MOS就是一种电子开关,我们的信号来控制开关的导通和关闭开关,开关负责将io口接到vdd或者vss,在这里可以选择推挽,开漏或关闭三种输出方式,在推挽输出模式下,P-MOS或N-MOS均有效。数据寄存器为1时,上管导通,下管断开,输出直接接到vdd,就是输出高电平,数据寄存器为零时,上管断开下管导通,输出直接接到vss,就是输出低电平。这种模式下,高低电平均有较强的驱动能力,所以推挽输出模式也可以叫强推输出模式。在推广输出模式下,stm32对io口具有绝对的控制权,高低电平都由stm32说的算,在开漏输出模式下,这个P-MOS是无效的,只有N-MOS在工作,数据寄存器为1时,下管断开,这时输出相当于断开,也就是高阻模式,数据寄存器为0时,下管导通,输出直接接到vss,也就是输出低电平。这种模式下只有低电平有驱动能力高电平是没有驱动能力的,那这个模式有什么用呢,这个开漏模式可以做为通信协议的驱动方式,比如12c通信的引脚,就是使用的开漏模式。在多机通信的情况下,这个模式可以避免各个设备的相互干扰,另外开漏模式还可以用于输出5伏的电平信号,比如在io口外接一个上拉电阻到五伏的电源,当输出低电平时,由内部的N-MOS直接接vss,当输出高电平时,由外部的上拉电阻拉高至五伏,这样就可以输出五伏的电平信号,用于兼容一些五伏电平的设备,这就是开漏输出的主要用途。剩下的一种状态就是关闭,这个是当引脚配置为输入模式的时候,这两个MOS管都无效,也就是输出关闭,端口的电平由外部信号来控制,那这些就是GPIO位结构的全部介绍。
四.GPIO模式
在输入模式时,施密特触发器打开,输出被禁止。
可通过输入数据寄存器GPIOx_IDR 读取 I/O 状态。
输入模式可以配置为模拟、上拉、下拉以及浮空模式。上拉和下拉输入很好理解,默认的电平由上拉或者下拉决定。
浮空输入的电平是不确定的,完全由外部的输入决定,一般接按键的时候可以使用这个模式。
模拟输入则用于 ADC 采集。
在输出模式中,推挽模式时双 MOS 管以推挽方式工作,输出数据寄存器GPIOx_ODR 可控制 I/O 输出高低电平。
开漏模式时,只有 N-MOS 管工作,输出数据寄存器可控制 I/O 输出高阻态或低电平。
输出速度可配置,有2MHz\25MHz\50MHz 的选项。此处的输出速度即 I/O 支持的高低电平状态最高切换频率,支持的频率越高,功耗越大,如果功耗要求不严格,把速度设置成最大即可。
在输出模式时,施密特触发器是打开的,即输入可用,通过输入数据寄存器 GPIOx_IDR 可读取 I/O 的实际状态。
复用功能模式中,输出使能,输出速度可配置,可工作在开漏及推挽模式,但是输出信号源于其它外设,输出数据寄存器 GPIOx_ODR 无效;输入可用,通过输入数据寄存器可获取 I/O 实际状态,但一般直接用外设的寄存器来获取该数据信号。