;****************************************************** ; ; Filename: KeyRead_Int.asm ; Author: J. Flanagan ; Company: JRF Consulting ; Date: 1/3/2003 2:49PM ; Email: jrfb@att.net ; ;****************************************************** ; The following assembly routine represents my ; favorite method for reading switch (PushButton) ; presses using the 8051/52 microcontroller. My ; algorithm is based on a 'State-Machine' design where ; the switches are sampled at an adequate rate and the ; state of the switches 'latched' when a key is pressed ; for a minimum of two sample periods. The switch state ; is captured in the variable 'KeyState' and the bit ; position represents the switch(s) pressed. This routine ; is best utilized in a timer interrupt where an approx ; 10-20 mSec sample rate is utilized. The user only needs ; to monitor the KeyState variable for '1's to indicate ; which switch(s) were pressed. Once the key press has been ; recognized, the user needs to reset the bit position in ; the 'KeyState' variable. The beauty of this state ; machine routine, is that the key MUST be released for a min ; of two sample periods to reset the state machine. i.e. if ; the operator presses a switch and holds the switch down ; indefinately, the 'KeyState' variable will not capture ; that particular key until the key is released for two ; sample periods. All key presses are processed in parallel. ; ; Usage Notes: ; * switches (up to 8) assumed to reside on one port ; * switches assumed to be active low for closure ; * Modify Switch_port for switch port used ; * Modify Switch_mask for masking unused bits on ; the switch port. ; * Interrupt routine shows reloading of Timer 0 upon entry. ; * Routine written as relocatable module for Keil Assembler ; * State analysis done using Atmel WinCupl FREE tool. ; * Routine written without any loops. ; * Assumption is made that user has set proper timers,etc ; to initiate Timer0 interrupt(s). ; ; Please feel free to use this routine anyway you desire. If you ; have questions or suggestions, please contact me. ; ;****************************************************** $MOD51 PUBLIC KeyRead PUBLIC KeyState KeyRead_code SEGMENT CODE KeyRead_data SEGMENT DATA ;******************* Port & Mask Definitions ********** Switch_port equ P1 ;modify this.. Switch_mask equ 0x0F ;modify this.. only lower nibble shown here ;******************* Local Variables ****************** State_now equ R1 State_captured equ R2 State_temp equ R3 ;******************* Global Variables ***************** rseg KeyRead_data KeyState: DS 1 State_filtered: DS 1 State_saved: DS 1 ;****************************************************** rseg KeyRead_code KeyRead_Int: ;****************************************************** USING 2 ; save the working registers PUSH PSW PUSH ACC PUSH AR1 PUSH AR2 PUSH AR3 ; reload the timer values for desired interrupt MOV TL0,#00 ;change this value for your clock MOV TH0,#00 ;change this value for your clock ; Start to process the designed 'State-machine' ; implement 'State_now = ~Switch_port & Port_mask' MOV A,Switch_port CPL A ANL A,#Switch_mask MOV State_now,A ; implement 'State_captured = State_saved AND ; State_now AND ; ~State_filtered ANL A,State_saved MOV State_temp,A MOV A,State_filtered CPL A ANL A,State_temp MOV State_captured,A MOV KeyState,A ; Switch Filter State Equation: ; State_filtered = ( State_saved AND State_now) OR ; ( State_saved AND State_filtered) OR ; (~State_saved AND State_now AND State_filtered); MOV A,State_saved ANL A,State_filtered ORL A,State_temp MOV State_temp,A MOV A,State_saved CPL A ANL A,State_now ANL A,State_filtered ORL A,State_temp MOV State_filtered,A ; State_saved = State_now; MOV State_saved,State_now ; Restore the working registers POP AR3 POP AR2 POP AR1 POP ACC POP PSW ; Done.. return RETI END