??? 10/21/02 18:54 Read: times |
#31164 - RE: 4 BY 5 Matrix key scan routine |
If you are writing code in C here is a code example for a 4x4 key scan algorithm. It should be reasonably easy to translate the concepts in this to assembly language as well. The code is also quite easy to expand to more more rows and/or columns.
#define REPEAT_ENABLE 1 /* set non zero to enable key repeat */ #define KEY_RATE 5 /* Number of calls to key_scan() before /* a key repeats */ /* ** ** keypad scanning program to decode the keypad via column to row ** sensing and decoding into a valid key code. This routine is ** designed to be called repeatively by a timed interrupt routine ** to support keypad filtering, debounce, and key repeat/held ** down logic. ** ** The keypad connects to the microcontroller via the following ** connections. The numbers in the lower corner of each button ** the logical local key code for the button in hexadecimal. ** The numbers in the upper corner of each button are the ** trnslated radio key codes. ** ** Note that this module generates logical key codes from the ** translate table that are +1 in value from those defined for ** the equipment interface so that a code of zero can indicate that ** no key is pressed. ** ** ** ** ** +-1----+ +-2----+ +-3----+ +-A----+ ** | 1 |____| 2 |____| 3 |____| ESC |_K4______ Row 0 ** | SW1 | | SW2 | | SW3 | | SW4 | P2.0 ** +----0-+ +----1-+ +----2-+ +----3-+ ** | | | | ** +-4----+ +-5----+ +-6----+ +-E----+ ** | 4 |____| 5 |____| 6 |____| PREV |_K5______ Row 1 ** | SW5 | | SW6 | | SW7 | | SW8 | P2.1 ** +----4-+ +----5-+ +----6-+ +----7-+ ** | | | | ** +-7----+ +-8----+ +-9----+ +-F----+ ** | 7 |____| 8 |____| 9 |____| NEXT |_K6______ Row 2 ** | SW9 | | SW10 | | SW11 | | SW12 | P2.2 ** +----8-+ +----9-+ +----A-+ +----B-+ ** | | | | ** +-C----+ +-0----+ +-D----+ +-B----+ ** | < |____| 0 |____| > |____| ENT |_K7______ Row 3 ** | SW13 | | SW14 | | SW15 | | SW16 | P2.3 ** +----C-+ +----D-+ +----E-+ +----F-+ ** | | | | ** | | | | ** | | | +-----K3------ Col 3 ** | | | P2.7 ** | | | ** | | +-----------------K2------ Col 2 ** | | P2.6 ** | | ** | +-----------------------------K1------ Col 1 ** | P2.5 ** | ** +-----------------------------------------K0------ Col 0 ** P2.4 ** ** The four rows K4-K7 are equipped with pullup resistors at the ** inputs to the microcontroller. In normal operation the ** columns are held high and placed low one column at a time ** while looking at the row inputs and seeing if there is ** a key pressed. ** ** scan codes are composed from the row and columns as two ** two bit pairs as RRCC to compose a nibble wise key code. ** */ /* globals that handle keyboard state logic */ char key_code; /* logical key code found in matrix */ char key_flag; /* flag true of key_code has a key present */ /* 0 = no keypress present */ /* -1 = key in debounce state */ /* +1 = key is valid press */ #if REPEAT_ENABLE char key_cnt; /* used to count out the key repeat duration */ #endif char key_inp; /* this holds new key code detected */ /* key fetch routine clears upon seeing key */ /* ** ** routine to initialize the board scan port logic to the inactive ** state. ** */ void key_init(void) { P2 = 0xFF; /* init all of keyboard port as inputs */ key_code=0; /* clear keyboard status variables */ key_flag=0; #if REPEAT_ENABLE key_cnt=0; #endif key_inp=0; } /* table to translate from the logical key numbers of the key matrix */ /* to the equipment matrix keycodes. note that the initializer is laid */ /* out in matrix that is like the key pad locatioms */ // setup whatever scan codes you want in here, Dont use zero for one of them const char key_xlat[16]={ RKEY_1, RKEY_2, RKEY_3, RKEY_ESC, RKEY_4, RKEY_5, RKEY_6, RKEY_PREV, RKEY_7, RKEY_8, RKEY_9, RKEY_NEXT, RKEY_LEFT, RKEY_0, RKEY_RIGHT, RKEY_ENT, }; /* this translates column number to low active column select bit */ const char col_xlat[4]={ 0xe0, /* column code 1110 */ 0xd0, /* column code 1101 */ 0xb0, /* column code 1011 */ 0x70, /* column code 0111 */ }; /* this prioritizes scan decode to row 3-2-1-0. codes in */ /* table encode as high two bits of a nibble key code */ const char row_xlat[16]={ 0x0, /* row code 0000 */ 0x0, /* row code 0001 */ 0x4, /* row code 0010 */ 0x4, /* row code 0011 */ 0x8, /* row code 0100 */ 0x8, /* row code 0101 */ 0x8, /* row code 0110 */ 0x8, /* row code 0111 */ 0xc, /* row code 1000 */ 0xc, /* row code 1001 */ 0xc, /* row code 1010 */ 0xc, /* row code 1011 */ 0xc, /* row code 1100 */ 0xc, /* row code 1101 */ 0xc, /* row code 1110 */ 0xc, /* row code 1111 */ }; /* ** ** routine to scan the keypad matrix to detect keys that ** are pressed. This routine is designed to be called ** at a regular repeatitive rate. (100 Hz is recommended). ** a key is valid is detected for two successive calls ** to this routine. A key detection is signalled by placing ** the key code into the "key_inp" variable with the MSB set. ** A separate key fetch routine would see this flag set ** capture the key and then clear the flag. ** ** The key scanner will repeat a key that is seen held ** down for an extended period of time causing repeated ** insertions of the code into the "key_inp" variable. ** ** This routine uses a single key lockout scheme and ** puts a priority on the scan order and stop at the ** first key seen. Is multiple keys are pressed the ** highest priority one takes precidence. ** */ void key_scan(void) { char col; char row; char key; for(col=0; col<4; col++) { P2=P2 | col_xlat[col]; row=P2; /* fetch in the row data */ row=(row&0x0f)^0x0f; /* keep low bits and invert */ if(row != 0) /* if a row bit set then some key */ { key=row_xlat[row]+col; /* get key code */ key=key_xlat[key]; /* translate to radio code+1 */ P2|=0xf0; /* force column bits high */ if(key_flag == 0) /* new key found */ { key_flag=-1; /* setup the debounce state */ key_code=key; return; } if(key == key_code) /* matching last time? */ { if(key_flag < 0) /* 2nd sighting of same key */ { key_flag=1; /* show valid key code */ #if REPEAT_ENABLE key_cnt=KEY_DELAY; /* init for initial repeat */ #endif key_inp=key; /* set new key out */ return; } #if REPEAT_ENABLE if(key_cnt-- <= 0) { key_cnt=KEY_RATE; /* set period to repeat */ key_inp=key; /* show key press */ } #endif return; } else { key_flag=-1; /* setup debounce for this new one */ key_code=key; return; } } } P2|=0xf0; /* force all column bits high */ /* no key seen so remove indication of any key */ key_code=0; key_flag=0; #if REPEAT_ENABLE key_cnt=0; #endif } /* ** ** routine to check if a particular key code is being held down ** for an external check for a repeat function of sorts. ** */ char keydown(char key) { if((key_flag > 0) && (key == key_code)) { /* show that key is pressed */ return(1); } /* show that this key is not pressed */ return(0); } /* ** ** function to get a key code if any present. ** this will return the key code value and that will ** valid of > 0. A return value of zero indicates that no ** key is pressed. ** */ char getkey(void) { char key; if(key_inp) { key=key_inp; key_inp=0; return(key); } return(0); } /* ** ** routine to check is a key is present ** this will return a zero value if mo ** key is present ** */ char chkkey(void) { if(key_inp) { return(1); /* key is ready */ } return(0); /* no key ready */ } Have Fun Mike Karas |
Topic | Author | Date |
4 BY 5 Matrix key scan routine | 01/01/70 00:00 | |
RE: 4 BY 5 Matrix key scan routine | 01/01/70 00:00 | |
RE: 4 BY 5 Matrix key scan routine![]() | 01/01/70 00:00 | |
RE: 4 BY 5 Matrix key scan routine | 01/01/70 00:00 | |
RE: 4 BY 5 Matrix key scan routine | 01/01/70 00:00 | |
RE: 4 BY 5 Matrix key scan routine | 01/01/70 00:00 | |
RE: 4 BY 5 Matrix key scan routine | 01/01/70 00:00 |