indirect addressing in PIC MCU

Thread Starter

walid el masry

Joined Mar 31, 2009
133
i have problem with indirect addressing in PIC16f877A, i wanna learn the indirect addressing so i saw the datasheet example and it was easy it clears memory from address 0x20 to 0x2f like this

Rich (BB code):
ORG 0x500
BCF PCLATH,4
BSF PCLATH,3 ;Select page 1
;(800h-FFFh)
CALL SUB1_P1 ;Call subroutine in
: ;page 1 (800h-FFFh)
:
ORG 0x900 ;page 1 (800h-FFFh)
SUB1_P1
: ;called subroutine
;page 1 (800h-FFFh)
:
RETURN ;return to
;Call subroutine
;in page 0
;(000h-7FFh)
so i decided to write my 1st program, i wanna save data indirectly and retrieve it indirectly and display it on portb the data is 0x01,0x02,0x04 which will blink leds on portb with time difference 0.5 sec between each display and before the whole process but

unfortunately the code doesn't work correctly it blink RB5,RB1,RB0 unlike what i wrote(RB0,RB1,RRB2) that my code here


Rich (BB code):
;------------------------------------------
;device configuration
;------------------------------------------
    processor 16f877A
    #include<p16F877a.inc>
    __config _CP_OFF&_DEBUG_OFF&_WRT_OFF&_CPD_OFF&_LVP_OFF&_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_HS_OSC
;------------------------------------------
;variable decleration
;------------------------------------------
cblock 0x24
d1
d2
d3
endc
;------------------------------------------
;device initialise
;------------------------------------------
    org 0x00
    bsf STATUS,RP0
    movlw 0x00
    movwf TRISB
    bcf STATUS,RP0
    movwf PORTB
;------------------------------------------
;load data in 0x20 ~ 0x22 with Fh,Eh,Dh
;------------------------------------------
movlw 0x20
movwf FSR
movlw 0x01
movwf INDF
INCF FSR,F
movlw 0x02
movwf INDF
INCF FSR,F
movlw 0x04
movwf INDF
;------------------------------------------
call long_delay;wait 0.5 sec
;------------------------------------------
;read data from 0x20 ~ 0x22 and show it on PORTB for 0.5 sec for each address then stop
;------------------------------------------
movlw 0x20
movwf FSR
next:
movf INDF
movwf PORTB
call long_delay
INCF FSR,F
movlw 0x23
xorwf FSR,W
btfss STATUS,Z
goto next;no
;------------------------------------------
stop
goto stop
;------------------------------------------
;0.5 sec subroutine
;------------------------------------------
long_delay
            ;499994 cycles
    movlw    0x03
    movwf    d1
    movlw    0x18
    movwf    d2
    movlw    0x02
    movwf    d3
Delay_0
    decfsz    d1, f
    goto    $+2
    decfsz    d2, f
    goto    $+2
    decfsz    d3, f
    goto    Delay_0
            ;2 cycles
    goto    $+1
            ;4 cycles (including call)
    return
;------------------------------------------
end
 

Markd77

Joined Sep 7, 2009
2,806
A nice little feature to neaten up the code is if you put:
cblock 0x20
ramtable:3 ;reserve 3 bytes
.
.

and then anytime you do:
movlw 0x20
movwf FSR

you can replace it with:
movlw ramtable
movwf FSR
 

Thread Starter

walid el masry

Joined Mar 31, 2009
133
ooh what an idiot mistake yeah it was it i forgot to put "W" after "movf INDF" thnx " Markd77 " i'm about to use the indirect addressing in saving strings and retrieve them again when interfacing to LCD but there will be a problem that if i use too many strings the controller will still busy on reset in saving these strings in memory and may not response to outside untill it finishes, is there any way to save these strings in the mcu in flashing stage?
 
Last edited:

Thread Starter

walid el masry

Joined Mar 31, 2009
133
A nice little feature to neaten up the code is if you put:
cblock 0x20
ramtable:3 ;reserve 3 bytes
.
.

and then anytime you do:
movlw 0x20
movwf FSR

you can replace it with:
movlw ramtable
movwf FSR
i guess i will need to tell the compiler which byte i point to in ramtable because the work register is 8bit ?
 
Last edited:

Markd77

Joined Sep 7, 2009
2,806
It should work fine if you are still using incf FSR, F. I'm not sure what happens if you use it on PICs with more than 256 bytes of memory.
If you want to store more you would have to use the EEPROM or a table in program memory using the retlw instruction.
Have a look at AN556 on microchip site for the table read - it can get complicated.
 

Thread Starter

walid el masry

Joined Mar 31, 2009
133
ok iam checking it now but by the way it is the 1st time i know that i can move register value to work register just by using "MOVLW" i used to do it like this
movf f,w is there any difference between them or just the "movlw" is dealing with work register only unlike the "movf"
 

Markd77

Joined Sep 7, 2009
2,806
In this case it is not using the contents of ramtable, it is using the address of ramtable, which is 0x20.
It was probably easier to understand when variables were declared like:
var equ 0x20
var2 equ 0x21

Any time you use a variable name in place of a literal it uses the address.
 

Markd77

Joined Sep 7, 2009
2,806
It's easy enough to read and maintain your code at the moment, but if you had 4 tables and you decided to change the sizes, this method could save a lot of time.
 

Thread Starter

walid el masry

Joined Mar 31, 2009
133
it is using the address of ramtable
yes yes i know that it uses the address of the ramtable but the problem is still exist ramtable addresses a 3byte data and the "FSR" even "INDF" is 1byte wide :)
in my example ramtable will contain 0x010204 with address through 0x20,0x21,0x22 and i need to retrieve just 1 byte of 3 each time how could i point to it in code
 

Markd77

Joined Sep 7, 2009
2,806
What happens in the cblock is that the number 0x20 is given the name "ramtable", the next 2 bytes are reserved but don't have names.
Every time the compiler sees "ramtable" it just replaces it with the number 0x20.
for example:
movlw ramtable
compiles to movlw 0x20

and:
incf ramtable, F
compiles to incf 0x20, 1

The PIC itself is expecting either a literal or a file address depending on the instruction.

If you try it and watch what happens to the W reg when it executes the "movlw ramtable" instruction it should become clearer.
 

Thread Starter

walid el masry

Joined Mar 31, 2009
133
yes it works but i thought that

cblock 0x20
example
endc

will take the address of 0x20 and name it "example" cause it is easier to deal with names unlike numbers so why when i wrote

movlw example

it moves the address value of 0x20 not the content of the address 0x20 which pointed to by the name "example"

what is the reference you learned mcu from it ? :)
 

Thread Starter

walid el masry

Joined Mar 31, 2009
133
check this it really helps but he said like me that example is name of the address of 0x20 unlike in realtime it holds the address it self like you said and i test :S

http://tutor.al-williams.com/pic-inst.html

he said

The cblock directive allows you to define several bytes together. For example:
cblock 0x70
temp
x, y
endc This bit of assembler defines 3 bytes that will be at locations 0x70 (temp), 0x71 (x), and 0x72 (y)

and

When using cblock, you can also specify an increment by using a colon after each name. So for example:
cblock 0x70
temp:0, temp_hi, temp_lo
x, y
endc This snippet creates a variable called temp at 0x70. The variable temp_hi is also at 0x70 and temp_lo is at 0x71 (x and y are at 0x72 and 0x73). Presumably, we meant for temp to hold 16 bits in this example
 
Top