;Dick Cappels' project pages projects@cappels.org - you shoudl be able to copy and paste this text into an assembler file.
;©2002 Richard Cappels All Rights Reserved
;HOME
;Four Bottons on Two I/O Pin Driver ;Traget: AVR microcontroller Questions? Dick Cappels, avr@cappels.org ;Date: 05 March, 2002 ; THE KEY ROUTINE ALLOWS THE READING OF ;FOUR BUTTONS USING TWO I/O PINS. It uses one high register ;as a scratch register and one low register, to return the scan results. ;The only hardware required are the two I/O pins to test and determine \ ;the button status, though a timer could be used a number of ways to ;improve CPU utilization, when taking the delay for settling of the I/O lines ;into account. Note that this concept can be extend but in a quick analyis, ;the benefit in I/O efficency over a regular matrix disappears when 8 I/O pins ;or more are used. ; The routine, getbuttonstatus, returns a "1" in bits in ;buttonstatus register to indicate which of up to four buttons are pressed. ;Bits in buttonstatus register are assigned as follows: ; butonBdown = 0 ; buttonBup = 1 ; buttonAdown = 2 ; buttonAup = 3 ; ; In prinicple, the circuit senses three states of the pushbuttons: ;Open (no button down), Pulled Up, and Pulled Down. ;The process is this: ;Pin A (PORTB bit 4)driven high through a resitor and the other end of the resistor ;is looked, at Pin B (PORTB bit 4) to see if it is being pulled high, low, or not ;being driven up a button at all. Then Pin B is driven and the other end ;of the resistor (Pin A) is looked at. ; ; In the circuit, a 40k resistor is placed across the two I/O pins ;to allow each pin to drive the other through the resistor. ;The two pair of buttons connected identically, except that ;one pair of buttons is connected to pin A (PORTB bit 3) and the other ;pair of buttons is connected Pin B (PORTB bit 4). In each pair, one ;button is connected to VCC through a 10k resistor and the other button ;connects to ground through a 10k resistor. The remaining contacts on ;the two buttons in each pair are connected together and connected to ;their respective I/O pin. Its a digital circuit so the actual resitor ;values aren't important as long as the logic thresholdsfor the input ports ;are exceeded. The four button implimentation only requires three resistors ;total. ; ; ; The rotuine getbuttonstatus returns the status of the buttons. It requires ;ShortDelayAndLoadPinB to provide some delay to let the I/O lines settle before ;it reads the state of the input pins. In cases in which there is very light ;capacitive loading on the I/O pins associated with the buttons the delay can be reduce or ;even completely eliminated (though the statement in temp,pinb would need to replace ;the call to ShortDelayAndLoadPinB). The amount of capacitive loading that can be ;tolerated is dependent upon the value of the resitor across the I/O pins (39k in ;the example) and the microcontroller clock rate. ; ;The routine will not respond properly if both the pull-high and pull-low buttons ;in a pair are pushed at the same time, so these two are mutually exclusive. .include "1200def.inc" .def buttonstatus = r21 .def temp = r16 ;bits in Port B used test and sense button status .equ Apin = 3 .equ Bpin = 4 .org $0000 ldi temp,$FF ;set port D as all output ONL USED TO TEST THE ROUTINE out ddrd,temp forever: ;this loop is only used for testing rcall getbuttonstatus ;get the status of the buttons out portd,buttonstatus ;output the button status to PORTD rjmp forever ;do this until the power is switched off or reset getbuttonstatus: ;Read and four buttons, return flags showing which ;buttons are down. clr buttonstatus ;set A high, test for B low cbi DDRB,Bpin ;make B an input sbi PORTB,Apin ;make pull for B buttons high sbi DDRB,Apin ;make A output pin rcall ShortDelayAndLoadPinB ;delay to settle I/O then load PORTB into temp andi temp,$10 ;mask all but the relevant bit brne notblow ;test for b being low ldi temp,$01 ;if be is low, then set but stat bit high or buttonstatus,temp notblow: ;set A low, test for B high (enter with DDRB Apin already set high) cbi portB,Apin ;make pull for B buttons low rcall ShortDelayAndLoadPinB ;delay to settle I/O then load PORTB into temp andi temp,$10 ;mask all but the relevant bit breq notbhigh ldi temp,$02 or buttonstatus,temp notbhigh: cbi DDRB,Apin ;make pin A input, pin B output sbi DDRB,Bpin ;set B high, test for A low sbi PORTB,Bpin ;make pull for A buttons high rcall ShortDelayAndLoadPinB ;delay to settle I/O then load PORTB into temp andi temp,$08 ;mask all but the relevant bit brne notalow ldi temp,$04 or buttonstatus,temp notalow: ;set B low, test for A high cbi portB,Bpin ;make pull for B buttons low rcall ShortDelayAndLoadPinB ;delay to settle I/O then load PORTB into temp andi temp,$08 ;mask all but the relevant bit breq notahigh ldi temp,$08 or buttonstatus,temp notahigh: ret ShortDelayAndLoadPinB: ldi temp,$00 shordelayroutine: dec temp brne shordelayroutine in temp,pinb ret ;http://projects.cappels.org/
;HOME