S3C2440-GPIO口的学习与总结

来源:互联网 发布:手机号段归属地数据库 编辑:程序博客网 时间:2024/05/15 06:38
1         简介
1.1       IO的操作主要包括两个方面:
1. 设置引脚的功能(输入、输出、特殊功能);
2. 为引脚赋值、读数据或其他功能。
1.2       难点:
由于此ARM9不能对位进行操作(至少我目前没有发现类似51中的sbit功能的符号),所以我们必须准确的找到相应的位,相关内容会在后文重点论述。
1.3       IO口数量及特殊功能:
S3C2440-GPIO口的学习与总结 - SCE - ARM_UCLINUX
各IO口的特殊功能,请参考S3C2440的datasheet.
2         寄存器(以GPIOB为参考)
2.1       GPBCON
此寄存器用于配置B口 的功能,例如第5口(LED1口)的配置情况如下:
S3C2440-GPIO口的学习与总结 - SCE - ARM_UCLINUX
我们可以通过设置GPBCON的第[11:10]为01,使GPB5口为输出口。
初始状态:0x0.
2.2       GPBDAT
此寄存器可以输出数据也可以读数据。
2.3       GPBUP
此寄存器控制相关的引脚是否加上拉电阻(默认加)。
置1表示不加上拉电阻。
初始状态:0x0.
NOTE: 这些寄存器理解起来还是比较简单的,但因为无法直接对位进行操作,控制起来比不简单。
3         相关操作函数
在此之前,先介绍如何对寄存器特定位进行置1、置0操作。
一般一个寄存器都含有4个字节即32个位。寄存器的定义如下:
#define rGPBCON    (*(volatile unsigned *)0x56000010) //Port B control
首先,理解一下这个语句。在一般情况下,我们定义pointer:
unsigned int *a; 即a是指向unsigned int类型数据的指针,它本身是一个内存地址。那么我们就可以理解上面的那个语句了。内存地址0x56000010中储存了unsigned类型的变量,而且这一变量的值是直接读取内存得到的。rGPBCON是内存地址为0x56000010中的数据,4个字节,32位。
      如果我们不知道此时这32位各存有什么数据,而我们又想将其中的第11位置0、第10位置1,应如何操作。
流程如下:
①.  0x3<<10将得:
S3C2440-GPIO口的学习与总结 - SCE - ARM_UCLINUX
②.  ~(0x3<<10)
S3C2440-GPIO口的学习与总结 - SCE - ARM_UCLINUX
这样我们就分离了[11:10]位。
③.  ~(0x3<<10)& rGPBCON
这样得到的数据中除[11:10]位为0外,其余的位依旧保持了原来的值。
④.  rGPBCON  = ( ( ~(0x3<<(PIN*2)) ) & rGPBCON ) | (0x1<<10);
(0x1<<10)的值是:
S3C2440-GPIO口的学习与总结 - SCE - ARM_UCLINUX
或后,[11:10]=”01”,其它位保持原来的数据不变。
NOTE: 这是我目前想到的方法,如果大家有其它的好思路的话,请notice me.我一定会认真学习的。
  【下面的是后来又加的】
  【在我写完了,这片文档后,我总觉得自己的这种方法不是那么的直观,我总感觉我可以用指针或找到类似sbit的操作符。于是我看了以前自己用EasyARM1138写的程序,那里面有一项bit_bang技术,实现了对位的操作。里面介绍如下:
S3C2440-GPIO口的学习与总结 - SCE - ARM_UCLINUX
S3C2440-GPIO口的学习与总结 - SCE - ARM_UCLINUX
S3C2440-GPIO口的学习与总结 - SCE - ARM_UCLINUX
3.1       设置引脚为输入类型
void GPIOPinTypeIn(U8 PORT, U8 PIN)
{
      if(PORT == GPIOB)
             rGPBCON =( ( ~(0x3<<(PIN*2)) ) & rGPBCON );
}
3.2       设置引脚为输出类型
void GPIOPinTypeOut(U8 PORT, U8 PIN)
{
      if(PORT == GPIOB)
             rGPBCON  = ( ( ~(0x3<<(PIN*2)) ) & rGPBCON ) | (0x1<<(PIN*2) );
}
3.3       写数据
void GPIOPinWrite(U8 PORT, U8 PIN, U8 data)
{
      if(PORT == GPIOB)
             if(data == ON)
                    rGPBDAT =( ~(0x1<<PIN) & rGPBDAT );
             if(data == OFF)
                 rGPBDAT = ( (~(0x1<<PIN) )& rGPBDAT )| (0x1<< PIN);
}
附录
1、             写之前的准备
1.1       每一个寄存器的地址都是32位的,而每一位都代表了一个字节(即8位)。【17:06】
1.2       如果要对某一位操作,先将改为置1,然后整体取反,这样会导致该位为0,其余的都是1,然后和原来的数据进行“与”操作,这样其余位保持原来的数据不变,目标为为0.
1.3       在对寄存器操作时,记住0x11,代表00010001,写时很容易理解成00000011,注意。
2、             还需改进的地方
2.1       PORT还需要再写写。
声明:本篇文章来源于:Ednchina
原创粉丝点击