在做 MCU 编程开发的时候,GPIO 可以说是最基础也是最重要的部分,MCU 的学习研究无非就是三点:高低电频,输入输出,通讯协议。而GPIO可以说贯穿始终,在模拟一些通讯协议时,GPIO 所采用的模式错误,往往会引起各种意想不到的问题。

对于不同的计算机体系结构,设备可能是端口映射,也可能是内存映射的。如果系统结构支持独立的 IO 地址空间,并且是端口映射,就必须使用汇编语言完成实际对设备的控制,因为 C 语言并没有提供真正的“端口”的概念。如果是内存映射,那就方便的多了。比如像寄存器A(地址假定为0x48000000)写入数据0x01,那么就可以这样设置了,#define A (*(volatile unsigned long *)0x48000000) A = 0x01;这种通过宏定义某个存储空间,然后对该空间写入数据的过程是最为常见的。

GPIO 模式:

不同的 MCU 会提供不同的模式选择,一般 GPIO 的模式无外乎以下几种:推挽输出,开漏输出,浮空输入,上拉/下拉输入,模拟口,复用功能等等。

而实际使用中,

通用推挽输出(push-pull):

在功率放大器电路中大量采用推挽放大器电路,这种电路中用两只三极管构成一级放大器电路,两只三极管分别放大输入信号的正半周和负半周,即用一只三极管放大信号的正半周,用另一只三极管放大信号的负半周,两只三极管输出的半周信号在放大器负载上合并后得到一个完整周期的输出信号。原理图如下:

推挽放大器电路中,一只三极管工作在导通、放大状态时,另一只三极管处于截止状态,当输入信号变化到另一个半周后,原先导通、放大的三极管进入截止,而原先截止的三极管进入导通、放大状态,两只三极管在不断地交替导通放大和截止变化,所以称为推挽放大器

这种电路主要用于低功耗情况下能输出较大功率的交流信号,通常用于低频放大电路设计中。可增强输出的负载能力。这种输出结构带负载能力较强,你驱动个LED灯什么的操作IO口可以用推挽输出。

开漏输出(open drain):

输出端相当于三极管的集电极. 要得到高电平状态需要上拉电阻才行。原理图如下:

开漏输出只有外部有上拉电阻时,才有可能输出高电平。当外部无上拉电阻时,该口不能输出高电平,处于悬空状态,或只可以输出低电平。开漏的主要用处:

  • 芯片的 Open drain 输出是设计用于”线或” (wire AND) 逻辑的,就是说当多个漏极开路器件的输出连在一起的时候,只要是其中一个导通,输出就为‘0’。这个特性被广泛用于串行总线电路。
  • 可以用于如继电器之类只吸入电流的负载, 或驱动比你的芯片电源电压高的负载,吸电流能力较强,但是输出能力不如推挽输出较弱,(一般如果单一驱动的话,大都选用推挽输出。)
  • 对于一些需要防止干扰的操作,如:不希望单片机的上拉电阻对外部电路(如ADC)产生任何影响。

open-drain 是漏极开路输出的意思,相当于集电极开路(open-collector)输出,即 ttl 中的集电极开路(oc)输出。一般用于线或、线与,也有的用于电流驱动。open-drain 是对 mos 管而言,open-collector 是对双极型管而言,在用法上没啥区别。OC 门的输出就是开漏输出;OD(open-collector) 门的输出也是开漏输出(实际是开集)。TTL 电路有集电极开路 OC 门,MOS 管也有和集电极对应的漏极开路的 OD 门,它的输出就叫做开漏输出。它可以吸收很大的电流,但是不能向外输出电流。所以,为了能输入和输出电流,它使用的时候要跟电源和上拉电阻一齐用。因此在 MCU 中我们就用开漏来表示本身无上拉能力,高阻抗的这种功能。

上拉/下拉输入

上拉就是输入高电平,然后接一个上拉电阻(起保护作用),需要知道上拉就表示该端口在默认情况下输入为高电平;同理,下拉就是默认情况输入低电平。

这边上下拉比较好理解,而且一般的单片机都可以配置成这种功能,有关上下拉,可能一些人不会太在意,认为并不会有多大影响,但是一个稳定的产品配置上下拉很重要,而且,如果你需要考虑功能的话,那就更加需要注意这点。

复用功能

新款的 MCU 中为了实现某些特殊的功能,如 uart,I2C 通讯等,加入了复用功能这种 IO 模式,GPIO 需要使用复用功能,然后配置相关的寄存器才可以开启这些功能,但是,也并不绝对,一些 MCU 即便使用其他模式,开启相关功能后,仍然是可以使用这些特殊功能的。

但需要注意的是,个人认为 MCU 采用复用功能的模式,是为了安全,防止你错误的配置 GPIO 口,然后可能会导致 IO 口烧坏,所以如果你对相关功能需要的 GPIO 状态不是太熟悉的话,如果需要使用 MCU 寄存器来配置 GPIO 口,则最好按照规定将 GPIO 口配置为复用功能。

这边关于通讯协议就不另外展开叙述,详细可以参考一些案例,尤其是需要模拟通讯协议输出时,一定要以芯片手册为准,部分网上流传的例程可能 IO 口配置是错误的,短时间没有问题,但不利于长久使用。

参考链接:
https://wenku.baidu.com/view/50417ea6f524ccbff121845c.html
http://blog.csdn.net/ybhuangfugui/article/details/52953533
http://blog.csdn.net/kevinhg/article/details/17490273
http://www.openedv.com/forum.php?mod=viewthread&tid=2288&highlight=%CD%C6%CD%EC%2B%BF%AA%C2%A9
http://www.openedv.com/forum.php?mod=viewthread&tid=67623&highlight=%CD%C6%CD%EC%2B%BF%AA%C2%A9
http://jingyan.baidu.com/article/5225f26b047a5ee6fa0908f6.html
http://zhidao.baidu.com/link?url=ZnvwHHE10-0UZ8hPRvLczpw7-qZolpNolBuT0TsGZHEjDMxmZeYz5QsOYUybxc7OBMSiPOfZx_401s5KlEIQKcrUZPqSaOTMX4yrEgfsbX3
http://blog.chinaunix.net/uid-23065002-id-3885199.html
http://wenku.baidu.com/link?url=9BSyigTdzjcZ73LWkfGOhzfxyD1oDhVHMS0ykLUG1sMp9lUbY9yGhL2hsqIKPaX47fdcfDwRxLnfu46m_Z4y0_HGE6XPk_8VSpE38ztCFIe
http://www.9mcu.com/9mcubbs/forum.php?mod=viewthread&tid=951093
https://wenku.baidu.com/view/131592ba1a37f111f1855b79