Problems with program counter and lookup table

Discussion in 'Embedded Systems and Microcontrollers' started by wannaBinventor, Aug 21, 2010.

  1. wannaBinventor

    Thread Starter Member

    Apr 8, 2010
    I've got a program that has an ADC measurement transmitted to it. I've gotten that to work great as evidenced by clearing or setting bits on a port with LED attached to each an giving a BCD of what the measurement was.

    Now I'm trying to send that to an LCD display by way of a lookup table. Long story short, I'm receiving a temp reading, then breaking it out into the tens place and the ones place. From there, the program will clock each number individually into the display. So I'm getting the measurement, extracting the tens place number, sending that to the W reg, then calling a lookup table which adds the w reg to the program counter: (memory address 02 in the PIC16F818). The problem is MPLAB SIM shows it skipping off widely, but consistently, do a different part of the code. I understand the program counter at address 02 to be the lower 8 bits, so if its 132 and I add 12 the PC should increment to 144, but this is not happening at all. I've even got a book that I've read that says its suppose to happen that way, but no dice.

    Below is a snip of the code. I'm making calls from within the lookup table so my numbers will clock into the LCD, with a RETLW 0 between each one so it doesn't keep calling everything below it if the W+PC puts it at the beginning of the table.

    Code ( (Unknown Language)):
    2. TMR0            EQU         1           ;means TMR0 is file 1.  
    3. PC                EQU            2            ;means Program Counter is file 2.
    4. STATUS          EQU         3           ;means STATUS is file 3.        
    5. PORTA           EQU         5              ;means PORTA  is file 5.        
    6. PORTB           EQU         6           ;means PORTB is file 6.
    7. ZEROBIT         EQU         2           ;means ZEROBIT is bit 2.        
    8. ADCON0          EQU         1FH           ;A/D Configuration reg.0
    9. ADCON1          EQU         9FH           ;A/D Configuration reg.1
    10. ADRES           EQU         1EH         ;A/D Result register.
    11. CARRY           EQU         0           ;CARRY IS BIT 0.
    12. TRISA            EQU            85H            ;PORTA Configuration Register
    13. TRISB            EQU            86H            ;PORTB Configuration Register
    14. OPTION_R         EQU            81H            ;Option Register
    15. OSCCON            EQU            8FH            ;Oscillator control register.
    16. CCPR1L            EQU            15H
    17. CCPR1H            EQU            16H
    18. CCP1CON            EQU            17H
    19. PR2                EQU            92H
    20. T2CON            EQU            12H
    21. TMR2            EQU            11H
    23. COUNT           EQU         20H         ;COUNT a register to count events.
    24. COUNTERA        EQU            21H
    25. COUNTERB        EQU            22H
    26. COUNTERC        EQU            23H            
    27. RCVDNUM            EQU            24H  
    28. NUMERATOR        EQU            25H
    29. DIVISOR            EQU            26H
    30. ANSWER            EQU            27H
    31. REMAINDER        EQU            28H
    32. MULTIPLIER        EQU            29H
    33. MULTWORK        EQU            30H
    35. ;********************************************
    37.     LIST        P=16F818             ;we are using the 16F818.
    38.     ORG         0                   ;the start address in memory is 0
    39.     GOTO          START               ;goto start!
    41. ;;;SUBROUTINE SECTION  (abbreviated for posting here)
    43. ;PIC Time Delay = 0.00012700 s with Osc = 4000000 Hz
    44. ;this should be same time as NOP on 31.25KHz
    46. CLKDLAY    movlw    D'42'
    47.         movwf    COUNTERA
    48. LOOPNOP    decfsz    COUNTERA,1
    49.         goto    LOOPNOP
    50.         RETLW    0
    52. CLOCK   BSF        PORTA,4
    53.         CALL    CLKDLAY                ;SUBSTITUTED FOR "NOP" WHICH          WORKS ON 32.25KHZ BUT NOT ON 4MHZ
    54.         BCF     PORTA,4
    55.         CALL    CLKDLAY                ;SUBSTITUTED FOR "NOP" WHICH WORKS ON 32.25KHZ BUT NOT ON 4MHZ
    56.         RETLW   0
    60. TENSLU    ADDWF    PC            ;ADD W TO PROGRAM COUNTER
    61.         CALL    NUM0        ;0 ADDED    
    62.         RETLW    0            ;1 ADDED
    63.         CALL    NUM1        ;2 ADDED    
    64.         RETLW    0            ;3 ADDED
    65.         CALL    NUM2        ;4
    66.         RETLW    0            ;5
    67.         CALL    NUM3        ;6
    68.         RETLW    0            ;7
    69.         CALL    NUM4        ;8
    70.         RETLW    0            ;9
    71.         CALL    NUM5        ;10
    72.         RETLW    0            ;11
    73.         CALL    NUM6        ;12
    74.         RETLW    0            ;13
    75.         CALL    NUM7        ;14
    76.         RETLW    0            ;15
    77.         CALL    NUM8        ;16
    78.         RETLW    0            ;17
    79.         CALL    NUM9        ;18
    80.         RETLW    0            ;19
    82. ONESLU    ADDWF    PC            ;ADD W TO PROGRAM COUNTER
    83.         CALL    NUM0        ;0 ADDED    
    84.         RETLW    0            ;1 ADDED
    85.         CALL    NUM1        ;2 ADDED    
    86.         RETLW    0            ;3 ADDED
    87.         CALL    NUM2        ;4
    88.         RETLW    0            ;5
    89.         CALL    NUM3        ;6
    90.         RETLW    0            ;7
    91.         CALL    NUM4        ;8
    92.         RETLW    0            ;9
    93.         CALL    NUM5        ;10
    94.         RETLW    0            ;11
    95.         CALL    NUM6        ;12
    96.         RETLW    0            ;13
    97.         CALL    NUM7        ;14
    98.         RETLW    0            ;15
    99.         CALL    NUM8        ;16
    100.         RETLW    0            ;17
    101.         CALL    NUM9        ;18
    102.         RETLW    0            ;19
    105. ;abbreviated program, with just the affected area.  all else works properly in MPLAB SIM
    108.         MOVWF    MULTIPLIER
    109.         MOVLW    .2                    ;MULTS REMAINDER BY TWO FOR THE LU TABLE
    110.         CALL    MULTPLY
    111.         MOVF    MULTIPLIER,W
    112.         CALL    ONESLU                ;DISPLAY THE # FROM THE ONES PLACE
    114.         CALL    DEG                    ;DISPLAY DEGREE SYMBOL
    115.         CALL    F                    ;DISPLAY AN "F"    
    117.         CALL    SECDLAY                ;THESE DELAYS WILL DISPLAY THE TEMP FOR 5 SECS
    118.         CALL    SECDLAY
    119.         CALL    SECDLAY
    120.         CALL    SECDLAY
    121.         CALL    SECDLAY
    122.         GOTO    BEGIN
    As always, thank you very much for the help.

    I should add that the watch window shows the value of PC becoming W + PC + 1 instruction, but obviously something else is wrong because its obviously affecting the program. Also, I noticed that I didn't add a "direct command" (0,1/w,f) after ADDWF PC, but I have sense added that into the command with the same result.
    Last edited: Aug 21, 2010
  2. Markd77

    Senior Member

    Sep 7, 2009
    The problem is almost certainly that the table is not in the first memory page.
    For more info download AN556 from the microchip site.
    It should explain all.
  3. wannaBinventor

    Thread Starter Member

    Apr 8, 2010

    Thanks for the help there. I love this place. I don't think I had to wait 10 minutes for a solution.

    I don't really fully understand AN556, but I did move my tables to the top of my subroutine section and MPLAB SIM seems to be happy with that.

    I would like to try and understand what AN556 is saying, however.

    When I look at my code in MPLAB ASM, how do I know what memory page a particular line or subroutine is in?

    Does the "memory page" that I am at in the code when I make the call matter if the lookup table is always on page 0?

    I've looked on the datasheet in the memory organization section. I'm having trouble deciphering what the page breaks are in memory.

    This is code from AN556:
    Code ( (Unknown Language)):
    2. EXAMPLE 3A:
    3. org 0x80
    4. movlw HIGH Table
    5. movwf PCLATH
    6. movlw offset
    7. call Table
    8. .
    9. .
    10. .
    11. org 0x320
    12. Table:
    13. addwf PCL,F
    14. retlw ’A’
    15. retlw ’B’
    Is the "org 0x80" and "org 0x320" actually required in the code, or is it just telling the reader where that piece of memory is for demonstrative purposes.
    I'm assuming "MOVLW HIGH TABLE" means to move a literal value to W that is equivalent to the memory page that the table is on. Is this correct?

    Thanks for the help. Much appreciated.
  4. Markd77

    Senior Member

    Sep 7, 2009
    If you look at the disassembly listing view, you can work out which page it is in, 0-255 is page 0, etc. Or you can look at PCLATH while stepping through code.
    It doesn't matter where you call it from unless you are using more than 2K of program memory.
    The ORGs are just for demo purposes, but it can be useful to put a table at the start of the last page (for example) if you don't want it to cross a boundary and don't want to keep track of it.
    The assumption about HIGH is correct - it gets the high byte from a 16bit number.
    Last edited: Aug 21, 2010