微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > LPC1114通用输入/输出端口(GPIO)

LPC1114通用输入/输出端口(GPIO)

时间:11-13 来源:互联网 点击:
在前面的示例中,已经用到了LPC1114GPIO端口。GPIO端口是CPU与外部设备打交道的基础,为了更好地运用好它,下面将对LPC1114的通用输入输出端口(GPIO)的寄存器结构及用法做详细深入地讨论。

在第一节中已经介绍过,LPC1114处理器是一个32位结构的处理器,但它的GPIO端口没有把32根引脚都接出来,而是每组只接出来12根引脚(注意,第四组只接出来6根引脚),共有4组,一共42根引脚。它们都具有如下特点:

1.可通过软件配置GPIO引脚为输入或输出
2.每个独立的端口引脚均可作为外部中断的输入引脚(边沿或电平触发)
3.边沿触发中断可配置为上升沿触发、下降沿触发以及双边沿触发
4.电平触发中断引脚可以配置为高电平或低电平触发
5.所有GPIO引脚默认情况下均为输入
6.从端口读取和写入数据操作可以通过地址位13:2屏蔽

端口的具体使用配置会在后面一一进行讨论,这里先来看一下“通用输入/输出端口GPIO”的结构体是如何定义的,代码如下。
typedef struct

{

union {

__IO uint32_t MASKED_ACCESS[4096];/*!< Offset: 0x0000 to 0x3FFC Port data Register for pins PIOn_0 to PIOn_11 (R/W) */

struct {

uint32_t RESERVED0[4095];

__IO uint32_t DATA;/*!< Offset: 0x3FFC Port data Register (R/W) */

};

};

uint32_t RESERVED1[4096];

__IO uint32_t DIR;/*!< Offset: 0x8000 Data direction Register (R/W) */

__IO uint32_t IS;/*!< Offset: 0x8004 Interrupt sense Register (R/W) */

__IO uint32_t IBE;/*!< Offset: 0x8008 Interrupt both edges Register (R/W) */

__IO uint32_t IEV;/*!< Offset: 0x800C Interrupt event Register(R/W) */

__IO uint32_t IE;/*!< Offset: 0x8010 Interrupt mask Register (R/W) */

__I uint32_t RIS;/*!< Offset: 0x8014 Raw interrupt status Register (R/ ) */

__I uint32_t MIS;/*!< Offset: 0x8018 Masked interrupt status Register (R/ ) */

__O uint32_t IC;/*!< Offset: 0x801C Interrupt clear Register (R/W) */

} LPC_GPIO_TypeDef;

上述代码对LPC1114的GPIO端口的进行了结构体定义,由于GPIO位于内存地图中的AHB部分,所以从代码中可以看出,同前面讨论的结构体一样,它定义的成员变量利用偏移地址与AHB中的GPIO寄存器进行了对映。特殊的地方在于多了一个关于union的定义,要弄清这个定义,还必须回到AHB模块部分的寄存器描述中去。下图就给出了AHB模块内GPIO部分的寄存器分布情况。

对应上图与结构体中的内容可以看出,除了GPIODATA以外,其它寄存器与结构体成员的对映关系与前面讨论的SYSCON的一样。但对于GPIODATA就不能用前面的方法来分析了。下面就着重来讨论一下GPIODATA寄存器与其结构体成员之间是如何进行对映的。

GPIODATA寄存器是GPIO的数据寄存器,它存放的数据直接被输出到GPIO的引脚上,引脚输入的数据也会被放到该寄存器中。所以要对端口进行电平控制(无论是输入还是输出),就要对GPIODATA寄存器进行操作。同样,GPIODATA寄存器也是一个32位的结构,其地址占用4个字节。而GPIO端口只有12个引脚,因此GPIODATA寄存器只用了低12位来对映GPIO端口引脚。

从上图中还可以看出,GPIODATA寄存器的偏移地址是从0x0000~0x3FFC。最高地址是0x3FFC是因为,每个GPIODATA寄存器单元占用4 字节,所以共有0x3FFC/4=0xFFF个(即4095个)GPIODATA寄存器单元,因为地址是从第0个单元算起的,所以总共有4096个单元。而2的12次方刚好就等4096,所以它刚好可以表征12个引脚的容量。由此可以看出,每个引脚电平的值(无论是输入还是输出)都可以在GPIODATA寄存器中找到一个对映的单元(因为有4096个引脚状态就有4096个GPIODATA地址单元)。这样做是为什么呢?为什么不把端口引脚统一用一个端口寄存器来描述(姑且称为“方法一”),写(或读)这个端口寄存器不就行了?其实,其它大部分单片机也确实是这样做的。而这里LPC1114却要花费4096个地址单元来把引脚状态全部描述一遍(姑且称为“方法二”),也肯定是有它的理由的。其实,应该说LPC1114是两种方法都包含的(因为严格来说,“方法一”包含于“方法二”)。至于“方法二”的优点,其实就是可以在不改变其它引脚状态下,单独改变某一引脚上的电平。按理说,通过“与或”的逻辑操作方式,也可以让“方法一”实现这一功能(其它单片机也是这样做的),但它必须通过“读——修改——写”的步骤来实现。比如要实现仅对P0端口的第7个引脚输出高电平,程序可写为“P0 |= 1

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top