johnnyquest
New Member
Using Microchip Application Note AN557 I have a problem with keypad scanning. When the keypad is pressed at times for numbers in the first column a "zero" will appear instead of the correct value. The zero appears randomly and introducing a delay as noted below reduces the zero from appearing when other numbers are pressed. The other columns are not affected so it does not seem to be some type of roll-over? I have seen similar code on the net used for keyscans, what could be wrong?
;ScanKeys, scans the 4X4 keypad matrix and returns a key value in
;NewKey (0 - F) if a key is pressed, if not it clears the keyhit flag.
;Debounce for a given keyhit is also taken care of.
;The rate of key scan is 20mS with a 4.096Mhz clock.
ScanKeys
btfss KeyFlag,DebnceOn ;debounce on?
goto Scan1 ;no then scan keypad
decfsz Debnce, F ;else dec debounce time
return ;not over then return
bcf KeyFlag,DebnceOn ;over, clr debounce flag
return ;and return
Scan1
call SavePorts ;save port values
movlw B'11101111' ;init TempD
movwf TempD
ScanNext
movf PORTB,W ;read to init port
bcf INTCON,RBIF ;clr flag
rrf TempD, F ;get correct column
btfss STATUS,C ;if carry set?
goto NoKey ;no then end
movf TempD,W ;else output
movwf PORTB ;low column scan line
; Intoducing this delay kinda helps
; MOVLW D'80' ;cycle delay
; MOVWF KeyScanDelay
; DECFSZ KeyScanDelay,F
; GOTO $-1
nop
btfss INTCON,RBIF ;flag set?
goto ScanNext ;no then next
btfsc KeyFlag,keyhit ;last key released?
goto SKreturn ;no then exit
bsf KeyFlag,keyhit ;set new key hit
swapf PORTB,W ;read port
movwf TempE ;save in TempE
call GetKeyValue ;get key value 0 - F
movwf NewKey ;save as New key
bsf KeyFlag,ServKey ;set service flag
bsf KeyFlag,DebnceOn ;set flag
movlw 4
movwf Debnce ;load debounce time
SKreturn
call RestorePorts ;restore ports
return
;
NoKey
bcf KeyFlag,keyhit ;clr flag
goto SKreturn
;
;GetKeyValue gets the key as per the following layout
;
; Col1 Col2 Col3 Col3
; (RB3) (RB2) (RB1) (RB0)
;
;Row1(RB4) 0 1 2 3
;
;Row2(RB5) 4 5 6 7
;
;Row3(RB6) 8 9 A B
;
;Row4(RB7) C D E F
;
GetKeyValue
clrf TempC
btfss TempD,3 ;first column
goto RowValEnd
incf TempC, F
btfss TempD,2 ;second col.
goto RowValEnd
incf TempC, F
btfss TempD,1 ;3rd col.
goto RowValEnd
incf TempC, F ;last col.
RowValEnd
btfss TempE,0 ;top row?
goto GetValCom ;yes then get 0,1,2&3
btfss TempE,1 ;2nd row?
goto Get4567 ;yes the get 4,5,6&7
btfss TempE,2 ;3rd row?
goto Get89ab ;yes then get 8,9,a&b
Getcdef
bsf TempC,2 ;set msb bits
Get89ab
bsf TempC,3 ; /
goto GetValCom ;do common part
Get4567
bsf TempC,2
GetValCom
movf TempC,W
addwf PCL, F
retlw 0
retlw 1
retlw 2
retlw 3
retlw 4
retlw 5
retlw 6
retlw 7
retlw 8
retlw 9
retlw 0a
retlw 0b
retlw 0c
retlw 0d
retlw 0e
retlw 0f
;ScanKeys, scans the 4X4 keypad matrix and returns a key value in
;NewKey (0 - F) if a key is pressed, if not it clears the keyhit flag.
;Debounce for a given keyhit is also taken care of.
;The rate of key scan is 20mS with a 4.096Mhz clock.
ScanKeys
btfss KeyFlag,DebnceOn ;debounce on?
goto Scan1 ;no then scan keypad
decfsz Debnce, F ;else dec debounce time
return ;not over then return
bcf KeyFlag,DebnceOn ;over, clr debounce flag
return ;and return
Scan1
call SavePorts ;save port values
movlw B'11101111' ;init TempD
movwf TempD
ScanNext
movf PORTB,W ;read to init port
bcf INTCON,RBIF ;clr flag
rrf TempD, F ;get correct column
btfss STATUS,C ;if carry set?
goto NoKey ;no then end
movf TempD,W ;else output
movwf PORTB ;low column scan line
; Intoducing this delay kinda helps
; MOVLW D'80' ;cycle delay
; MOVWF KeyScanDelay
; DECFSZ KeyScanDelay,F
; GOTO $-1
nop
btfss INTCON,RBIF ;flag set?
goto ScanNext ;no then next
btfsc KeyFlag,keyhit ;last key released?
goto SKreturn ;no then exit
bsf KeyFlag,keyhit ;set new key hit
swapf PORTB,W ;read port
movwf TempE ;save in TempE
call GetKeyValue ;get key value 0 - F
movwf NewKey ;save as New key
bsf KeyFlag,ServKey ;set service flag
bsf KeyFlag,DebnceOn ;set flag
movlw 4
movwf Debnce ;load debounce time
SKreturn
call RestorePorts ;restore ports
return
;
NoKey
bcf KeyFlag,keyhit ;clr flag
goto SKreturn
;
;GetKeyValue gets the key as per the following layout
;
; Col1 Col2 Col3 Col3
; (RB3) (RB2) (RB1) (RB0)
;
;Row1(RB4) 0 1 2 3
;
;Row2(RB5) 4 5 6 7
;
;Row3(RB6) 8 9 A B
;
;Row4(RB7) C D E F
;
GetKeyValue
clrf TempC
btfss TempD,3 ;first column
goto RowValEnd
incf TempC, F
btfss TempD,2 ;second col.
goto RowValEnd
incf TempC, F
btfss TempD,1 ;3rd col.
goto RowValEnd
incf TempC, F ;last col.
RowValEnd
btfss TempE,0 ;top row?
goto GetValCom ;yes then get 0,1,2&3
btfss TempE,1 ;2nd row?
goto Get4567 ;yes the get 4,5,6&7
btfss TempE,2 ;3rd row?
goto Get89ab ;yes then get 8,9,a&b
Getcdef
bsf TempC,2 ;set msb bits
Get89ab
bsf TempC,3 ; /
goto GetValCom ;do common part
Get4567
bsf TempC,2
GetValCom
movf TempC,W
addwf PCL, F
retlw 0
retlw 1
retlw 2
retlw 3
retlw 4
retlw 5
retlw 6
retlw 7
retlw 8
retlw 9
retlw 0a
retlw 0b
retlw 0c
retlw 0d
retlw 0e
retlw 0f