分类: LINUX
2010-10-25 13:20:27
TQ2440开发板为我们提供了四个按键,具体电路图如下:
K1—K4四个按键分别连接S3C2440CPU的EINT0—EINT4四个引脚。在按键处于未按下状态时,四个引脚接上拉电阻连接高电平;当按下按键时,引脚电平被拉低。根据这个电平变化的原理,我们可以判断有没有按键被按下。
本程序由crt0.S key_led.c Makefile三个文件组成。其中启动代码crt0.S文件与上一节我们讲的一样,在这里我就不再赘述了。这里要强调一下,由于我们下载到SDRAM中运行,注意堆栈指针的设置。
下面的代码(key_led.c)涉及的寄存器比较多,建议读者配合三星的手册一并使用。这里所涉及的寄存器都在手册的第9章。下面我在每行代码都作了注释,相信大大家应该有能看得懂了。
/*
*映射GPB、GPF控制寄存器、数据寄存器的地址
*/
#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对应GPB5、GPB6、GPB7、GPB8
*/
#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对应GPG11、GPG3、GPF2、GPF0
*/
#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)
{
//若Kn为0(表示按下),则令LEDn为0(表示点亮)
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手册》第九章。
chinaunix网友2010-12-02 21:52:40
刚刚换了一种写法,用PBDAT=(GPBDAT & ~(0xf<<5))|((~n & 0xf)<<5),然后每次调用这个加个延时好像就可以了。谢谢你!
chinaunix网友2010-12-02 20:15:36
这是我仿照你写的一个轮流点的灯,但是好像不是那种轮流转的,一直是长期亮着的,请问您能给我指导下哪错了吗?我的目的是想让他从LED1轮流到LED4的亮着,然后一个灯亮的时候别的都是灭的,但是好像不成功。请教你了,呵呵
#define GPBCON (*(volatile unsigned long *)0x56000010)
#define GPBDAT (*(volatile unsigned long *)0x56000014)
#define GPB5 0x00000400
#define GPB6 0X00001000
#define GPB7 0X00004000
#defin