历史上的今天
今天是:2025年01月14日(星期二)
2021年01月14日 | NXP LPC1100 GPIO 端口操作
2021-01-14 来源:eefocus
LPC1100的GPIO端口被映射到从0x5000,0000到0x5003,FFFF的地址空间中,共有4个端口,每个端口占用64K字节的空间。详见下表:
端口0:0x5000,0000 - 0x5000,FFFF
端口1:0x5001,0000 - 0x5001,FFFF
端口2:0x5002,0000 - 0x5002,FFFF
端口3:0x5003,0000 - 0x5003,FFFF
在LPC1100用户手册上,是这么描述如何对端口进行读写操作的:“In order for software to be able to set GPIO bits without affecting any other pins in a single write operation, bits [13:2] of a 14-bit wide address bus are used to create a 12-bit wide mask for write and read operations on the 12 GPIO pins for each port. Only GPIOnDATA bits masked by 1 are affected by read and write operations. The masked GPIOnDATA register can be located anywhere between address offsets 0x0000 to 0x3FFC in the GPIOn address space. Reading and writing to the GPIOnDATA register at address 0x3FFC sets all masking bits to 1.”
翻译过来就是:“为了让软件能够在进行端口引脚写操作的时候,只写端口上的某些引脚而不会影响其他引脚,要用14位地址(这个地址指的是以每个端口的起始地址为基地址的偏移地址)中的2-13位来作为屏蔽,只有GPIOnDATA寄存器中被1屏蔽住的位才会在读写操作中起作用,被屏蔽的GPIOnDATA寄存器可以被定位到从地址0x0000到0x3FFC的任何地方。在地址0x3FFC处对GPIOnDATA寄存器的读写,会使所有的屏蔽位都置1。”
这段话让人读起来真是一头雾水。其实它的意思是说,从0x0000到0x3FFC的所有地址,都对应着同一个端口,对这个范围内的不同地址的读写,就是访问这个端口的不同的引脚。如果要读写某些特定的引脚,只要对特定的地址进行读写就行。那么怎么才能知道特定引脚的地址是多少呢?就是,用一个14位的二进制数,bit2代表引脚0,bit3代表引脚1......以此类推(bit0,bit1设置为0),如果你想读写某个引脚,则把这个二进制数对应的位设置成1,不想读写就置0,这个二进制数,再加上端口的基地址,就是我们需要的地址。而所写入的数据,则是一个12位的二进制数,bit0就代表引脚0,bit1代表引脚1。。。例如:
我们要对PIO2_0和PIO2_1置1,则地址就是0x5002,0000(端口2的基地址) + 0x0C = 0x5002,000C,要写入的数据是0x03。代码就是:*(0x5002,000C)=0x03;
而如果对地址0x3FFC进行读写,0x3FFC的二进制表示是 11,1111,1111,1100,12个管脚对应的位都是1,就相当于读写整个端口。
在MDK开发环境中,GPIO端口是这样定义的:
typedef struct
{
union {
__IO uint32_t MASKED_ACCESS[4096];
struct {
uint32_t RESERVED0[4095];
__IO uint32_t DATA;
};
};
uint32_t RESERVED1[4096];
__IO uint32_t DIR;
__IO uint32_t IS;
__IO uint32_t IBE;
__IO uint32_t IEV;
__IO uint32_t IE;
__IO uint32_t RIS;
__IO uint32_t MIS;
__IO uint32_t IC;
} LPC_GPIO_TypeDef;
在这个结构中,首先定义了有4096个元素的32位数组,这其实是用数组来代替地址指针。MASKED_ACCESS[0]的偏移地址是0,MASKED_ACCESS[1]的偏移地址是4,MASKED_ACCESS[4095]的偏移地址正好就是0x3FFC,所以,这个结构中的内部联合里面,DATA成员的地址就是数组元素4095的偏移地址,恰恰就是整个端口的访问地址。
因为上面结构的巧妙定义,GPIO的读写就变的更加简单易懂。读写引脚0,就是对MASKED_ACCESS[1]进行读写;引脚1,就是对MASKED_ACCESS[2]读写;引脚3,是对MASKED_ACCESS[4];而要读写引脚0和1,就对MASKED_ACCESS[3]读写。引脚与数组序号的对应关系,与前述类似,只不过因为每个数组元素都是32位的,共4个字节,占用了4个地址,所以引脚0就直接对应了bit0, 引脚1对应bit1, 以此类推生成的数据就是数组元素的序号。例如,要对PIO2_0和PIO2_1置1,程序就是:
MASKED_ACCESS[3] = 0x03;
另:MDK4.12, 4.13a在进行纯软件仿真的时候,对GPIO端口的操作结果会不正确。不知道是软件问题还是我的设置不对。
史海拾趣
|
我的程序跑在ARM机上、WINCE4.0,对方程序跑在POWER PC的VxWorks下,ARM机为数据接收方,POWER PC为数据发送方。双方COM口设置相同。进行数据传输时,有时正确,有时错误。具体情况是,根据双方定好的通信协议,先交换简单的指令,每次二十几个字节 ...… 查看全部问答> |
|
刚接触32位的单片机,实习公司里面用的瑞萨的单片机,看宣传资料上说瑞萨现在是世界上生产单片机最多的企业,已经超过摩托罗拉。不知瑞萨的单片机市场上应用得多不多,学了这个单片机有没有用?瑞萨的32位supperH是不是用ARM的内核呢?请达人指点! ...… 查看全部问答> |
|
#include<reg52.h>#include<intrins.h>//循环左移头文件#define uint unsigned int#define uchar unsigned charuchar temp;void delay(uint); void main(){ temp=0xfe; P1=temp; while(1) { ...… 查看全部问答> |
|
打算买6472的EVM回来做实验,不过不知道如何操作 希望有经验的不吝赐教 那些个什么TI的代理商,真TM不给力,打了几遍电话,都给忽视了,以后再也不TM找他们了… 查看全部问答> |
|
我使用RLINK烧录STM8S207MB: 第一次烧录(STVP)时,程序运行正常; 然后修改一个程序参数(绝对不会影响烧录), 再次烧录: 在烧程序代码部分(PROGRAM MEMORY)时正常, 而在烧录选项字节时,出现" ERROR ON OPTION BYTES(COMPLEMENTARY BYTES, R ...… 查看全部问答> |
|
最近在做一个项目,采用UCOS II +UCFS +UCGUI的基本架构,在ARM平台上运行,以一片K9F1G08为存储器,一片K4S561632为内存。遇到一个问题:创建目录、文件,删除文件以及格式化行为都是正常的,但不能删除目录。分析来看,创建目录和删除目录在前期 ...… 查看全部问答> |
|
基于UC3842的DC_DC升压电路,输入12V,输出20~24V可调,当不接负载电阻时电压可调范围较大,一接入负载电阻(20Ω)电源电压被拉低至2.2V,并且不在可调,当移除负载又恢复原来的情况,这是怎么回事?… 查看全部问答> |




