Interfacing PIC's to hardware peripherals like keypads is relatively straight forward. Once you know how. Here I present to you all a complete and ready to build project that should hopefully make it all look like a snack to do. Because it actually really is. This Universal Keypad interface, in its current configuration, is serial by nature. Connected to a Hyper Terminal program it will print to the screen the literal values of the keys as they're pressed. This even includes the hash & star keys.
The keypad is robust. When I say robust I mean that there is absolutely positively no chance of key bouncing - (key bouncing is typically a multiple output of the key whilst being depressed) - but with this keypad, it's impossible for more than one key to be processed at any given time. This effectively eliminates the possibility of errors if the user attempts to press many keys simultaneously.
With little modification the hardware circuit & software that I present, could be easily adapted towards something more specific. Perhaps a simple burglar alarm, or maybe just a combination lock that controls some external device. The circuit uses a PIC16f628a processor and as it stands, only 400 words of code space has been used thus far. So there's plenty of room left for you to create your very own application specific projects. I promote the project as bare bones essential and universal in the fact that the serial output could be quickly exchanged with a relay. It's an adaptive building block!
</td>
</tr>
</table>
The Hardware Schematic
Pin numbers and all. No excuse not to build this. As you can see, there's hardly anything to it. We have the keypad, one discrete active component - NPN transistor, and a handful of passives. Also, it's worth while noting that the 4MHz crystal isn't critical, you could if you wish use an RC oscillator. You'll save a few bucks. Also, arguably, the PIC's internal pull ups could be used instead of the 100K externals.
The 4x3 matrix keypad consists of 4 rows & 3 columns. By using a process known as multiplexing, we can effectively provide direct support for 12 buttons using only 7 wire connections. Here's how it works: We continuously scan the columns incrementally, only one is ever on at a time, then we read the rows to determine what button was pressed. For example; if RB1 is low - (by the way the cols are active low) - pressing the hash key will cause RB0 to be pulled low. Similarly, if the 9 key is pressed RB2 swings low.
Power for the circuit is derived from any regulated 5V DC rail. 100nF & 10uF associated capacitors provide adequate decoupling for the circuit. These may need to be changed if heavier loads are anticipated. For example, adding a relay to switch something, ideally the 10uF capacitor will be upgraded to say 100uF. RA4 on the PIC is an open drain line, meaning it can sink current but it can't source it. In other words, it can't swing high only low. Hence the 2K2 pull up is required for the first column. This rather low value ensures a fast transition from low to high.
<hr/>
Code:Include "modedefs.bas" Define OSC 4 CMCON = 7 TRISA = %00001000 TRISB = %00001101 '// Declare Variables... Col_A VAR PORTB.1 Col_B VAR PORTA.2 Col_C VAR PORTA.4 Row_A VAR PORTA.3 Row_B VAR PORTB.3 Row_C VAR PORTB.2 Row_D VAR PORTB.0 Buzzer VAR PORTB.5 RX_To_PC VAR PORTA.0 Scan_Col VAR BYTE ' Counter - current col Key_Press VAR BYTE ' Value of key (0-9) & * + # Key_Down VAR BYTE ' Flag set true when key is depressed Allow_Key VAR BYTE ' Flag - disallow multiple keys being pressed I VAR byte ' General working var Scan_Keypad: @ incf _Scan_Col, 1 ' Inc col pos... SELECT CASE Scan_Col ' Col (1-3) CASE 1 Col_A = 0 ' Switch on col (active low) Col_B = 1 ' Col off Col_C = 1 ' Col off '// 3 Key IF Row_A = 0 THEN ' Key down? ... IF Allow_Key = 0 THEN ' Any other key down? Key_Press = 3 ' Load var w/value of key Allow_Key = 1 ' Disallow other keys ENDIF ENDIF '// 6 Key IF Row_B = 0 THEN IF Allow_Key = 0 THEN Key_Press = 6 Allow_Key = 1 ENDIF ENDIF '// 9 Key IF Row_C = 0 THEN IF Allow_Key = 0 THEN Key_Press = 9 Allow_Key = 1 ENDIF ENDIF '// # Key IF Row_D = 0 THEN IF Allow_Key = 0 THEN Key_Press = 35 Allow_Key = 1 ENDIF ENDIF CASE 2 Col_A = 1 Col_B = 0 Col_C = 1 '// 2 Key IF Row_A = 0 THEN IF Allow_Key = 0 THEN Key_Press = 2 Allow_Key = 1 ENDIF ENDIF '// 5 Key IF Row_B = 0 THEN IF Allow_Key = 0 THEN Key_Press = 5 Allow_Key = 1 ENDIF ENDIF '// 8 Key IF Row_C = 0 THEN IF Allow_Key = 0 THEN Key_Press = 8 Allow_Key = 1 ENDIF ENDIF '// 0 Key IF Row_D = 0 THEN IF Allow_Key = 0 THEN Key_Press = 0 Allow_Key = 1 ENDIF ENDIF CASE 3 Col_A = 1 Col_B = 1 Col_C = 0 '// 1 Key IF Row_A = 0 THEN IF Allow_Key = 0 THEN Key_Press = 1 Allow_Key = 1 ENDIF ENDIF '// 4 Key IF Row_B = 0 THEN IF Allow_Key = 0 THEN Key_Press = 4 Allow_Key = 1 ENDIF ENDIF '// 7 Key IF Row_C = 0 THEN IF Allow_Key = 0 THEN Key_Press = 7 Allow_Key = 1 ENDIF ENDIF '// * Key IF Row_D = 0 THEN IF Allow_Key = 0 THEN Key_Press = 42 Allow_Key = 1 ENDIF ENDIF Scan_Col = 0 END SELECT '// Output key serially, once only IF Key_Down <> Key_Press THEN ' Key already been sent? IF Key_Press <> 255 THEN ' 255 denotes no key press IF Key_Press = 42 OR Key_Press = 35 THEN ' Numerical key? SEROUT RX_To_PC, N2400, [Key_press] ' No ELSE ' SEROUT RX_To_PC, N2400, [#Key_press] ' Yes ENDIF '// Brief chrip of the piezo & flash of the LED for i = 0 to 20 toggle buzzer pause 5 next ENDIF Key_Down = Key_Press ' Copy of key just sent Buzzer = 0 ' Make sure LED is off ENDIF '// Check for key release, all cols on (active low) ... Col_A = 0 Col_B = 0 Col_C = 0 IF Row_A = 1 THEN IF Row_B = 1 THEN IF Row_C = 1 THEN IF Row_D = 1 THEN Allow_Key = 0 Key_Down = 0 Key_Press = 255 ENDIF ENDIF ENDIF ENDIF GOTO Scan_Keypad
Trent Jackson
<hr/><br/><br/><br/>
Bookmarks