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: