1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

Keypad Scanning Problem with AN557 16F628A

Discussion in 'Microcontrollers' started by johnnyquest, Nov 24, 2007.

  1. johnnyquest

    johnnyquest New Member

    Joined:
    Dec 18, 2004
    Messages:
    12
    Likes:
    0
    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
     
  2. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,642
    Likes:
    109
    Location:
    Michigan, USA
    I think I see a potential problem in the author's use of the RBIF (interrupt on change) flag bit while scanning the keypad and I suspect the flag may not always be valid when scanning the first keypad column.

    Do you feel like testing a small program change? This modified code doesn't use the RBIF "change" flag but tests for a pressed key using a slightly different method. Please let us know if it helps.

    Code (text):
    ScanNext
            rrf     TempD,F         ; last column done?
            skpc                    ; no, skip, else
            goto    NoKey           ; done, exit, no press
            movf    TempD,W         ; get new column pattern
            movwf   PORTB           ; update column lines
            nop                     ; settling time
            comf    PORTB,W         ; invert PORTB bits
            andlw   b'11110000'     ; any keys pressed?
            bz      ScanNext        ; no, branch, else
            btfsc   KeyFlag,keyhit  ; last key released?
     
     
  3. johnnyquest

    johnnyquest New Member

    Joined:
    Dec 18, 2004
    Messages:
    12
    Likes:
    0
    Mike,

    Your revised code does indeed work, many thanks for your help.

    I am trying to learn as much as I can on pic programming. Would this affect all pics? Could you please tell me why the use of the RBIF flag was not valid scanning the first column?

    Again Thanks,
    JohnnyQuest
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,642
    Likes:
    109
    Location:
    Michigan, USA

    Glad you got it working.

    It looked to me like the author was relying on the RB7 through RB4 "row" pins being set or high (ie; '1111xxxx') from a previous column scan cycle (when no keys connected to that column are pressed) before starting a new column scan cycle. This won't be the case for the first column scan when one of the keys in that column are pressed.

    I believe the author's method would produce the same symptoms on all PICs.
     

Share This Page