Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Scan code for parallel read on matrix keypad

Requests for sample C code to deal with a matrix keypad is a recurrent question, what motivated me to share here some tips on an alternative implementation, not so widely employed.

This code brings some benefits:
  • Allows reading combinations of multiple keys pressed at same row: 8(4 keys), 32(3keys), 48(2keys), 16(1key)
  • A little faster, due just 2 nibble scans are performed, instead 16 bit scan, performed on the classical approach.

Find bellow its implementation, fully tested on a 51 core, with a single adaptation for PIC core:

Code:
/* ********************************************************************** */
#define ROW_MASK        0x0F
#define COLUMN_MASK     0xF0
#define NO_KEY          0x00
/* ********************************************************************** */
unsigned int ScanKey ( void )
{
unsigned int ReadingKey                                ;
TRISx = COLUMN_MASK                                    ;  // Set high nible as Input and low nible as Output ( not tested )
PORTx = ROW_MASK                                       ;  // Output "1" value for low nible
Delay ( STEADY_OUTPUT )                                ;  // wait a few for charging parasitic capacitance on Port
ReadingKey = (~( PORTx | COLUMN_MASK ))                ;  // Read only high nible at "ReadingKey"
if ( ReadingKey )                                      ;  // If some key were pressed...
   {
   TRISx = ~COLUMN_MASK                                ;  // Set low nible as Input and high nible as Output ( not tested )
   PORTx =  COLUMN_MASK                                ;  // Output "1" value for high  nible
   Delay ( STEADY_OUTPUT )                             ;  // wait a few for charging parasitic capacitance on Port
   ReadingKey |= (~( PORTx | ROW_MASK ))               ;  // Read only low  nible at "ReadingKey" ( but now, add to previous read  )
   return ( ReadingKey )                               ;
   }
   else return ( NO_KEY )                              ;  // ...otherwise, returns "0"
}
/* ********************************************************************** */
//            KEY DEFINITIONS
//            ---------------
//
//          Px.4 Px.5 Px.6 Px.7
//                          
// Px.0    --0----1----2----3-                        
//           |    |    |    |
// Px.1    --4----5----6----7-
//           |    |    |    |     ROW_MASK ( 00001111 )
// Px.2    --8----9----A----B-
//           |    |    |    |
// Px.3    --C----D----E----F-
//
//             COLUMN_MASK ( 11110000 )
//
//
//
//           KEY MAPPING 
//           -----------
//
//   "0"    [ BIT0 + 0    + 0    + 0    + BIT4 + 0    + 0    + 0    ]
//   "1"    [ BIT0 + 0    + 0    + 0    + 0    + BIT5 + 0    + 0    ]
//   "2"    [ BIT0 + 0    + 0    + 0    + 0    + 0    + BIT6 + 0    ]
//   ...    [                        ...                            ]
//   "E"    [ 0    + 0    + 0    + BIT3 + 0    + 0    + BIT6 + 0    ]
//   "F"    [ 0    + 0    + 0    + BIT3 + 0    + 0    + 0    + BIT7 ]
//   ...
//   "0|3"  [ BIT0 + 0    + 0    + 0    + BIT4 + 0    + 0    + BIT7 ]
//   "4|6"  [ 0    + BIT1 + 0    + 0    + BIT4 + 0    + BIT6 + 0    ]
//
//    BITn = ( 1 << n )

Important advice that presented code merely performs kernel scan feature, so that additional features ( e.g debounce ) must be performed for functions which instantiate it.





+++
  • Like
Reactions: dmathis1

Comments

Very smart, good job man! ;)
I'm wondering abount a nobounce check, it could be a simple compare after each ReadingKey, something like:

Code:
unsigned int ScanKey ( void )
{
unsigned int ReadingKey, ReadingKey_                ;
TRISx = COLUMN_MASK                                    ;  // Set high nible as Input and low nible as Output ( not tested )
PORTx = ROW_MASK                                       ;  // Output "1" value for low nible
Delay ( STEADY_OUTPUT )                                ;  // wait a few for charging parasitic capacitance on Port

[COLOR="#FF0000"]do
{
ReadingKey = (~( PORTx | COLUMN_MASK ))                ;  // Read only high nible at "ReadingKey"
Delay (10 to 15 ms)                                                      ; // After a while time
ReadingKey_ = (~( PORTx | COLUMN_MASK ))                ;  // perform read check
}
while (ReadingKey~=ReadingKey_);[/COLOR]

if ( ReadingKey )                                      ;  // If some key were pressed...
   {
   TRISx = ~COLUMN_MASK                                ;  // Set low nible as Input and high nible as Output ( not tested )
   PORTx =  COLUMN_MASK                                ;  // Output "1" value for high  nible
   Delay ( STEADY_OUTPUT )                             ;  // wait a few for charging parasitic capacitance on Port
   
   [COLOR="#FF0000"]do
   {
   ReadingKey |= (~( PORTx | ROW_MASK ))               ;  // Read only low  nible at "ReadingKey" ( but now, add to previous read  )
   Delay(10 to 15 ms)                                                  ; // After a while time 
   ReadingKey_ |= (~( PORTx | ROW_MASK ))              ; // perform read check
   }
   while (ReadingKey~=ReadingKey_);[/COLOR]

   return ( ReadingKey )                               ;
   }
   else return ( NO_KEY )                              ;  // ...otherwise, returns "0"
}

What do you think?

Regards
 

Part and Inventory Search

Blog entry information

Author
andre_luis
Read time
2 min read
Views
1,270
Comments
2
Last update

More entries in Uncategorized

More entries from andre_luis

Share this entry

Back
Top