打印
[S3C2440]

ARM位操作实例分析

[复制链接]
1607|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yzai|  楼主 | 2015-9-1 15:46 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 yzai 于 2015-9-2 16:51 编辑

程序实例来自韦东山老师教学实例
S3C2440:130个IO管脚,除了A口的控制寄存器GPACON有25位,且是每位控制一个IO管脚外,
其他口的控制寄存器GPxCON都是两位控制一个对应的IO管脚见图

#define GPFCON      (*(volatile unsigned long *)0x56000050)//给寄存器设置地址:(volatile unsigned long *)0x56000050表示
                                                     volatile unsigned long型指针指向地址0x56000050,volatile表示不会因编译器优化而省略,
                                                    *(volatile unsigned long *)0x56000050表示指针操作,最终该语句表示GPFCON定义为 指针
                                                     操作,即 #define GPFCON  *p=&a  ,(unsigned long a    volatile unsigned long *p , a的内存地
                                                     址为0x56000050 )   
#define GPFDAT      (*(volatile unsigned long *)0x56000054)//IO口数据寄存器,该寄存器的每一位对应一个IO口管脚

#define GPGCON      (*(volatile unsigned long *)0x56000060)
#define GPGDAT      (*(volatile unsigned long *)0x56000064)

/*
* LED1,LED2,LED4对应GPF4、GPF5、GPF6
*/
#define GPF4_out (1<<(4*2))//1向左移8位,#define    GPF4_out             01 0000 0000
#define GPF5_out (1<<(5*2))//1向左移10位,#define  GPF5_out         0100 0000 0000
#define GPF6_out (1<<(6*2))//1向左移12位,#define  GPF6_out    01 0000 0000 0000

#define GPF4_msk (3<<(4*2))//11向左移8位,#define            GPF4_msk             11 0000 0000
#define GPF5_msk (3<<(5*2))//11向左移10位,#define          GPF4_msk         1100 0000 0000
#define GPF6_msk (3<<(6*2))//11向左移12位,#define          GPF4_msk    11 0000 0000 0000

/*
* S2,S3,S4对应GPF0、GPF2、GPG3
*/
#define GPF0_in     (0<<(0*2))        //0向左移0位,#define    GPF0_in                 0
#define GPF2_in     (0<<(2*2))        //0向左移4位,#define    GPF2_in        0 0000
#define GPG3_in     (0<<(3*2))       //0向左移6位,#define    GPG3_in    000 0000

#define GPF0_msk    (3<<(0*2))      //11向左移0位,#define            GPF0_msk                          11
#define GPF2_msk    (3<<(2*2))      //11向左移4位,#define            GPF2_msk                 11 0000
#define GPG3_msk    (3<<(3*2))     //11向左移6位,#define            GPG3_msk            1100 0000

int main()
{
        unsigned long dwDat;
        // LED1,LED2,LED4对应的3根引脚设为输出
        GPFCON &= ~(GPF4_msk | GPF5_msk | GPF6_msk);//对应位清零操作 与-反操作,过程如下:
                  // ~(GPF4_msk | GPF5_msk | GPF6_msk)=~(11 0000 0000|1100 0000 0000|11 0000 0000 0000)
                 // =00 0000 1111 1111,GPFCON &00 0000 1111 1111=xx00 0000 xxxx xxxx
        GPFCON |= GPF4_out | GPF5_out | GPF6_out;       //对应位赋值操作 或操作,过程如下:
                 // GPF4_out | GPF5_out | GPF6_out=(1 0000 0000|100 0000 0000|1 0000 0000 0000)
                 //=1 0101 0000 0000,GPFCON |1 0101 0000 0000=xx00 0000 xxxx xxxx|1 0101 0000 0000
                // =xx01 0101 xxxx xxxx,即GPFCON=xx01 0101 xxxx xxxx
                                                                                            F口的第4、5、6管脚设置为输出状态

        // S2,S3对应的2根引脚设为输入
        GPFCON &= ~(GPF0_msk | GPF2_msk);  //对应位清零,GPFCON=xxxx xxxx xx00 xx00
        GPFCON |= GPF0_in | GPF2_in;               //对应位赋值,GPFCON|0 0000=xxxx xxxx xx00 xx00
                                                                                           F口的第0、2管脚设置为输入状态

        // S4对应的引脚设为输入
        GPGCON &= ~GPG3_msk;                       //对应位清零,GPGCON=xxxx xxxx 00xx xxxx
        GPGCON |= GPG3_in;                              //对应位赋值,GPGCON|000 0000=xxxx xxxx 00xx xxxx
                                                                                            G口的第3管脚设置为输入状态
        while(1){
            //若Kn为0(表示按下),则令LEDn为0(表示点亮)
            dwDat = GPFDAT;               // 读取GPF管脚电平状态

            if (dwDat & (1<<0))            // 若F口第0管脚输入1,即对应按键未被按下
                GPFDAT |= (1<<4);         //  则F口第4管脚输出1,即对应灯熄灭
            else   
                GPFDAT &= ~(1<<4);      //  则F口第4管脚输出0,即对应灯点亮

            if (dwDat & (1<<2))              // 若F口第2管脚输入1,即对应按键未被按下
                GPFDAT |= (1<<5);          //  则F口第5管脚输出1,即对应灯熄灭
            else   
                GPFDAT &= ~(1<<5);      //  则F口第5管脚输出0,即对应灯点亮

            dwDat = GPGDAT;             // 读取GPG管脚电平状态

            if (dwDat & (1<<3))             // 若G口第3管脚输入1,即对应按键未被按下
                GPFDAT |= (1<<6);         //  则F口第6管脚输出1,即对应灯熄灭
            else   
                GPFDAT &= ~(1<<6);      //  则F口第6管脚输出0,即对应灯点亮
    }

    return 0;
}
//综上,对于GPFCON等两位对应一个IO口管脚的寄存器,应先清零才能赋值;对于GPFDAT等一位对应一个IO口管脚的寄存器,不用先清零就能赋值;

1.PNG (121.18 KB )

IO端口功能

IO端口功能

2.PNG (178.58 KB )

F口

F口

相关帖子

沙发
mini1986| | 2015-9-2 08:39 | 只看该作者
S3C2440市面上真正用来研发的少吧,大部分都是用这个来学习的.....裸机程序大概了解下就好,linux下面都封装好了......

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
yzai + 1 赞一个!
板凳
yzai|  楼主 | 2015-9-2 16:52 | 只看该作者
呵呵,初入而已,发发学习经过

使用特权

评论回复
地板
yzai|  楼主 | 2015-9-2 16:54 | 只看该作者
mini1986 发表于 2015-9-2 08:39
S3C2440市面上真正用来研发的少吧,大部分都是用这个来学习的.....裸机程序大概了解下就好,linux下面都封 ...

请教LINUX下怎么封装的?

使用特权

评论回复
5
mini1986| | 2015-9-6 09:49 | 只看该作者
yzai 发表于 2015-9-2 16:54
请教LINUX下怎么封装的?

没记错的话,应该是有clear_bit,set_bit这些函数或者宏定义......

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

128

帖子

2

粉丝