关于 GPIO 的输入输出模式的选择,是理解和使用好 GPIO 的关键。这次嵌入式系统实验课程使用的 Tiva C Series TM4C123G LaunchPad Evaluation Board 采用 TI 公司的 TM4C123GH6PM Microcontroller。相较而言,STM32 显得更加优雅简洁。anyway,GPIO 的几种输入输出模式核心技术大同小异,因此我们选用 STM32 作为载体来阐述这个问题,包括几种输入输出模式内部的硬件实现细节以及它们各自适用范畴。
为什么必须先配置时钟再配置 GPIO?
- 所有寄存器都需要时钟才能配置:因为寄存器是由D触发器组成的,只有送来了时钟,触发器才能被改写值。
- 任何 MCU 的任何外设都需要有时钟,8051 也是如此;STM32/TM4C123G 为了让用户更好地掌握功耗,对每个外设的时钟都设置了开关(Clock Gating 时钟门控),让用户可以精确地控制,关闭不需要的设备,达到节省供电的目的;51 单片机不用配置 IO时钟,只是因为默认使用同一个时钟,这样是方便,但是这样的话功耗就降低不了。
- ARM 的芯片都是这样,外设通常都是给了时钟后,才能设置它的寄存器(即才能使用这个外设),这么做的目的是为了省电,低功耗,使用了所谓时钟门控的技术。
GPIO 常见的四种输入模式
- 最右端为 I/O 管脚,左端的器件位于芯片内部。I/O 引脚并联了两个用于保护的二极管 ,可以防止外部电流倒灌;
- 两个保护二极管进来,接下来就遇到了两个开关和两个电阻,与 $V_{DD}$ 相连的为上拉电阻,与 $V_{SS}$ 相连的为下拉电阻;
- 再连接到 TTL 施密特触发器就把电压信号转化为 0、1 的数字信号存储在输入数据寄存器 (IDR);
- STM32/TM4C123G 上有很多 I/O 口,也有很多的内置外设(片上外设),像 I2C,ISP,USART等,为了节省引出管脚,这些内置外设基本上是与 I/O 口共用管脚的,也就是 I/O 管脚的复用功能。
- ADC 模拟输入管脚也建议用作 DAC 的模拟输出管脚。
我们可以通过设置配置寄存器(CRL、CRH)来控制这两个开关,于是就可以得到 GPIO 的上拉输入模式 (GPIO_Mode_IPU
)、浮空输入模式 (GPIO_Mode_FLOATING
) 和下拉输入模式 (GPIO_Mode_IPD
) 了。
上拉输入
- 从上面结构我们可以理解:GPIO 引脚配置为上拉输入模式,在默认状态下(GPIO 引脚无输入),读取得的 GPIO 引脚数据为 1,高电平;
- 上拉输入默认是高电平,外接低电平有影响,故只能用来检测外接低电平。
浮空输入
- 浮空输入模式在芯片内部既没有接上拉电阻,也没有接下拉电阻,经由 TTL 触发器输入;
- 配置成这个模式直接用电压表测量其引脚电压为 1 点几伏,这是个不确定值(高、低电平都有可能);可以用来检测外接是高电平,还是低电平;
- 浮空输入模式其输入阻抗较大,一般把这种模式用于标准的通信协议如 $I^2C$、$USART$ 的接收端,作为复用功能输入传送到片上外设模块。
下拉输入
- 下拉输入模式与上拉输入模式相反,在默认状态下其引脚数据为 0,低电平,故只能用来检测外接高电平。
模拟输入
- 模拟输入模式则关闭了 TTL 触发器,不接上、下拉电阻,经由另一线路把电压信号传送到采用模拟输入的片上外设模块(如传送至 ADC 模块,由 ADC 采集电压信号,所以使用 ADC 外设的时候,必须设置为模拟输入模式);
- 不管外接是高电平还是低电平,始终是检测到低电平 0,本质上已经没意义了;
- 此外,当 GPIO 管脚与 DAC 等片上外设模块的模拟输出相连时,为了避免寄生的干扰和额外的功耗,也应该将管脚设置成模拟输入模式。
结构图的下半部分为输出模式结构,分为 推挽输出模式、开漏输出模式、复用推挽输出模式 和 复用开漏输出模式;线路经过一个由 P-MOS 管和 N-MOS 管组成的输出控制电路。
GPIO 常见的四种输出模式
开漏输出
- 在开漏输出模式时,如果我们控制输出为 0,低电平,则使 N-MOS 管导通,使输出接地,若控制输出为 1 ,则既不输出高电平,也不输出低电平,为高阻态(高阻态就是电阻很大,或者说是趋向无穷大,用来隔开相当于断开但又不是真的断开);
- 右边为开漏输出形式 (Open Collector Outout),需要接上拉电阻:
- 控制输出为 0,低电平,N-MOS 管导通,输出 Out 接地;
- 控制输出为 1,高阻态,输出 Out 的电压为外部上拉电阻所接电源的电压$V_{S+}$。
- 开漏输出模式的输出端相当于三极管的集电极,要得到高电平状态需要上拉电阻才行,适合于做电流型的驱动,其吸收电流的能力相对强(一般 20mA 以内)。
开漏形式的电路有以下几个特点:
+ 一般来说,开漏是用来连接不同电平的器件,匹配电平用的,因为开漏引脚不连接外部的上拉电阻时,只能输出低电平,如果需要同时具备输出高电平的功能,则需要接上拉电阻,很好的一个优点是通过改变上拉电源的电压,便可以改变传输电平:比如加上上拉电阻就可以提供 TTL/CMOS 电平输出等;
+ 开漏输出提供了灵活的输出方式,但是也有其弱点,就是带来上升沿的延时。因为上升沿是通过外接上拉无源电阻对负载充电,所以当电阻选择小时延时就小,但功耗大;反之延时大功耗小。因此上拉电阻的阻值决定了逻辑电平转换的速度,阻值越大,速度越低功耗越小,所以负载电阻的选择要兼顾功耗和速度,所以如果对延时有要求,则建议用下降沿输出;
+ 开漏输出模式的输出端利用外部电路的驱动能力,减少 IC 内部的驱动。当 IC 内部 MOSFET 导通时,驱动电流是从外部的 $V_{S+}$ 流经上拉电阻、MOSFET 到 GND,IC 内部仅需很小的栅极驱动电流; - 可以将多个开漏输出连接到一起,通过一只上拉电阻,在不增加任何器件的情况下,形成 “与逻辑” 关系,即 “线与”。因为只有当所有引脚都输出高阻态,才由上拉电阻提供高电平,此高电平的电压为外部上拉电阻所接电源的电压。若其中一个引脚为低电平,那线路就相当于短路接地,使得整条线路都为低电平,0 伏。
- 开漏输出模式中,输入模式结构中的 TTL 触发器处于开启状态,这意味着 CPU 可以在 “输入数据寄存器” 的另一端,随时监控 I/O 端口的状态:默认状态是高电平,能够实现正常检测低电平;通过这个特性,可以实现虚拟的 I/O 端口双向通信:假如 CPU 输出逻辑 “1” 由于③的 N-MOS 管处于关闭状态,I/O 端口的电平将完全由外部电路决定,因此,CPU 可以在 “输入数据寄存器” 读到外部电路的信号,而不是它自己输出的逻辑 “1”,不过建议还是不要把输出模式用作输入检测。
推挽输出
- 推挽输出模式 (Push-Pull Output) 在输出高电平时,N-MOS 管导通(使输出接地) ;输出低电平时,P-MOS 管导通(输出高电平),两个管子轮流导通,一个负责灌电流,一个负责拉电流。推挽输出的低电平为 0 伏,高电平为 $V_{DD} = 3.3$ 伏;
- 推挽电路是两个参数相同的三极管或 MOSFET,以推挽方式存在于电路中,各负责正负半周的波形放大任务,电路工作时,两只对称的MOSFET 每次只有一个导通,所以导通损耗小、效率高;
- 输出既可以向负载灌电流,也可以从负载抽取电流,推拉式输出既提高电路的负载能力,又提高开关速度。
- 推挽输出模式默认输出低电平,另外,必须配置引脚输出速率,否则会导致输出紊乱;
- 与开漏输出模式类似,推挽输出模式中输入模式结构中的 TTL 触发器也处于开启状态,默认输出低电平,能够实现正常检测高电平,不过建议还是不要把输出模式用作输入检测。
复用开漏输出
- 复用开漏输出模式与开漏输出模式的工作原理基本相同,不同的是②的输入源不同,它是和复用功能输出,即片上外设模块的输出端相连。
复用推挽输出
- 复用推挽输出模式与普通推挽输出模式的区别与复用开漏输出模式相同;
- 此外,将 GPIO 配置成复用输出功能后,假如相应的外设模块没有被激活,那么此时 IO 端口的输出将不确定!
TM4C123G vs STM32
TI 的 TM4C123G 中有关 GPIO 输入输出模式的设计则相对简单,也没 STM32 那么优雅!
- 也是 AD 分开,有一个 Analog Circuitry 模块,直接负责管脚的模拟输入输出 (AIN/AOUT),通过寄存器
GPIOAMSEL
使能模拟电路; - 数字部分中,同样存在 Periph 0…n 等片上外设模块:
- 通过
GPIOAFSEL
、GPIOPCTL
等寄存器控制 Alternate Output Enable、GPIO Output Enable 信号进而控制 Pad Output Enable 使能信号(基本都是通过 MUX 多路复用模块实现),决定管脚作为普通 GPIO 还是复用功能引脚; GPIODIR
寄存器控制管脚的输入输出方向;- 此外,TM4C123G 的 GPIO 输入输出模式可以进行一些配置,以满足某些具体应用场景(如 I2C、USART 等):
GPIOPUR
、GPIOPDR
寄存器控制输入管脚是否采用上拉输入、下拉输入?(我猜默认,而且大多数应用是采用浮空输入);GPIOODR
是否采用开漏输出?(我猜默认,而且大多数应用是采用推挽输出)。
- 通过