Continue to Site

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.

  • 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.

eeprom addressing help

Status
Not open for further replies.

fiveten

Member
Hello all,
I am having a problem changing eeprom addresses.

I am using a variable "ADR"

movlw 0x00
movwf ADR
call EE_Read
incf ADR
call EE_Read

EE_Read
bsf STATUS, RP0 ; Bank 1
movlw ADR
movwf EEADR ; Address to read
bsf EECON1, RD ; EE Read
movf EEDATA, W ; W = EEDATA
bcf STATUS, RP0 ; Bank 0
return

as i step through this code and i get to "movlw ADR" the w reg does not take this value.
am I addressing incorrectly? do i have to put a hex address in place of the ADR?
Please advise, Thanks
 
Hi fiveten,

If you want to load W with the address of 'ADR' you use 'movlw ADR'... If you want to load W with the value stored in 'ADR' you use 'movf ADR,W'...

Good luck with your project...
 
I have used "movf ADR, w" and when it executes the w reg is loaded with 0x00. When i use "movlw" the ADR address is loaded correctly. any thoughts?
 
I wonder if it could be a banking problem?

Code:
        cblock  0x20            ; bank 0, 0x20..0x7F
ADR                             ; EEPROM address, 0..255
        end

;*************************************************************
;                                                            *
;*************************************************************
        org 0x000
start
        banksel 0               ; bank 0                     |00
        movlw   0               ; start at address 0         |00
        movwf   ADR             ; ADR = 0                    |00
        call    EE_Read         ; read EEPROM                |00
        incf    ADR,F           ; ADR = 1                    |00
        call    EE_Read         ; read EEPROM                |00
        ...

EE_Read
        movf    ADR,W           ; get address, 0..255        |00
        banksel EEADR           ; bank 1                     |01
        movwf   EEADR           ; EEPROM address, 0..255     |01
        bsf     EECON1,RD       ; read EEPROM                |01
        movf    EEDATA,W        ; W = EEDATA                 |01
        banksel 0               ; bank 0                     |00
        return                  ;                            |00
 
Last edited:
I have used "movf ADR, w" and when it executes the w reg is loaded with 0x00. When i use "movlw" the ADR address is loaded correctly. any thoughts?
I'm sure someone can explain this much better than me. The assembler knows where the ADR variable is located (it's a 'constant') but it doesn't know what you have stored in that variable. When the program is assembled, the assembler can provide the correct value for the ADR address when you use the 'movlw ADR' instruction. It doesn't matter what bank you're in because the ADR address is a constant. On the other hand, when a running program tries to access a variable using the 'movf ADR,W' instruction, it has to be in the bank where the ADR variable is located.

Hope that makes sense...
 
Last edited:
See my revisions below:
Code:
   movlw 0x00
   movwf ADR
   call EE_Read
   incf ADR,f ; don't forget the destination: ',f'
   call EE_Read

EE_Read
   bsf STATUS, RP0 ; Bank 1
   movf ADR,f   ;*****changed this line****** but make sure ADR is accessible from bank 1
   movwf EEADR ; Address to read
   bsf EECON1, RD ; EE Read
   movf EEDATA, W ; W = EEDATA
   bcf STATUS, RP0 ; Bank 0
   return


Also, you can increment the EERAM address register directly. So you don't really need the ADR register. Here is code that I use:
Code:
    movlw 0x00
    call EE_Read
    call EE_Read_Next


EE_Read
    bank1
    movwf eeadr
    bsf eecon1,rd
    movf eedata,w
    return
EE_Read_Next
    bank1
    incf eeadr,f
    bsf eecon1,rd
    movf eedata,w
    return
 
Thanks for your help Mike and Bob. I will make these changes and let you know how it turned out.
Fiveten
 
Hi Fiveten. Good luck. I'll give you an "atta-boy" if you can find the error in Bob's first code example (grin)...
 
Here is some code I have used in the past to read and write to EEPROM on a PIC16f876

*****************************************************************************
;
; subroutine to read from EEPROM

;
; Function : EEREAD
;
; Input: EEPROM address to read from (In "W" register)
;
; Output: Date read from EEPROM (In "W" register)
;
;*****************************************************************************
; subroutine to read EEPROM memory (For PIC16F876)
EEREAD
bcf STATUS,RP0
bsf STATUS,RP1 ; select memory bank 2
movwf EEADR ; write EEADR
BSF STATUS,RP0 ; Bank 3
BCF EECON1, EEPGD ;Select data memory
bsf EECON1,RD ; read EEPROM
bcf STATUS,RP0 ; select bank 2
movfw EEDATA ; EEPROM value in w
BCF STATUS,RP1 ;Select bank 0

return

;*****************************************************************************
;
; subroutine to write to EEPROM
;
; Function : EWRITE
; Writes data in "W" register to internal EEPROM
; Address of EEPROM to be written must first be put in EEADR register
;
; Input: Value to write to internal EEPROM
;
;*****************************************************************************

; subroutine to write to EEPROM (For PIC16F876)

EWRITE
BCF INTCON,GIE ;Disable INTs.
BSF STATUS,RP1 ;
BSF STATUS,RP0 ;Select bank 3
BTFSC EECON1,WR ;Wait for write
GOTO $-1 ;to complete
BCF STATUS, RP0 ;select Bank 2
BCF STATUS,RP1 ;Select bank 0
MOVF DATA_EE_ADDR,W ;Data Memory
BSF STATUS,RP1 ;Select bank 2
MOVWF EEADR ;Address to write
BCF STATUS,RP1 ;Select bank 0
MOVF DATA_EE_DATA,W ;Data Memory Value
BSF STATUS,RP1 ;Select bank 2
MOVWF EEDATA ;to write
BSF STATUS,RP0 ;Select Bank 3
BCF EECON1,EEPGD ;Point to DATA memory
BSF EECON1,WREN ;Enable writes
MOVLW 0x55 ;
MOVWF EECON2 ;Write 55h
MOVLW 0xAA ;
MOVWF EECON2 ;Write AAh
BSF EECON1,WR ;Set WR bit to begin write
BCF EECON1,WREN ;Disable writes
BCF STATUS,RP1 ;Select bank 2
BCF STATUS,RP0 ;Select bank 0
BSF INTCON,GIE ;Enable INTs.
RETURN

I seem to remember the sequence of writing 0x55 and 0xAA to EECON2 was important

Les.
 
Hi Fiveten. Good luck. I'll give you an "atta-boy" if you can find the error in Bob's first code example (grin)...
Oops.
Fixed, I think:
Code:
EE_Read
   bsf STATUS, RP0 ; Bank 1
   movf ADR,w   ;                        <---   ***
   movwf EEADR ; Address to read
   bsf EECON1, RD ; EE Read
   movf EEDATA, W ; W = EEDATA
   bcf STATUS, RP0 ; Bank 0
   return
 
I think Mike was referring to the fact that on one of the instructions, I had incorrectly set the destination flag to f instead of w. I fixed this in my last post.

Regarding the use of upper/lower case for register names, I have the "strict case checking" option turned off in MPLAB. It would drive me crazy.
 
Status
Not open for further replies.

Latest threads

Back
Top