Pic PIC16F877 branching to different location

Thread Starter

limbonic

Joined Jul 4, 2011
17
I try to write code in assembly drive an LCD screen and a keypad. At the end the program have to drive also 2 stepper motors but in this stage i want to create first the menu of the LCD screen. When i press the buttons i want to display some messages on the LCD. My problem is that when i add more messages my code brances in weird location than the locations i want.

If in the code below i have only:

Rich (BB code):
kpad_values
    goto     keypad
    goto     FORWARD
    goto     keypad    ;invalid key        
    goto     LEFT
it runs smooth and when i press the suitable buttons it displays the suitable word in the LCD.

When i add one more message connected to another button:
Rich (BB code):
kpad_values
    goto     keypad
    goto     FORWARD
    goto     keypad    ;invalid key        
    goto     LEFT
    goto     STORE0
The programm doesn't work properly. Any idea what is going wrong and how i could fix this problem??

The code i use;

Rich (BB code):
LIST P=16F877A
include "P16F877A.INC"
__CONFIG _RC_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BODEN_ON & _LVP_OFF  & _CPD_OFF & _DEBUG_OFF;
ERRORLEVEL -302
   
PCL      EQU   H'02'      
STATUS   EQU   H'03'      
PORTA    EQU   H'05'      
TRISA    EQU   H'85'      
PORTB    EQU   H'06'      
TRISB    EQU   H'86'   
PORTC     EQU   H'07'
TRISC     EQU   H'87'
PORTD      EQU   H'08'
TRISD     EQU   H'88'   
INTCON   EQU   H'0B'
ADCON1     EQU   H'9F'
 
         
LOOP       EQU   H'20'      
LOOPA      EQU   H'21'      
CLKCNT     EQU   H'22'     
STORE   EQU   H'27'     
d1        equ      H'28'
d2        equ      H'29'
d3        equ   H'2a'
RSLINE  EQU   H'2F'     


cblock 0x30  
rowCode
scanFlag
rowCounter
rowMask
keytemp
kpadPattern
tabh
tabl
endc        

            
W   EQU   0      
F   EQU   1      
            
   ORG   0x00      
   GOTO   main      

main
    CALL    PORT_INIT
    CALL    LCD_INIT
    CALL    LCD_MESSAGE
    call    LCD_LINE2
    call    LCD_MESSAGE2

nop
    CALL    keypad
nop
    GOTO     NOMORE


PORT_INIT
    BCF        STATUS,5
    BCF        STATUS,6
    CLRF     PORTA
    CLRF    PORTB
    CLRF    PORTC
    CLRF    PORTD
    BSF        STATUS,5
    MOVLW    0x06
    MOVWF    ADCON1

    CLRF    TRISA
    CLRF    TRISB
    CLRF    TRISC
    MOVLW    B'00000111'        ;D0-2 OUTPUT, D4-7 INPUT
    MOVWF    TRISD
    BCF   STATUS,5         
RETURN
    
     
            
LCD_INIT
   CALL   DELAY1     ;perform first 1/5th sec delay
LCDSET   
   CLRF   LOOP      ;clr LCD set-up loop
   CLRF   RSLINE      ;clear RS line for instruction send
LCDST2   
   MOVF   LOOP,W      ;get table address
   CALL   TABLCD      ;get set-up instruction
   CALL   LCDOUT      ;perform it
   INCF   LOOP,F      ;inc loop
   BTFSS   LOOP,3      ;has last LCD set-up instruction now been done?
   GOTO   LCDST2      ;no
   CALL   DELAY1      ;yes, perform second 1/5th sec delay
            ;to allow final LCD command to occur
            ;(it takes longer than the rest)
RETURN


TABLCD   
   ADDWF   PCL,F           ;LCD initialisation table
   RETLW   B'00110011'   
   RETLW   B'00110011'   
   RETLW   B'00110010'   
   RETLW   B'00101100'   
   RETLW   B'00000110'   
   RETLW   B'00001100'   
   RETLW   B'00000001'   
   RETLW   B'00000010'   
                           



LCD_MESSAGE              
   CLRF   LOOP      ;clear loop
   BSF   RSLINE,4      ;set RS for data send
msg1   
   MOVF   LOOP,W      ;get table address
   CALL   MESSAG      ;get message letter
   CALL   LCDOUT      ;show it
   INCF   LOOP,F      ;inc loop
   BTFSS   LOOP,4      ;has last LCD letter been sent?
   GOTO   msg1      ;no, so repeat for next one
return
    
LCD_MESSAGE2
   CLRF   LOOP      ;clear loop
   BSF   RSLINE,4      ;set RS for data send
msg2
   MOVF   LOOP,W      ;get table address
   CALL   MESSAG2      ;get message letter
   CALL   LCDOUT      ;show it
   INCF   LOOP,F      ;inc loop
   BTFSS  LOOP,4      ;has last LCD letter been sent?
   GOTO   msg2      ;no, so repeat for next one
RETURN
            

            
LCDOUT   MOVWF   STORE      ;temp store data
           MOVLW   D'250'      ;set minimum time between sending full bytes to
              MOVWF   LOOPA      ;LCD - value of 250 seems OK for this prog with
DELAY    DECFSZ  LOOPA,F      ;XTAL clk of upto 20MHz
             GOTO   DELAY      ;keep decrementing LOOPA until zero
            CALL   SENDIT      ;send MSB
            CALL   SENDIT      ;send LSB
      RETURN         
            
SENDIT  SWAPF   STORE,F      ;swap data nibbles
           MOVF   STORE,W      ;get data byte
           ANDLW   H'0F'      ;get nibble from byte (LSB)
           IORWF   RSLINE,W      ;OR the RS bit
           MOVWF   PORTB      ;output the byte
           BSF   PORTB,5      ;set E line high
           BCF   PORTB,5      ;set E line low
   RETURN         
            


LCD_LINE2
    BCF       RSLINE,4      ;set RS for instructions send
    MOVLW    B'11000000'
    MOVWF    PORTB
       CALL       LCDOUT      ;perform it
    CALL     DELAY1
    BSF        RSLINE,4
    RETURN
    

;KEYPAD
keypad
    CLRF    kpadPattern
   
startscan
    CLRF    rowCode            ;register to help distrinct each row key values
;                            ;0:access 1,2,3 values
;                            ;3:access 4,5,6 values

    CLRF    scanFlag

    movlw    0x04
    movwf    rowCounter
    movlw    b'00001110'
    movlw    b'00010000'
    movwf    rowMask
    
keyfind
    movf    rowMask,w
    movwf    PORTD
    BTFSC    PORTD,0
    call    col0
    btfsc     PORTD,1
    call    col1
    btfsc    PORTD,2
    call    col2

    movlw    0x03
    addwf     rowCode,f
    bcf        PORTD,3
    rlf        rowMask,f
    decfsz    rowCounter,f
    goto    keyfind
    movf    scanFlag,f
    btfsc    STATUS,Z
    goto    scanEnd
    call    get_key

scanEnd
    call    DELAY1
    goto     startscan

col0
    movf    rowCode,w
    addlw    0x00
    movwf    kpadPattern
    incf    scanFlag,f
    return


col1
    movf    rowCode,w
    addlw    0x01
    movwf    kpadPattern
    incf    scanFlag,f
    return

col2
    movf    rowCode,w
    addlw    0x02
    movwf    kpadPattern
    incf    scanFlag,f
    return

get_key
    movf    kpadPattern,w
    movlw    high(kpad_values)
    movwf    tabh
    movlw    low(kpad_values)
    addwf    kpadPattern,w
    movwf    tabl


    btfsc    STATUS,C
    incf    tabh
    movf    tabh,W
    movwf    PCLATH
    movf    tabl,W
    movwf    PCL

kpad_values
    goto     keypad
    goto     FORWARD
    goto     keypad    ;invalid key        
    goto     LEFT
    goto     STORE0 




FORWARD
    BCF        RSLINE,4
    movlw    b'00000001'
    movwf    PORTB
    call    LCDOUT
    bsf        RSLINE,4
    call    LCD_MESSAGE4
    goto     NOMORE

LEFT
    BCF        RSLINE,4
    movlw    b'00000001'
    movwf    PORTB
    call    LCDOUT
    bsf        RSLINE,4
    call    LCD_MESSAGE5
    goto     NOMORE

STORE0
    movlw    0x01
    movwf    0x40
    BCF        RSLINE,4
    movlw    b'00000001'
    movwf    PORTB
    call    LCDOUT
    bsf        RSLINE,4
    call    LCD_MESSAGE6
    goto     NOMORE


DELAY1
            ;1499993 cycles
    movlw    0x0C
    movwf    d1
    movlw    0x46
    movwf    d2
    movlw    0x04
    movwf    d3
Delay_0
    decfsz    d1, f
    goto    $+2
    decfsz    d2, f
    goto    $+2
    decfsz    d3, f
    goto    Delay_0

            ;3 cycles
    goto    $+1
    nop

            ;4 cycles (including call)
    return



LCD_MESSAGE4
   CLRF   LOOP      
   BSF   RSLINE,4     
msg4
   MOVF   LOOP,W     
   CALL   MESSAG4       
   CALL   LCDOUT      
   INCF   LOOP,F     
   BTFSS  LOOP,4      
   GOTO   msg4      
RETURN

LCD_MESSAGE5
   CLRF   LOOP     
   BSF   RSLINE,4     
msg5
   MOVF   LOOP,W     
   CALL   MESSAG5       
   CALL   LCDOUT    
   INCF   LOOP,F     
   BTFSS  LOOP,4      
   GOTO   msg5     
RETURN

LCD_MESSAGE6
   CLRF   LOOP      
   BSF   RSLINE,4      
msg6
   MOVF   LOOP,W     
   CALL   MESSAG6      
   CALL   LCDOUT      
   INCF   LOOP,F      
   BTFSS  LOOP,4     
   GOTO   msg6     
RETURN

MESSAG   
   ADDWF   PCL,F      
   RETLW   ' '      
   RETLW   ' '      
   RETLW   ' '      
   RETLW   ' '      
   RETLW   ' '      
   RETLW   'r'      
   RETLW   'o'      
   RETLW   'b'
   RETLW   'o'      
   RETLW   't'      
   RETLW   ' '      
   RETLW   'v'      
   RETLW   '0'      
   RETLW   '.'   
   RETLW   '1'      
   RETLW   ' '   
  
MESSAG2   
   ADDWF   PCL,F   
   RETLW   'a'
   RETLW   'd' 
   RETLW   'd'
   RETLW   ' '  
   RETLW   'i'      
   RETLW   'n'      
   RETLW   's'      
   RETLW   't'      
   RETLW   'r'      
   RETLW   'u'      
   RETLW   'c'      
   RETLW   't'
   RETLW   'i'      
   RETLW   'o'      
   RETLW   'n' 
   RETLW   's' 






MESSAG4   
   ADDWF   PCL,F   
   RETLW   ' '
   RETLW   ' '      
   RETLW   ' '
   RETLW   'F' 
   RETLW   'O'
   RETLW   'R'  
   RETLW   'W'      
   RETLW   'A'      
   RETLW   'R'      
   RETLW   'D'      
   RETLW   ' '      
   RETLW   ' '      
   RETLW   ' '      
   RETLW   ' '
   RETLW   ' '      
   RETLW   ' ' 

MESSAG5   
   ADDWF   PCL,F   
   RETLW   ' '
   RETLW   ' '      
   RETLW   ' '
   RETLW   ' ' 
   RETLW   ' '
   RETLW   'L'
   RETLW   'E'  
   RETLW   'F'      
   RETLW   'T'      
   RETLW   ' '      
   RETLW   ' '          
   RETLW   ' '      
   RETLW   ' '      
   RETLW   ' '
   RETLW   ' '      
   RETLW   ' ' 

MESSAG6   
   ADDWF   PCL,F   
   RETLW   ' '
   RETLW   ' '      
   RETLW   ' '
   RETLW   ' ' 
   RETLW   'S'
   RETLW   'T'
   RETLW   'O'  
   RETLW   'R'      
   RETLW   'E'      
   RETLW   ' '      
   RETLW   ' '          
   RETLW   ' '      
   RETLW   ' '      
   RETLW   ' '
   RETLW   ' '      
   RETLW   ' ' 


NOMORE   GOTO   NOMORE      ;hold here
   END         ;final line
 
Last edited:

Thread Starter

limbonic

Joined Jul 4, 2011
17
I have to limit my text to 10000 characters so i delete some comments (sorry). In order to debug i use the stimulus. If i choose d0 pin as '1' and then as '0' then the first keypad column is active so i could take the keys in keypad(1,4,7,*) having the suitable row , if i choose d1 pin as HIGH first and as LOW then i choose column 2 and the keys(2,5,8,0) etc.
 
Top