一、目标
1.按下key1,key2,key3,key4,分别点亮LED1,LED2,LED3,LED4.
2.按下其他键则将四盏灯同时点亮
二、目的
1.熟悉GPIO口的操作
2.熟悉键盘扫描程序编写
三、原理图
4 x 4 键盘
4路LED灯
三、键盘扫描算法
1.用一个二维数组存放key值
2.将4x4的键盘看成4行和4列
第一行 : EINT0
第二行 : EINT2
第三行 : EINT11
第四行 : EINT19
第一列 : KSCAN0
第二列 : KSCAN1
第三列 : KSCAN2
第四列 : KSCAN3
3.算法思路
A.确定行
(1)四列的GPIO口全部输出低电平
(2)分别采集四行的GPIO口,如果一行采集到的电平是低电平,则这一行有按键按下
B.确定列
举例说明:
(1)假如,已经确定第4行有键按下
(2)将第1列输出低电平,其他列输出高电平,如果此时采集第四行,得到低电平,则确定按下的键是第一列上的键
即:(4,1)代表key1键按下。如果采集到的是高电平,则说明按下的键不在第一列。
依据这种思路,在分别将第2列输出低电平,其他列输出高电平。然后,在采集行.....
五、源码
1.启动代码(start.S)
.extern main
.text
.global _start
_start:
@关看门狗,不然cpu会不断重启
ldr r0,=0x53000000
mov r1,#0
str r1,[r0]
@设置栈指针(sp),为调用c语言准备栈空间
@注意,此时我们的实际物理内存并没有初始化
@此时,我们可用的内存只有s3c2410内部自带的片内4k SRAM
ldr sp,=4096
@ldr sp,=0x33000000
@跳到main函数
bl main
mainloop:
b mainloop
2.Makefile
key.bin:start.S key.c
arm-none-linux-gnueabi-gcc -c start.S -o start.o
arm-none-linux-gnueabi-gcc -c key.c -o key.o
arm-none-linux-gnueabi-ld -Ttext 0x00000000 start.o key.o -o key_elf
#arm-none-linux-gnueabi-ld -Ttext 0x30008000 start.o key.o -o key_elf
arm-none-linux-gnueabi-objcopy -O binary -S key_elf key.bin
cp key.bin /tftpboot
clean:
rm -rf *.o key_elf key.bin
3.主程序
- #include "s3c2410.h"
- #define LOW_LEVEL 0
- #define HIGH_LEVEL 1
- #define SET_GPIO_OUTPUT(R,nbit,data) do{\
- R &= ~(0X1 << nbit);\
- R |= (data << nbit);\
- }while(0)
- #define SET_ROW_OUTPUT(LEV1,LEV2,LEV3,LEV4) do{\
- SET_GPIO_OUTPUT(ROW1_R_11,11,LEV1);\
- SET_GPIO_OUTPUT(ROW2_R_6,6,LEV2);\
- SET_GPIO_OUTPUT(ROW3_R_13,13,LEV3);\
- SET_GPIO_OUTPUT(ROW4_R_2,2,LEV4);\
- }while(0)
- #define LINE1_R_0 GPFDAT
- #define LINE2_R_2 GPFDAT
- #define LINE3_R_3 GPGDAT
- #define LINE4_R_11 GPGDAT
- #define ROW1_R_11 GPEDAT
- #define ROW2_R_6 GPGDAT
- #define ROW3_R_13 GPEDAT
- #define ROW4_R_2 GPGDAT
- #define LINE1 1
- #define LINE2 2
- #define LINE3 3
- #define LINE4 4
- //初始化
- int led_init()
- {
- //GPFCON -> [8:15]清零
- GPFCON &= ~(0xff << 8);
- //GPF4 GPF5 GPF6 GPF7设为输出模式
- GPFCON |= 0x55 << 8;
- //输出高低平,关闭四路LED灯
- GPFDAT |= 0xf << 4;
- return 0;
- }
- //点亮灯
- int turn_on_light(int key)
- {
-
- if(key <= 4)
- GPFDAT &= ~(0x1 << key + 3);
- else
- //打开所有的灯
- GPFDAT &= ~(0xf << 4);
- return 0;
- }
- //关闭灯
- int turn_off_light(int key)
- {
- if(key <= 4)
- GPFDAT |= (0x1 << key + 3);
- else
- //关闭所有的灯
- GPFDAT |= (0xf << 4);
- return 0;
- }
- //设GPIO为输入模式
- int line_gpio_init()
- {
- int a,b;
- //GPF0->input
- GPFCON &= ~(0x3 << 0);
-
- //GPF2->input
- GPFCON &= ~(0x3 << 4);
- //GPG3->input
- GPGCON &= ~(0x3 << 6);
-
- //GPG11->input
- GPGCON &= ~(0x3 << 22);
- return 0;
- }
- //设GPIO为输出模式
- int row_gpio_init()
- {
- //GPE11->output 0
- GPECON &= ~(0X3 << 22);
- GPECON |= (0x1 << 22);
- //GPG6->output 0
- GPGCON &= ~(0x3 << 12);
- GPGCON |= (0X1 << 12);
- //GPE13->output 0
- GPECON &= ~(0x3 << 26);
- GPECON |= (0x1 << 26);
- //GPG2->output 0
- GPGCON &= ~(0x3 << 4);
- GPGCON |= (0x1 << 4);
- return 0;
- }
- int read_line_value(int line)
- {
- unsigned long data;
- switch(line)
- {
- case LINE1:
- //读寄存器
- data = LINE1_R_0;
- if(data & (1 << 0))
- return HIGH_LEVEL;
- else
- return LOW_LEVEL;
- case LINE2:
- data = LINE2_R_2;
- if(data & (1 << 2))
- return HIGH_LEVEL;
- else
- return LOW_LEVEL;
- case LINE3:
- data = LINE3_R_3;
- if(data & (1 << 3))
- return HIGH_LEVEL;
- else
- return LOW_LEVEL;
- case LINE4:
- data = LINE4_R_11;
- if(data & (1 << 11))
- return HIGH_LEVEL;
- else
- return LOW_LEVEL;
- }
- }
- int true_row_by_line(int line)
- {
- SET_ROW_OUTPUT(0,1,1,1);
- if(read_line_value(line) == LOW_LEVEL)
- return 1;
-
- SET_ROW_OUTPUT(1,0,1,1);
- if(read_line_value(line) == LOW_LEVEL)
- return 2;
- SET_ROW_OUTPUT(1,1,0,1);
- if(read_line_value(line) == LOW_LEVEL)
- return 3;
- SET_ROW_OUTPUT(1,1,1,0);
- if(read_line_value(line) == LOW_LEVEL)
- return 4;
- }
- int scan_key()
- {
- int x = -1,y = -1;
- int key_arry[4][4] = {
- {10 , 11 , 12 , 16},
-
- {7 , 8 , 9 , 15},
-
- {4 , 5 , 6 , 14},
-
- {1 , 2 , 3 , 13},
- };
-
- //将每一行的gpio口设为输入状态
- line_gpio_init();
- //将每一列的gpio口设为输出状态
- row_gpio_init();
-
- while(1)
- {
- //所有列的GPIO口输出低电平
- SET_ROW_OUTPUT(0,0,0,0);
-
- //第1行有键按下
- if(read_line_value(LINE1) == LOW_LEVEL)
- {
- x = 1;
- y = true_row_by_line(LINE1);
-
- turn_on_light(key_arry[x-1][y-1]);
- while(read_line_value(LINE1) == LOW_LEVEL);
- turn_off_light(key_arry[x-1][y-1]);
- }
- //第2行有键按下
- if(read_line_value(LINE2) == LOW_LEVEL)
- {
- x = 2;
- y = true_row_by_line(LINE2);
- turn_on_light(key_arry[x-1][y-1]);
- while(read_line_value(LINE2) == LOW_LEVEL);
- turn_off_light(key_arry[x-1][y-1]);
- }
- //第3行有键按下
- if(read_line_value(LINE3)== LOW_LEVEL)
- {
- x = 3;
- y = true_row_by_line(LINE3);
- turn_on_light(key_arry[x-1][y-1]);
- while(read_line_value(LINE3) == LOW_LEVEL);
- turn_off_light(key_arry[x-1][y-1]);
- }
- //第4行有键按下
- if(read_line_value(LINE4) == LOW_LEVEL)
- {
- x = 4;
- y = true_row_by_line(LINE4);
- turn_on_light(key_arry[x-1][y-1]);
- while(read_line_value(LINE4) == LOW_LEVEL);
- turn_off_light(key_arry[x-1][y-1]);
- }
-
- }
- return 0;
- }
- int main()
- {
- led_init();
- line_gpio_init();
-
- row_gpio_init();
-
- scan_key();
- return 0;
- }
阅读(6147) | 评论(0) | 转发(4) |