PIC Microcontroler based Keyboards

Input multiplexing using 74HC251/4051

By Jinx

From: http://home.clear.net.nz/pages/joecolquitt/input_select.html with permission

There are many ways of multiplexing pushbuttons with micro pins, for example strobing,
with pins alternating between input (read button) and output (drive). Strobing will
often involve pull-ups and current-limiting resistors. Using an external IC such as a
latch or multiplexer enables the detection of signals like those that cannot be strobed,
for example toggle switches (ie no short-term release), signals which may be able to
drive/pull in only one direction or analogue signals (which can be multiplexed using a
4051). As appropriate, use and modify the detection routine below to suit your inputs


74HC251s can be added in parallel (datasheet says 128), each needing its own E0. With
only a short settling time after a selection or chip change, it is possible to scan many
inputs quickly and reliably



#define led         lata,4       ;indicator
#define e2512       latb,0       ;74HC251 (2) E0
#define e2513       latb,1       ;74HC251 (3) E0

;LCD pins 0V V+ VO RS R/W En DB0-DB7

#define  rs         latb,3       ;LCD RS out
#define  z251      portb,3       ;74HC251 Z in
#define  rs_z_tris trisb,3       ;direction
#define  rw         lata,0       ;LCD R/W
#define  en         lata,1       ;LCD enable
#define  e251       lata,2       ;74HC251 (1) output enable

;PortB <4:7>                      LCD data

;PortB <4:6>                      74HC251 select

         movlw   b'00100000'
;                  x            osc
;                   x           osc
;                    1          /MCLR
;                     0         LED
;                      0
;                       0       74HC251 (1) E0
;                        0      LCD enable
;                         0     LCD R/W
         movwf   trisa

         movlw   b'00000000'
;                  0000         LCD data out
;                   000         74HC251 input select
;                      0        RS out, 74HC251 Z in
;                       0
;                        0      74HC251 (3) E0
;                         0     74HC251 (2) E0
         movwf   trisb

;================================================

get_btn  call    read_btn

         movlw   0x00
         xorwf   btn_no,w
         bz      process_button1
         xorlw   0x00^0x01
         bz      process_button2
         xorlw   0x01^0x02
         bz      process_button3
         xorlw   0x02^0x03
         bz      process_button4
         xorlw   0x03^0x04
         bz      process_button5
         xorlw   0x04^0x05
         bz      process_button6
         xorlw   0x05^0x06
         bz      process_button7
         xorlw   0x06^0x07
         bz      process_button8

;Button processing routines

process_button1

         goto    get_btn       ;return to button routine

;================================================
;        Read buttons
;================================================

read_btn bsf     rs_z_tris     ;input for 74HC251 data
         bcf     e251          ;74HC251 output enabled

load_clk movlw   0x07          ;'Select' counter
         movwf   s_clk

btn_lp   movfw   portb
         andlw   b'10001111'   ;clear 74HC251 S0,S1,S2
         movwf   temp0
         swapf   s_clk,w
         addwf   temp0,w
         movwf   latb          ;add counter
         usec                  ;short settling delay
         btfsc   z251          ;test selected 74HC251 input
         bra     btn_down      ;= 1, button pressed
         decf    s_clk         ;decrement counter
         incf    s_clk,w
         bz      load_clk      ;counter = -1, reload

         bra     btn_lp        ;else no press, loop

btn_down movff   s_clk,btn_no  ;save button number 0 - 7 
         call    ms50          ;debounce delay

;test for release

         btfsc   z251          ;test selected 74HC251 input
         bra     $-2           ;still = 1
         call    ms50          ;debounce delay

         bsf     e251          ;74HC251 output disabled
         bcf     rs_z_tris     ;output for LCD RS
         return

Also: