Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2761732
  • 博文数量: 102
  • 博客积分: 1444
  • 博客等级: 中尉
  • 技术积分: 13891
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-29 10:58
文章分类

全部博文(102)

文章存档

2014年(29)

2013年(14)

2012年(59)

分类: LINUX

2012-06-30 15:24:26

一、目标

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.主程序

  1. #include "s3c2410.h"

  2. #define LOW_LEVEL 0
  3. #define HIGH_LEVEL 1

  4. #define SET_GPIO_OUTPUT(R,nbit,data) do{\
  5.     R &= ~(0X1 << nbit);\
  6.     R |= (data << nbit);\
  7. }while(0)


  8. #define SET_ROW_OUTPUT(LEV1,LEV2,LEV3,LEV4) do{\
  9.     SET_GPIO_OUTPUT(ROW1_R_11,11,LEV1);\
  10.     SET_GPIO_OUTPUT(ROW2_R_6,6,LEV2);\
  11.     SET_GPIO_OUTPUT(ROW3_R_13,13,LEV3);\
  12.     SET_GPIO_OUTPUT(ROW4_R_2,2,LEV4);\
  13. }while(0)

  14. #define LINE1_R_0    GPFDAT
  15. #define LINE2_R_2     GPFDAT
  16. #define LINE3_R_3     GPGDAT
  17. #define LINE4_R_11     GPGDAT

  18. #define ROW1_R_11     GPEDAT
  19. #define ROW2_R_6     GPGDAT
  20. #define ROW3_R_13     GPEDAT
  21. #define ROW4_R_2     GPGDAT

  22. #define LINE1 1
  23. #define LINE2 2
  24. #define LINE3 3
  25. #define LINE4 4

  26. //初始化
  27. int led_init()
  28. {
  29.     //GPFCON -> [8:15]清零
  30.     GPFCON &= ~(0xff << 8);
  31.     //GPF4 GPF5 GPF6 GPF7设为输出模式
  32.     GPFCON |= 0x55 << 8;
  33.     //输出高低平,关闭四路LED灯
  34.     GPFDAT |= 0xf << 4;

  35.     return 0;
  36. }

  37. //点亮灯
  38. int turn_on_light(int key)
  39. {
  40.     
  41.     if(key <= 4)
  42.         GPFDAT &= ~(0x1 << key + 3);
  43.     else
  44.         //打开所有的灯
  45.         GPFDAT &= ~(0xf << 4);

  46.     return 0;
  47. }


  48. //关闭灯
  49. int turn_off_light(int key)
  50. {

  51.     if(key <= 4)
  52.         GPFDAT |= (0x1 << key + 3);
  53.     else
  54.         //关闭所有的灯
  55.         GPFDAT |= (0xf << 4);

  56.     return 0;
  57. }

  58. //设GPIO为输入模式
  59. int line_gpio_init()
  60. {    
  61.     int a,b;

  62.     //GPF0->input
  63.     GPFCON &= ~(0x3 << 0);
  64.     
  65.     //GPF2->input
  66.     GPFCON &= ~(0x3 << 4);

  67.     //GPG3->input
  68.     GPGCON &= ~(0x3 << 6);
  69.     
  70.     //GPG11->input
  71.     GPGCON &= ~(0x3 << 22);

  72.     return 0;
  73. }


  74. //设GPIO为输出模式
  75. int row_gpio_init()
  76. {
  77.     //GPE11->output 0
  78.     GPECON &= ~(0X3 << 22);
  79.     GPECON |= (0x1 << 22);

  80.     //GPG6->output 0
  81.     GPGCON &= ~(0x3 << 12);
  82.     GPGCON |= (0X1 << 12);

  83.     //GPE13->output 0
  84.     GPECON &= ~(0x3 << 26);
  85.     GPECON |= (0x1 << 26);

  86.     //GPG2->output 0
  87.     GPGCON &= ~(0x3 << 4);
  88.     GPGCON |= (0x1 << 4);

  89.     return 0;
  90. }


  91. int read_line_value(int line)
  92. {
  93.     unsigned long data;

  94.     switch(line)
  95.     {
  96.     case LINE1:
  97.         //读寄存器
  98.         data = LINE1_R_0;
  99.         if(data & (1 << 0))
  100.             return HIGH_LEVEL;
  101.         else
  102.             return LOW_LEVEL;

  103.     case LINE2:
  104.         data = LINE2_R_2;
  105.         if(data & (1 << 2))
  106.             return HIGH_LEVEL;
  107.         else
  108.             return LOW_LEVEL;

  109.     case LINE3:
  110.         data = LINE3_R_3;
  111.         if(data & (1 << 3))
  112.             return HIGH_LEVEL;
  113.         else
  114.             return LOW_LEVEL;

  115.     case LINE4:
  116.         data = LINE4_R_11;
  117.         if(data & (1 << 11))
  118.             return HIGH_LEVEL;
  119.         else
  120.             return LOW_LEVEL;
  121.     }
  122. }

  123. int true_row_by_line(int line)
  124. {

  125.     SET_ROW_OUTPUT(0,1,1,1);
  126.     if(read_line_value(line) == LOW_LEVEL)
  127.         return 1;
  128.     
  129.     SET_ROW_OUTPUT(1,0,1,1);
  130.     if(read_line_value(line) == LOW_LEVEL)
  131.         return 2;

  132.     SET_ROW_OUTPUT(1,1,0,1);
  133.     if(read_line_value(line) == LOW_LEVEL)
  134.         return 3;

  135.     SET_ROW_OUTPUT(1,1,1,0);
  136.     if(read_line_value(line) == LOW_LEVEL)
  137.         return 4;
  138. }

  139. int scan_key()
  140. {

  141.     int x = -1,y = -1;
  142.     int key_arry[4][4] = {

  143.         {10    ,    11    ,    12    ,    16},
  144.         
  145.         {7    ,    8    ,    9    ,    15},
  146.         
  147.         {4    ,    5    ,    6    ,    14},
  148.         
  149.         {1    ,    2    ,    3    ,    13},
  150.     };
  151.     
  152.     //将每一行的gpio口设为输入状态
  153.     line_gpio_init();
  154.     //将每一列的gpio口设为输出状态
  155.     row_gpio_init();
  156.     
  157.     while(1)
  158.     {
  159.         //所有列的GPIO口输出低电平
  160.         SET_ROW_OUTPUT(0,0,0,0);
  161.             
  162.         //第1行有键按下
  163.         if(read_line_value(LINE1) == LOW_LEVEL)
  164.         {

  165.             x = 1;
  166.             y = true_row_by_line(LINE1);
  167.         
  168.             turn_on_light(key_arry[x-1][y-1]);
  169.             while(read_line_value(LINE1) == LOW_LEVEL);            
  170.             turn_off_light(key_arry[x-1][y-1]);
  171.         }

  172.         //第2行有键按下
  173.         if(read_line_value(LINE2) == LOW_LEVEL)
  174.         {    
  175.             x = 2;
  176.             y = true_row_by_line(LINE2);

  177.             turn_on_light(key_arry[x-1][y-1]);
  178.             while(read_line_value(LINE2) == LOW_LEVEL);
  179.             turn_off_light(key_arry[x-1][y-1]);
  180.         }

  181.         //第3行有键按下
  182.         if(read_line_value(LINE3)== LOW_LEVEL)
  183.         {

  184.             x = 3;
  185.             y = true_row_by_line(LINE3);

  186.             turn_on_light(key_arry[x-1][y-1]);
  187.             while(read_line_value(LINE3) == LOW_LEVEL);
  188.             turn_off_light(key_arry[x-1][y-1]);
  189.         }

  190.         //第4行有键按下
  191.         if(read_line_value(LINE4) == LOW_LEVEL)
  192.         {

  193.             x = 4;        
  194.             y = true_row_by_line(LINE4);

  195.             turn_on_light(key_arry[x-1][y-1]);
  196.             while(read_line_value(LINE4) == LOW_LEVEL);
  197.             turn_off_light(key_arry[x-1][y-1]);
  198.         }
  199.         
  200.     }


  201.     return 0;
  202. }

  203. int main()
  204. {
  205.     led_init();

  206.     line_gpio_init();
  207.     
  208.     row_gpio_init();
  209.     
  210.     scan_key();

  211.     return 0;
  212. }
阅读(6147) | 评论(0) | 转发(4) |
给主人留下些什么吧!~~