(韦东山——嵌入式Linux 应用开发完全手册)
1、S3C2440 GPIO 简介
S3C2440共有130个多功能输入/输出端口,分为9组,GPA ~ GPJ,通过设置寄存器来确定某个引脚用于输入、输出还是其他特殊功能。
具体如下:
GPA:25个输出端口;
GPB:11个输入/输出端口;
GPC:16个输入/输出端口;
GED:16个输入/输出端口;
GFE:16个输入/输出端口;
GPF:8个输入/输出端口;
GPG:16个输入/输出端口;
GPH:9个输入/输出端口;
GPJ:13个输入/输出端口;
控制S3C2440的GPIO端口的寄存器有3类,分别是GPxCON、GPxDAT、GPxUP (x=A ~ J);
GPxCON:GPIO控制寄存器,可以设置选定GPIO口的输入输出方式和功能。GPA组的25个端口比较特殊,只能是输出方式。GPACON的每一位对应一个引脚,当某位为0时,对应引脚为输出端口;当某位被设为1时,相应引脚为地址线或用于地址控制,此时GPADAT无用,一般而言GPACON通常被设为1 ,以便访问外部存储器件。
GPB ~ GPJ端口的GPxCON寄存器使用方法一致,每两位控制一个引脚,00时为输入I/O口,01时为输出I/O口,10时为复用功能,11保留。
GPxDAT:此引脚用于读写引脚的状态,即端口数据。当引脚配置为输出时,给该寄存器某位写1,则对应引脚输出高电平,写0输出低电平。当引脚配置为输出时,读该寄存器可以得到端口电平状态。
GPxUP:该寄存器可以设置引脚是否使用上拉电阻,某位为0时对应引脚使用上拉电阻,某位为1时不使用上拉电阻。注意:GPA组没有GPxUP寄存器,即没有上拉电阻。
2、通过软件对GPIO设置:
#define GPBCON (*(volatile unsigned long *)0x56000010)
/* 0x56000010:为S342440的GPBCON地址 */
#define GPBDAT (*(volatile unsigned long *)0x56000014)
/*0x56000014:为S342440的GPBDAT地址*/
#define GPB_OUT (1<<(2*5))
/*此处为设置GPBCON对应第五位引脚的值其值为01----对应GPBCON展开值为0000010000000000*/
GPBCON = GPB_OUT; //设置GPB5为输出
GPBDAT &= ~(1<<5); //向GPB5输出低电平
【注意】 #define GPBCON (*(volatile unsigned long *)0x56000010) 解释
1、关于volatile 关键字的理解,前面转载有解释,总的来说就是volatile 变量可变,防止编译器对它进行优化,访问数据任何时候都会直接访问该地址处的内容(通过cache提高访问速度的优化被取消 )。
2、分步解释
a、0x56000010 表示一个常量
b、( volatile unsigned long * )0x56000010 表示将0x56000010 这个常量强制转换成一个无符号长整型的指针,也即相当于 p。
volatile 表明这个指针指向的内容是易变的。
c、*(volatile unsigned long *)0x56000010 相当于 *p, 为指针变量,取p指向的值。
设置GPIO寄存器技巧:
1,设置控制位GPxCON寄存器的控制:
从引脚读数据 将GPxCON设置为输入:
#define GPFx_in ~(3<<(x*2))
【注释:将GPF端口的第X位设置为输入】 ,
前面说到的寄存器的输入输出控制中:
【PORTB~PORTH/J对寄存器操作完全相同,GPXCON每2位对应一个引脚:
00--输入。 01--输出。10--特殊功能。11--保留不用。】
3对应的二进制是11,将3先移位到 要操作的对应位,取反就成了00。
按此思路,如果要将相应的GPxCON设置为输出位,
只需将“01”左移即可:
#define GPGx_out (1<<(x*2))
2,对数据寄存器GPxDAT的控制:
回顾前面对GPxDAT的说明:
【一句话:GPxDAT是用来读写端口数据的。写数据的时候,直接将要写的值赋给GPxDAT即可。要读数据时,先将寄存器置高,然后再读。】
只对寄存器第x位赋0,其余值不变 : GPBDAT &=~(1< 只对寄存器第x位赋1,其余值不变 : GPBDAT |=(1< 位与清零,位或置1。