GPIO简介
GPIO(General Purpose Input Output)通用输入输出口
可配置为8种输入输出模式
引脚电平:0V~3.3V,部分引脚可容忍5V
输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等
输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等
GPIO基本结构
在STM32中,所有的GPIO都是挂载在APB2外设总线上的,其中GPIO外设的名称是按照GPIOA、GPIOB、GPIOC等等这样来命名的。每个GPIO外设,总共有16个引脚,标号是从0到15。GPIO的第0号引脚,我们一般把它称作PA0,接着1号就是PA1,然后PA2,以此类推,一直到PA15。GPIOB也是一样。
在每个GPIO模快内,主要包含了寄存器和驱动器这些东西,寄存器就是一段特殊的存储器,内核可以通过APB2总线对寄存器进行读写,这样就可以完成输出电平和读取电平的功能了,这个寄存器的每一位对应一个引脚,其中输出寄存器写1,对应的引脚就会输出高电平,写0,就输出低电平。输入寄存器读取为1,就证明对应的端口目前是高电平,读取为0,就是低电平。
因为STM32是32位的单片机,所以STM32内部的寄存器都是32位的,但这个端口只有16位,所以这个寄存器只有低16位对应的有端口,高16位是没有用到的。
驱动器是用来增加信号的驱动能力的,寄存器只负责存储数据,如果要进行点灯这样的操作的话,还是需要驱动器负责增大驱动能力的。
GPIO位结构
整体结构可以分为两个部分,上面是输入部分,下面是输出部分。
输入部分
首先是这个IO引脚,这里接了两个保护二极管,这个是对输入电压进行限幅的,上面二极管接VDD,3.3V,下面二极管接VSS,0V;如果输入电压比3.3v还要高,那上方这个二极管就会导通,输入电压产生的电流就会直接流入VDD而不会流入内部电路,这样就可以避免过高的电压对内部电路产生伤害。
如果输入电压比0v还要低,这个电压是相对与VSS的电压,所以是可以有负电压的,那这时下方这个二极管就会导通,电流会从VSS直接流出来,电流会从VSS直接流出去,而不会从内部电路汲取电流,也是可以保护内部电路的。
这里连接了一个上拉电阻和一个下拉电阻,上拉电阻至VDD,下拉电阻至VSS,这个开关可以通过程序进行配置。
如果上面导通、下面断开,就是上拉输入模式;如果是下面导通、上面断开,就是下拉输入模式;如果两个都断开,就是浮空输入模式。
上拉和下拉的作用:是为了给输入提供一个默认的输入电平,因为对应一个数字的端口,输入不是高电平就是低电平;如果输入引脚哈都不接,这时输入就会处于一个浮空状态,引脚的输入电平极易受外界干扰而改变;为了避免引脚悬空导致的输入数据不稳定,我们就需要在这里加上上拉或下拉电阻。
施密特触发器的作用:是对输入电压进行整形
它的执行逻辑是:如果输入电压大于某一阈值,输出就会瞬间升为高电平,如果输入电压小于某一阈值,输出就会瞬间降为低电平。
对于施密特触发器来说,只有高于上限或者低于下限,输出才会变化
接下来经过施密特触发器整形的波形就可以直接写入输入数据寄存器了,我们再用程序读取输入数据寄存器对应某一位的数据,就可以知道端口的输入电平了。
上面还有两路线路,是连接到片上外设的一些端口;其中一个是模拟输入,这个可以连接到ADC上,因为ADC需要接受模拟量,所以这根线是接到施密特触发器前面的,另一个是复用功能输入,这个是连接到其他需要读取端口的外设上的(比如,串口的输入引脚等),这根线接受的是数字量,所以在施密特触发器后面。
输出部分
输出部分由输出数据寄存器或片上外设控制,两种控制方式通过这个数据选择器接到输出控制部分;如果选择通过输出数据寄存器进行控制,就是普通的IO口输出,写这个输出数据寄存器的某一位就可以操作对应的某个端口了。
位设置/清除寄存器,这个可以用来单独操作输出数据寄存器的某一位,而不影响其他位,因为这个输出数据寄存器同时控制16个端口,并且这个寄存器只能整体读写,所以如果想单独控制其中某一个端口而不影响其他端口的话,就需要一些特殊的操作方式。第一种方式:先读出这个寄存器,然后按位与和按位或的方式更改某一位,最后再将更改后的数据写回去,在C语言中就是&=和|=的操作,这种方式比较麻烦,效率不高,对于IO口的操作而言不太合适。第二种方式:通过位设置/位清楚寄存器,如果我们对于某一位进行置1的操作,在位设置寄存器的对应位写1即可,剩下不要操作的位写0,这样内部就会有有电路,自动将输出数据寄存器中对应位置为1,而剩下写0的位则保持不变。如果想对某一位进行清0的操作,就在位清除寄存器的对应位写1即可,这样内部电路就会把这一位清0了。第三种方式:读写STM32“位带”区域,在STM32中,专门分配的有一段地址区域,这段地址映射了RAM和外设寄存器所有的位,读写这段地址中的数据,就相当于读写映射位置的某一位。
上面是P-MOS,下面是N-MOS,这个MOS管就是一种电子开关,我们的信号来来控制开关的导通和关闭,开关负责将IO口接到VDD或者VSS,在这里可以选择推挽、开漏或关闭三种输出方式。
推挽输出模式下
这种模式下,高低电平均有较强的驱动能,所以推挽输出模式也可以叫强推输出模式,在推挽输出模式下,STM32对IO口具有绝对的控制权,高低电平都由STM32说的算。
在推挽输出模式下,P-MOS和N-MOS均有效。数据寄存器为1时,上管导通,下管断开,输出直接接到VDD,就是输出高电平。数据寄存器为0时,上管断开,下管导通,输出直接接到VSS,就是输出低电平。
在开漏输出模式下
- MOS是无效的,只有N-MOS在工作。数据寄存器为1时,下管断开,这时输出相当于断开,也就是高阻模式;数据寄存器为0时,下管导通,输出直接接到VSS,也就是输出低电平。在开漏输出模式下,只有低电平有驱动能力,高电平没有驱动能力。
这个模式的用处在于可以作为通信协议的驱动方式,比如IIC通信的引脚,就是使用开漏模式。在多机通信的情况下,这个模式可以避免各个设备的相互干扰。
开漏模式还可以用于输出5v的电平信号,比如在IO口外接一个上拉电阻到5v的电源,当输出低电平时,由内部的N-MOS直接接VSS,当输出高电平时,由外部的上拉电阻拉高至5v,这样就可输出5v的电平信号,用于兼容一些5v电平的设备,以上就是开漏输出的主要用途。
关闭状态输出方式
这个是当引脚配置为输入模式的时候,这两个MOS管都无效,也就是输出关闭,端口的电平由外部信号来控制。
GPIO模式
通过配置GPIO的端口配置寄存器,端口可以配置成以下8种模式。
浮空输入、上拉输入、下拉输入
这三个模式的电路结构基本是一样的,区别就是上拉电阻和下拉电阻的连接,它们都属于数字的输入口,特征就是,都可以读取端口的高低电平;当使用浮空输入时,端口一定要接上一个连续的驱动源,不能出现悬空状态。
这三种模式的电路结构如下,可以看到,在输入模式下,输出驱动器是断开的,端口只能输入而不能输出;上面这两个电阻可以选择位上拉工作、下拉工作或者都不工作,对应的就是上拉输入、下拉输入和浮空输入,然后输入通过施密特触发器进行波形整形后,连接到输入数据寄存器,另外这个输入保护这里写的是VDD或VDD_FT(这就是3.3v端口和容忍5v端口(它的上面保护二极管要做一下处理,要不然直接接VDD3.3v的话,外部再接入5v电压就会导致上边二极管开启,并且产生比较大的电流,这个是不太妥当的)的区别。
模拟输入(ADC模数转换器的专属配置)
这里输出是断开的,输入的施密特触发器也是关闭的无效状态,所以整个GPIO大部分都是无效的,只有下图的红色线有效,也就是从引脚直接接入片上外设,也就是ADC,所以当我们使用ADC的时候,将引脚配置位模拟输入就行了,其他时候吗,一般用不到模拟输入。
开漏输出和推挽输出
这两个电路结构也基本一样,数字输出,可以用于输出高低电平,区别就是开漏输出的高电平呈现的是高阻态,没有驱动能力,而推挽输出的高低电平都是具有驱动能力的。输出是由输出数据寄存器控制的,这个P-MOS无效就是开漏输出,如果P-MOS和N-MOS都有效,就是推挽输出;另外,在输出模式下,输入模式也是有效的(在上面电路,在输入模式下,输出无效;因为,一个端口只能有一个输出,但可以有多个输入,所以当配置成输出模式时,内部也可以顺便输入一下)。
复用开漏输出和复用推挽输出
这两模式和普通的开漏输出和推挽输出差不多,只不过是复用的输出,引脚电平是由片上外设控制的。通用的输出是没有连接的,引脚的控制权转移到了片上外设,由片上外设控制,在输入部分,片上外设也可以读取引脚的电平,同时普通的输入也是有效的,顺便接收一下电平信号。
参考手册
当使用片上外设的引脚时,可以参考这个表里给的配置。
可以看一下GPIO寄存器描述
首先是GPIO配置寄存器,每一个端口的模式由4位进行配置,16个端口就需要64位,所以这里的配置寄存器有两个,一个是端口配置低寄存器,一个是端口配置高寄存器,可以看介绍进行配置。
GPIO的输出速度可以限制输出引脚的最大翻转速度,这个设计出来,是为了低功耗和稳定性的,我们一般要求不高时一般配置成50MHz就可以了。