51单片机学习之路 —— 1.8 矩阵键盘

—.—  好久没有更新,最近太忙了,我被英语快搞死了,马上要四级了,自己语法好差。迷茫ing

 

1   什么是矩阵键盘?

    这里补一个键盘的定义

    

    

      

    

 

 

    大家看原理图,这就是矩阵键盘(4*4)

    四行 分别连到P3.0 P3.1 P3.2(INT0) P3.3(INT1) (从上到下)

    四列 分别连到P3.4(LCDEN) P3.5(RS) P3.6(WR) P3.7(RD)(左到右)

 

2    

    独立键盘一端固定位低电平! 检验较为方便

    但矩阵键盘不一样,他两边都与单片机的I/O相连接。所以检测方法有些不同

    要人为送出低电平,我们采取以下的检测方法:

    1.  先送一列为低电平,其余几列都为高电平(用此来确定列数)

    2.    然后立即轮流检测每一行是否有低电平(确定行数)

    

    我们写一个函数,用两个变量接受列和行的数据 cord_l cord_h

    P3 = 0xf0;  // 1111  0000

    

    判断是否有按键按下: 例如 S6按下  

    1.

    

    2. 假设S6按下

      

    此刻S6按下导通P3.4接口LCDEN为低电平(可以这样理解是P3.0与P3.4   0&1=0)

      此时的P3口为 1110 0000 (0xe0)

          P3 & 0xf0    (P3和0xf0按位与)

      P3     =  1110  0000

      0xf0  =  1111  0000  

         =  1110  0000 = 0xe0 

       这时成立

       表示有按键按下

 

    3   延时消抖

        

    4  储存值

          

          P3   =  1110  0000

          0xf0    =  1111  0000

          cord_l =  1110   0000

          

          cord_l     =   1110   0000

          0x0f        =   0000   1111

          P3           =   1110   1111  = 1110 1110(按下的是s6 P3.0 与 P3.1 与)

          

          P3       =    1110    1110

          0x0f    =    0000    1111

          cord_h =    0000    1110

          

          cord_l    =  1110   0000

          cord_h   =  0000   1110

            返回值  =  1110   1110    = 0xee

          这样我们就确定了一个值0xee  意味着是s6按下

          

2   程序编写  要求:按顺序按下s6~s21  依次显示0~f   6个数码管静态显示即可

           

  1 #include <reg52.h>
  2 #define uchar unsigned char
  3 #define uint  unsigned int
  4 sbit we = P2^7;
  5 sbit du = P2^6;
  6 uchar code leddata[]={ 
  7  
  8                 0x3F,  //"0"
  9                 0x06,  //"1"
 10                 0x5B,  //"2"
 11                 0x4F,  //"3"
 12                 0x66,  //"4"
 13                 0x6D,  //"5"
 14                 0x7D,  //"6"
 15                 0x07,  //"7"
 16                 0x7F,  //"8"
 17                 0x6F,  //"9"
 18                 0x77,  //"A"
 19                 0x7C,  //"B"
 20                 0x39,  //"C"
 21                 0x5E,  //"D"
 22                 0x79,  //"E"
 23                 0x71,  //"F"
 24                 0x76,  //"H"
 25                 0x38,  //"L"
 26                 0x37,  //"n"
 27                 0x3E,  //"u"
 28                 0x73,  //"P"
 29                 0x5C,  //"o"
 30                 0x40,  //"-"
 31                 0x00,  //熄灭
 32                 0x00  //自定义
 33  
 34                          };
 35 void delay(uint z)
 36 {
 37     uint x,y;
 38     for(x = z; x > 0; x--)
 39         for(y = 114; y > 0 ; y--);
 40 }
 41 
 42 
 43 uchar KeyScan()    //带返回值的子函数
 44 {
 45     uchar cord_l,cord_h;//声明列线和行线的值的储存变量
 46     P3 = 0xf0;//1111 0000
 47     if( (P3 & 0xf0) != 0xf0)//判断是否有按键按下
 48     {
 49         delay(5);//软件消抖
 50         if( (P3 & 0xf0) != 0xf0)//判断是否有按键按下
 51         {
 52               cord_l = P3 & 0xf0;// 储存列线值
 53               P3 = cord_l | 0x0f;
 54               cord_h = P3 & 0x0f;// 储存行线值
 55               while( (P3 & 0x0f) != 0x0f );//松手检测
 56               return (cord_l + cord_h);//返回键值码
 57         }    
 58     }
 59         
 60 }
 61 
 62 void KeyPro()
 63 {
 64     switch( KeyScan() )
 65     {
 66          //第一行键值码
 67         case 0xee: P0 = leddata[0];        break;
 68         case 0xde: P0 = leddata[1];        break;
 69         case 0xbe: P0 = leddata[2];        break;
 70         case 0x7e: P0 = leddata[3];        break;
 71         
 72         //第二行键值码
 73         case 0xed: P0 = leddata[4];        break;
 74         case 0xdd: P0 = leddata[5];        break;
 75         case 0xbd: P0 = leddata[6];        break;
 76         case 0x7d: P0 = leddata[7];        break;
 77 
 78         //第三行键值码
 79         case 0xeb: P0 = leddata[8];        break;
 80         case 0xdb: P0 = leddata[9];        break;
 81         case 0xbb: P0 = leddata[10];    break;
 82         case 0x7b: P0 = leddata[11];    break;
 83 
 84         //第四行键值码
 85         case 0xe7: P0 = leddata[12];    break;
 86         case 0xd7: P0 = leddata[13];    break;
 87         case 0xb7: P0 = leddata[14];    break;
 88         case 0x77: P0 = leddata[15];    break;
 89     }    
 90 }
 91 
 92 void main()
 93 {
 94     we = 1;//打开位选
 95     P0 = 0;//八位数码管全显示
 96     we = 0;//锁存位选
 97 
 98     du = 1;//打开段选端
 99     P0 = leddata[22];
100     while(1)
101     {
102          KeyPro();//提取键值码并且送不同数值给数码管显示
103     }
104 }
矩阵键盘

        

        

          这里让数码管一开始显示一个-

          用了一个循环让其一直执行

          

          注意switch中的表达式就是我们通过扫描键盘扫描出的键值码。

 

          

          

3   补充:

 

  c语言中的一些运算符      

       

运算符

范例

说明

+

a+b

a变量值和b变量值相加

-

a-b

a变量值和b变量值相减

*

a*b

a变量值乘以b变量值

/

a/b

a变量值除以b变量值

%

a%b

a变量值除以b变量值的余数

=

a=6

6设定给a变量,即a变量值等于6

+=

a+=b

等同于a=a+b,将ab相加的结果又存回a

-=

a-=b

等同于a=a-b,将ab相减的结果又存回a

*=

a*=b

等同于a=a*b,将ab相乘的结果又存回a

/=

a/=b

等同于a=a/b,将ab相除的结果又存回a

%=

a%=b

等同于a=a%b,将a变量值除以b变量值余数又存回a

++

a++

a的值加1,即a=a+1

--

a--

a的值减1,即a=a-1

a>b

测试a的值是否大于b

a<b

测试a的值是否小于b

=

a=b

测试a的值是否等于于b

>=

a>=b

测试a的值是否大于或等于b

<=

a<=b

测试a的值是否小于或等于b

=

a=b

测试a的值是否不等于b

&&

a&&b

ab做逻辑做AND,两个变量都是“真”,结果才为“真”否则结果为“0

||

a||b

ab做逻辑做OR,只要任何一个变量为“真”,结果就为“真”

a

a变量的值取反,即原来为“真”则变“假”,为“假”则变为“真”

>> 

a>>b

a按位右移b个位

<< 

a<<b

a按位左移b个位,右侧补“0

|

a|b

ab的按位做OR运算

&

a&b

ab的按位做AND运算

^

a^b

ab的按位做XOR运算

~

~a

a的每一位取反

&

a=&b

b变量的地址存入a寄存器

*

*a

用来取寄存器所指地址内的值

posted @ 2016-10-30 21:48  cc陈  阅读(1286)  评论(1)    收藏  举报