一、Cortex M3的GPIO口特性
    在介绍GPIO口功能前,有必要先说明一下M3的结构框图,这样能够更好理解总线结构和GPIO所处的位置。

ARM Cortex M3系列GPIO口介绍(工作方式探讨)-LMLPHP
Cortex M3结构框图
    从图中可以看出,GPIO口都是接在APB总线上的,而且M3具有两个AHB到APB桥,GPIO则直接接在AHB矩阵上,这样可以减少CPU和DMA控制器之间的竞争冲入,获得较高性能。APB总线桥配置为写缓冲区,使得CPU或DMA控制器可直接操作APB外设,而无需等待总线写操作完成。

M3数字I/O功能:
高速GPIO口,其寄存器被移到外设AHB总线,可以字节,半字和字寻址。
位电平置位和清零寄存器允许单指令置位和清零一个端口的任意位。
所有GPIO口寄存器支持M3位带操作。
整个端口值可以用一条指令写入。
GPIO口寄存器可由GPDMA控制器进行访问,可以进行DMA数据操作,使之与DMA请求同步。
单个I/O口方向可以控制。
所有I/O口在复位后默认作为上拉输入。(Why?因为微控制器连接了很多设备,如果复位后作为输出,则由于控制器电平状态不定,可能会导致外围设备产生动作,从而产生不利影响,故复位后一半都作为输入状态。)
M3可产生中断的数字端口:
PORT0 和 PORT2 端口的每个引脚都可以提供中断功能;
每个端口上的中断可被编程为上升沿、下降沿或边沿产生中断;
边沿检测是异步的,因此可以在没有时钟的情况下(例如掉电模式)操作。使用这种特性,就无需电平触发中断;
可掉电唤醒;
寄存器为软件提供挂起的上升沿中断、挂起的下降沿中断和整个挂起的 GPIO中断;
GPIO0 和 GPIO2 中断与外部中断 3 事件共用相同的 NVIC 通道。

  二、GPIO口的寄存器描述
Cortex M3引脚的寄存器描述:

ARM Cortex M3系列GPIO口介绍(工作方式探讨)-LMLPHP

PINMODEx表示引脚模式选择寄存器,在使用前要配置好。

引脚模式选择寄存器位
 
PINMODEx
功能
复位后的值
00
引脚使能上拉电阻
00
01
中继模式
10
引脚无片内上拉或下拉电阻
11
引脚使能下拉电阻

中继模式说明:当引脚处于逻辑高电平,中继模式能使能上拉电阻;当引脚处于逻辑低电平时,中继模式会使能下拉电阻,这样当引脚配置为输入且没有外部驱动时,能够保持上一个已知状态。

PINSELx:功能选择寄存器。用来设定PORT引脚的功能,当PINSELx各位为0时,才用作GPIO端口。
FIOxDIR:GPIO口方向寄存器,单独控制每个端口管脚的方向,可作为字节(8位),半字(16位)和字长(32位)的数据进行访问。
FIOxMASK:屏蔽寄存器。任何写、读的操作只在该寄存器对应位为“0“时才有效。
FIOxPIN:管脚值寄存器。只要管脚不配置为ADC,其他所有方式都可以从该位读出端口当前的实际状态。注:如果读FIOPIN寄存器,那么不管物理引脚的状态如何,在 FIOMASK寄存器中被“1”屏蔽的位将始终读出0。
FIOxSET:输出引脚的状态。写 1 使相应的端口引脚产生高电平。写 0 没有影响。读该寄存器,返回端口输出寄存器的当前内容。只可以更改 FIOMASK 中为 0 的位,即非屏蔽位。
FIOxCLR:控制输出引脚的状态。写 1 使相应的端口引脚产生低电平。写 0 没有影响。只可以更改 FIOMASK 中为 0 的位,即非屏蔽位。

  2.1  GPIO端口方向寄存器FIOxDIR(FIO0DIR??FIO4DIR- 0x2009 C000??0x2009 C080)
  当引脚被配置为 GPIO功能时,该寄存器可用来控制引脚的方向。务必根据引脚功能来设置每个引脚的方向。
注:GPIO引脚 P0.29和P0.30 与USB D+/-引脚共用,并且具有相同的方向。如果FP0DIR位29或位30在FIO0DIR寄存器中被配置为零,则P0.29 和P0.30都为输入。如果FP0DIR位29和位30被配置为1,则P0.29和P0.30都为输出。

高速GPIO端口方向寄存器位描述
 
符号
描述
复位值
31:0(字长数据)
FP0DIR
FP1DIR
FP2DIR
FP3DIR
FP4DIR
0
 
1
控制的引脚为输入引脚
 
控制的引脚为输出引脚
0

字和半字的操作基本类似,只是可以通过8位寄存器或者16位的寄存器分别控制方向而已,这里不再解释,请参看《深入浅出Cortex-M3 LPC1700》.

  2.2  GPIO端口输出设置寄存器FIOxSET(FIO0SET??FIO7SET - 0x2009 C018??0x2009 C098)
  当引脚在输出模式中被配置为 GPIO 时,该寄存器在端口引脚产生高电平输出。向该寄存器的某些位写入“1”时,对应的引脚产生高电平。写入“0”无效。如果需要引脚输出低电平或第二种功能,那么写 1 到 FIOxSET 的相应位无效。 读FIOxSET 寄存器返回该寄存器的值,该值由前一次对 FIOxSET 和 FIOxCLR(或前面提到的 FIOxPIN)的写操作确定,它不反映任何外部环境对 I/O引脚的影响。 通过 FIOxSET 寄存器访问的端口引脚受到 FIOxMASK 寄存器相应位的限制。

高速GPIO端口输出设置寄存器位描述
 
符号
描述
复位值
31:0(字长数据)
FP0SET
FP1SET
FP2SET
FP3SET
FP4SET
0
 
1
控制的引脚输出不改变         
控制的引脚输出被设为高电平
0

  2.3  GPIO端口输出清零寄存器FIOxCLR(FIO0CLR??FIO07CLR - 0x2009 C01C??0x2009 C09C)
  当引脚在输出模式中被配置为 GPIO 时,该寄存器在端口引脚产生低电平输出。向某些位写入“1”会使相应的引脚产生低电平,同时清零 FIOxSET 寄存器的相应位。写入“0”无效。如果引脚被配置为输入或其它功能,那么写 FIOxCLR 对引脚没有影响。 通过FIOxCLR寄存器访问的端口引脚受到FIOxMASK寄存器相应位的限制.

高速GPIO端口输出清零寄存器位描述
 
符号
描述
复位值
31:0(字长数据)
FP0CLR
FP1CLR
FP2CLR
FP3CLR
FP4CLR
0
 
1
控制的引脚输出不改变         
控制的引脚输出被设为低电平
0

  2.4  GPIO端口引脚值寄存器FIOxPIN(FIO0PIN??FIO7PIN- 0x2009 C014??0x2009 C094)
  该寄存器提供了端口引脚的值,可配置这些值来执行仅为数字的功能。该寄存器将给出引脚的当前逻辑值,而不管引脚是否配置为输入或输出,或作为 GPIO或作为其它可选的数字功能。
  例如,特殊的端口引脚可能具有 GPIO输入、GPIO 输出、UART 接收和 PWM 输出等可选功能。无论该引脚配置成何种功能,都可以从相应的 FIOxPIN 寄存器中读出其当前的逻辑状态。 如果引脚配置为模拟功能,当选择了模拟配置时,引脚状态不能被读出。将引脚选择用作A/D输入会断开与引脚数字部分的连接。在这种情况下,从 FIOxPIN 寄存器中读出的引脚值无效。
  写 FIOxPIN 寄存器时, FIOxPIN 寄存器的值会保存到端口输出寄存器,而无需使用 FIOxSET和 FIOxCLR寄存器来获得整个写入值。由于这种特性影响整个端口,因此在应用中时要小心。 通过 FIOxPIN 寄存器访问的端口引脚受到 FIOxMASK 寄存器相应位的限制。 只有在屏蔽寄存器中用0 屏蔽的引脚与高速 GPIO 端口引脚值寄存器的当前内容相互关联。

高速GPIO端口引脚值寄存器位描述
 
符号
描述
复位值
31:0(字长数据)
FP0VAL
FP1VAL
FP2VAL
FP3VAL
FP4VAL
0
 
1
控制的引脚输出设为低电平
控制的引脚输出设为高电平
0

  2.5  高速GPIO端口屏蔽寄存器FIOxMASK (FIO0MASK??FIO7MASK - 0x2009 C010??0x2009 C090)
  该寄存器用来屏蔽某些端口引脚,被屏蔽的引脚将无法通过 FIOxPIN、 FIOxSET 或 FIOxCLR寄存器写访问。当读FIOxPIN 寄存器时,屏蔽寄存器还将过滤相应端口的内容。
通过读或写访问,该寄存器中为“0”的位使能相应物理引脚的访问。如果该寄存器中的位为“1”,则相应位将不会通过写访问改变,并且读操作时将不会在更新的 FIOxPIN 寄存器中反映出来。

高速GPIO端口引脚值寄存器位描述
 
符号
描述
复位值
31:0(字长数据)
FP0VAL
FP1VAL
FP2VAL
FP3VAL
FP4VAL
0
 
1
控制的引脚输出设为低电平
控制的引脚输出设为高电平
0

  对于常见的ARM处理器,它们的GPIO口基本上可以配置为输入模式、输出模式、开漏或推挽模式,对于新唐的M0来说,所有I/O都处于准双端模式;对于NXP的M3处理器来说,GPIO可以配置为上拉、下拉、开漏或者中继模式

  开漏输出与推挽输出的区别:
  推挽输出:推挽结构一般是指两个三极管分别受两互补信号的控制,总是在一个三极管导通的时候另一个截止。可以输出高,低电平,连接数字器件,正常的拉出/灌入电流为4mA,短时间极限值可以达到40mA,但不是每个引脚都能输出这么多
  开漏输出:输出端相当于三极管的集电极。要得到高电平状态需要上拉电阻才行。适合于做电流型的驱动,其吸收电流的能力相对强(一般20mA以内).
 
  开漏电路概念中提到的“漏”就是指MOS FET的漏极。同理,开集电路中的“集”就是指三极管的集电极。开漏电路就是指以MOS FET的漏极为输出的电路。一般的用法是会在漏极外部的电路添加上拉电阻。完整的开漏电路应该由开漏器件和开漏上拉电阻组成。
  组成开漏形式的电路有以下几个特点:
  1. 利用外部电路的驱动能力,减少IC内部的驱动。当IC内部MOSFET导通时,驱动电流是从外部的VCC流经R pull-up,MOSFET到GNDIC内部仅需很小的栅极驱动电流。如图1。
  2. 可以将多个开漏输出的Pin,连接到一条线上。形成 “与逻辑” 关系。如图,当PIN_A、PIN_B、PIN_C任意一个变低后,开漏线上的逻辑就为0了。这也是I2C,SMBus等总线判断总线占用状态的原理。
  3. 可以利用改变上拉电源的电压,改变传输电平。IC的逻辑电平由电源Vcc1决定,而输出高电平则由Vcc2决定。这样我们就可以用低电平逻辑控制输出高电平逻辑了。
  4. 开漏Pin不连接外部的上拉电阻,则只能输出低电平(因此对于经典的51单片机的P0口而言,要想做输入输出功能必须加外部上拉电阻,否则无法输出高电平逻辑)。
ARM Cortex M3系列GPIO口介绍(工作方式探讨)-LMLPHP
问题集锦
一、准双向IO结构的特点是 
1 输出结构类似 OC门,输出低电平时,内部NMOS导通,驱动能力较强(800uA);输出高电平靠内部上拉电阻,驱动能力弱(60uA)。
2 永远有内部电阻上拉,高电平输出电流能力很弱,所以即使IO口长时间短路到地也不会损坏IO口(同理,IO口低电平输出能力较强,作低电平输出时不能长时间短路到VCC)
3 作输入时,因为OC门有"线与"特性,必须把IO口设为高电平(所以按键多为共地接法)
4 作输出时,输出低电平可以推动LED(也是很弱的),输出高电平通常需要外接缓冲电路(所以LED多为共阳接法)
5 软件模拟 OC结构的总线反而比较方便-----例如 IIC总线
* OC门:三极管的叫集电极开路,场效应管的叫漏极开路,简称开漏输出。具备"线与"能力,有0得0。
* 为什么设计成输出时高电平弱,低电平强----是考虑了当年流行的TTL器件输入
 
二、IO不同模式的区别?
简单的说:
“准双向IO口”在读前必须先用写指令置"1",才能读入;写则无须此步.
“真正的双向IO口”可直接读写.
“三态IO口”有高,低电平,高阻状态,高阻本人理解:相当此脚与内部电路断开.
04-30 01:09