Chinaunix首页 | 论坛 | 博客
  • 博客访问: 229448
  • 博文数量: 18
  • 博客积分: 3295
  • 博客等级: 少校
  • 技术积分: 431
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-26 19:11
文章分类
文章存档

2010年(18)

分类: LINUX

2010-10-25 13:20:27

  从人和电脑的角度来看,我们都只做四件事情:采集信息、处理信息、存储信息和发送信息。随着电子技术的快迅发展,电脑和嵌入式的输入、输出设备也在不停的更新换代,但无论输入设备现在有多么强大,按键直至今日也没有被替代,即使在最新潮的电子设备iPhnoe 4上,也是有按键的。下面,我和大家分享一些按键的学习过程。

TQ2440开发板为我们提供了四个按键,具体电路图如下:

 

  

 

         K1—K4四个按键分别连接S3C2440CPUEINT0—EINT4四个引脚。在按键处于未按下状态时,四个引脚接上拉电阻连接高电平;当按下按键时,引脚电平被拉低。根据这个电平变化的原理,我们可以判断有没有按键被按下。

本程序由crt0.S  key_led.c  Makefile三个文件组成。其中启动代码crt0.S文件与上一节我们讲的一样,在这里我就不再赘述了。这里要强调一下,由于我们下载到SDRAM中运行,注意堆栈指针的设置。

下面的代码(key_led.c)涉及的寄存器比较多,建议读者配合三星的手册一并使用。这里所涉及的寄存器都在手册的第9章。下面我在每行代码都作了注释,相信大大家应该有能看得懂了。

/*

 *映射GPBGPF控制寄存器、数据寄存器的地址

 */

#define GPBCON     (*(volatile unsigned long *)0x56000010)

#define GPBDAT     (*(volatile unsigned long *)0x56000014)

#define GPFCON     (*(volatile unsigned long *)0x56000050)

#define GPFDAT      (*(volatile unsigned long *)0x56000054)

/*

 * LED1-4对应GPB5GPB6GPB7GPB8

 */

#define GPB5_out        (1<<(5*2))

#define GPB6_out        (1<<(6*2))

#define GPB7_out        (1<<(7*2))

#define GPB8_out        (1<<(8*2))

/*

 * K1-K4对应GPG11GPG3GPF2GPF0

 */

#define GPF4_in    ~(3<<(4*2))

#define GPF2_in     ~(3<<(2*2))

#define GPF1_in     ~(3<<(1*2))

#define GPF0_in     ~(3<<(0*2))

int main()

{

        unsigned long dwDat;

        // 设置LED1-LED4对应的4根引脚设为输出

        GPBCON = GPB5_out | GPB6_out | GPB7_out | GPB8_out ;

        // 设置K1-K4对应的引脚设为输入

        GPFCON = GPF0_in & GPF1_in & GPF2_in & GPF4_in;        

        while(1)

{

            //Kn0(表示按下),则令LEDn0(表示点亮)

            dwDat = GPFDAT;           // 读取GPF管脚电平状态       

            if (dwDat & (1<<4))          // K1没有按下

                GPBDAT |= (1<<5);      // LED1熄灭

            else   

                GPBDAT &= ~(1<<5);     // LED1点亮               

            if (dwDat & (1<<2))          // K2没有按下

                GPBDAT |= (1<<6);      // LED2熄灭

            else   

                GPBDAT &= ~(1<<6);     // LED2点亮                     

            if (dwDat & (1<<1))          // K3没有按下

                GPBDAT |= (1<<7);      // LED3熄灭

            else   

                GPBDAT &= ~(1<<7);     // LED3点亮   

            if (dwDat & (1<<0))          // K4没有按下

                GPBDAT |= (1<<8);      // LED4熄灭

            else   

                GPBDAT &= ~(1<<8);     // LED4点亮

    }

    return 0;

}

下面列出Makefile文件的内容:

key_led.bin : crt0.S  key_led.c

         arm-linux-gcc -g -c -o crt0.o crt0.S

         arm-linux-gcc -g -c -o key_led.o key_led.c

         arm-linux-ld -Ttext 0x30000000 -g  crt0.o key_led.o -o key_led_elf

         arm-linux-objcopy -O binary -S key_led_elf key_led.bin

         arm-linux-objdump -D -m arm  key_led_elf > key_led.dis

         cp -f key_led.bin /home/machoe/tftpboot

clean:

         rm -f   key_led.dis key_led.bin key_led_elf *.o

这里的Makefile文件和上节中的相似,这里我们利用arm-linux-objdump工具进行反汇编,有兴趣的读者可以查看ked_led.dis文件。

 

执行make后,将生成的.BIN文件烧到TQ2440开发板,按K1-K4键,对应的LED会点亮对应的LED。同时按下多个键,可以同时点亮多个LED

这里我留给大家几个思考问题,希望初学者能广泛在天嵌科技的论坛上讨论,也可以到我的博客上留言,我会尽快回复的。

1、  在实际应用中,我们的按键功能不会像上例中这样单一,例如:我们手机的关机键,当短按时,就是挂机功能,当长按时,就是关机,实际的程序中是怎样区分长按和短按的?

2、  在用电脑的键盘时,常常会用到组合键,如Ctrl+Alt+Del就可以启动任务管理器,还有上档键(Shift),这些组合键是怎么实现的?

 

1、韦东山 《嵌入式Linux应用开发完全手册》。

2、三星  《S3C2440手册》第九章。

阅读(7217) | 评论(13) | 转发(4) |
给主人留下些什么吧!~~

chinaunix网友2010-12-04 09:28:14

machoe兄,你的这里的GPF_in我换成了(2<<8),(2<<4),(2<<2),(2<<0),可以实现按键,但是你那样取反我运行按键不灵。前面我粘贴上去的代码只是.C的,但是我觉得对那个crt0.s的那个我还是不是很明白,特别是你的那个ldr 0x30000000,关于这几个存储的空间的,有时间的话很希望你 能写个博客给大家讲解清楚下。呵呵。我现在运行都是用你那天教的  n ->a下载

machoe2010-12-03 11:24:51

chinaunix网友: #define GPBCON (*(volatile unsigned long *)0x56000010)
#define GPBDAT  (*(volatile  unsigned long *)0x56000014)

#define GPB5    0x00000400
#define G.....
nice

machoe2010-12-03 11:24:04

chinaunix网友: #define GPBCON (*(volatile unsigned long *)0x56000010)
#define GPBDAT  (*(volatile  unsigned long *)0x56000014)

#define GPB5    0x00000400
#define G.....
nice

chinaunix网友2010-12-03 09:13:48

#define GPBCON (*(volatile unsigned long *)0x56000010)
#define GPBDAT  (*(volatile  unsigned long *)0x56000014)

#define GPB5    0x00000400
#define GPB6    0X00001000
#define GPB7    0X00004000
#define GPB8    0x00010000
int m;

#define GPB   (1<<10)|(1<<12)|(1<<14)|(1<<16)

void delay(m)
{
   int i=0;

machoe2010-12-02 22:24:53

chinaunix网友: 刚刚换了一种写法,用PBDAT=(GPBDAT & ~(0xf<<5))|((~n & 0xf)<<5),然后每次调用这个加个延时好像就可以了。谢谢你!.....
把完整的代码贴出来和大家分享吧。或者上传到网上,贴个地址给我。