4x4 Keyboard Programming Experience

Publisher:tanjunhuiLatest update time:2016-07-18 Source: eefocus Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
    Keyboards are widely used in single-chip microcomputer systems. When there are many keys and the I/O ports of the single-chip microcomputer are limited, a matrix keyboard is often considered. There are two ways to implement a matrix keyboard: one is to use pure hardware to complete the decoding, which is called a "coded keyboard"; the other is to use software to achieve decoding, which is called a "non-coded keyboard".

  In the single-chip system, as long as the single-chip has spare time to decode, we often use software decoding, that is, "non-encoded keyboard" to realize the matrix keyboard. This can save costs. Below I will summarize the application of software decoding of matrix keyboard in 51 single-chip microcomputer.

   Schematic diagram:

working principle:

    The scanner queries the following:

     &129; Check whether a key is pressed. First, the MCU outputs a scan code F0H of all 0s to the row scan ports P1.0~P1.3, and then inputs the column detection signal from the column detection ports P1.4~P1.7. As long as one column signal is not 1, that is, the P1 port is not F0H, it means that a key is pressed. Then find out the row and column position of the pressed key.

     &8218; Query the row and column position of the pressed key. The microcontroller will invert the received signal, and the position where P1.4~P1.7 is 1 is the position of the key.

    Next, to determine the row where the key is located, it is necessary to scan the rows row by row. The single-chip computer first uses the P1.0 port to ground, and the P1.1~P1.7 ports are 1, that is, the scan code FEH is sent to the P1 port, and then the column detection signal is input. If it is all 1, it means that it is not in the first row. Then P1.1 is grounded, and the rest are 1, and then the column signal is read in... In this way, the scan code of 0 is sent row by row until the row where the key is located is found, and the scan code of the row is inverted and retained. If it is still not found after scanning all rows, the scan is abandoned and it is considered to be a false action of the key.

     &402; Decode the obtained row number and column number to get the key value.

     &8222; Debounce of keys. When you press a key manually, the key often jumps between the closed position and the open position several times before stabilizing to the closed state; a similar situation occurs when you release a key. This is key jitter. The duration of jitter varies, usually no more than 10 ms. If the jitter problem is not solved, it will cause multiple readings of the closed key. The most convenient way to solve key jitter is: when a key is found to be pressed, do not scan line by line immediately, but delay it for 10 ms before scanning. Since the time a key is pressed can last for hundreds of ms, it is not too late to scan after the delay.

The procedure is as follows:

unsigned char key_scan(void) // key scan function

{

    unsigned char sccode,recode;

    P1=0xf0; // Send all 0 row scan code, column line input

    if((P1&0xf0)!=0xf0) // If a key is pressed

    {

       delay_ms(10); // Delay debounce

       if((P1&0xf0)!=0xf0)

       {

          sccode=0xfe; // Scan line by line initial value

          While((sccode&0x10)!=0)

          {

             P1=sccode; // Output line scan code

             if((P1&0xf0)!=0xf0) // A key is pressed in this line

             {

                recode=(P1&0xf0)|0xf0;

                return(( ~ sccode)+( ~ recode)); // Returns the characteristic bytecode

             } 

             else

             sccode=(sccode<<1)|0x01; // Shift the row scan code one position to the left

          }

       }

    }

  return(0); // No key is pressed, the return value is 0

}

illustrate:

    This key scanning function is introduced in many books. It is completely correct and feasible from the original point of view. But when I was doing "Password Lock" last time, I found that it was troublesome to use this function and there were always some problems. By consulting a lot of books and experiments, I wrote a relatively simple and feasible key scanning program.

 

The procedure is as follows:

/****************************************************** **** 

 Function name: uchar Key_scan(void)

 Function: 4x4 buttons, button scanning

 Description: Scan the keys to get the key codes

 Entry parameters: None

 Return value: If a key is pressed, it returns: key code = row scan value + column scan value; if no key is pressed, it returns 0  

 *************************************************** ***/

uchar Key_scan(void)

{

  uchar key; //Store key code

  P1=0xf0; // Send all 0 row scan code, column line input

  if((P1&0xf0)!=0xf0) // If a key is pressed

  {

       delay_ms(10); // Delay debounce

      P1=0xf0; // Take the high 4-bit value. That is: column scan value

       key=P1&0xf0; //Store the high 4 bits of the key code

       P1=0x0f; // Take the lower 4 bits. That is: row scan value

       key=(P1&0x0f)|key; //Merge the lower 4 bits with the upper 4 bits

       if(key!=0xff)

       {

         return(key); // A key is pressed, return the key code

       }

   }

   return(0); // No key is pressed, return 0

}

 

/****************************************************** **** 

 Function name: uchar Key_switch(void)

 Function: key conversion program

 Description: Convert key codes

 Entry parameters: None

 Return value: ASCII code  

 *************************************************** ***/

uchar Key_switch(void)

 {

   uchar key;

   key=Key_scan();

   switch(key)

   {

      case 0xee:return(49);break; /* "1" key */ 

      case 0xed:return(50);break; /* "2" key */

      case 0xeb:return(51);break; /* "3" key */

      case 0xe7:return(65);break; /* "A" key */

 

 

      case 0xde:return(52);break; /* "4" key */

      case 0xdd:return(53);break; /* "5" key */

      case 0xdb:return(54);break; /* "6" key */

      case 0xd7:return(66);break; /* "B" key */  

                               

      case 0xbe:return(55);break; /* "7" key */                             

      case 0xbd:return(56);break; /* "8" key */ 

      case 0xbb:return(57);break; /* "9" key */

      case 0xb7:return(67);break; /* "C" key */

 

 

      case 0x7e:return(42);break; /* "*" key */

      case 0x7d:return(48);break; /* "0" key */

      case 0x7b:return(35);break; /* "#" key */

      case 0x77:return(68);break; /* "D" key */

 

 

      case 0x00:return(00);break; /* "None" key */

   }

 }

/* Accept button description:

--------------------------------------------------

            | 1 | 2 | 3 | A |

            - - - - - - - - - - - - -

            | 4 | 5 | 6 | B |

            - - - - - - - - - - - - -

            | 7 | 8 | 9 | C |

            - - - - - - - - - - - - -

            | * | 0 | # | D |

--------------------------------------------------

illustrate:

    If you need to change the key value, just change the corresponding return value in the Key_switch () function. The delay function is relatively simple and only requires a for loop, so it is not written here. Because the I/O application of each microcontroller is different, the function I wrote can only run under the 51 microcontroller system. If you want to use other microcontroller systems, you may need to use the first method for improvement.

Reference address:4x4 Keyboard Programming Experience

Previous article:Comparing AVR and ARM, talking about the similarities and differences
Next article:Introduction to MCU Types

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号