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 doesn't return right value after shutoff.

Status
Not open for further replies.

RobertD

New Member
I have a problem with the EEPROM. When I turn the chip off, I get 0xFF in my EEPROM registers, and the NEW register now puts this value in the read sequence and returns 255 instead of the previously entered value. In other words, the data doesn't get written into EEPROM, can you spot the error?

Code:
read
LIST	p=16F88
	include "P16F88.inc"
	__config _CONFIG1, _WDT_OFF & _INTRC_IO & _MCLR_ON & _LVP_OFF 

 errorlevel	-302

		NEW   	equ     h'74'   ;EEPROM locations
		OLD 	equ     h'75'	

read
   	banksel   EEADR             ;Select Bank of EEADR
	movf 	 NEW, W  
	movwf 	 EEADR               ; Data Memory Address to 
	banksel   EECON1               ; Select Bank of EECON1
	bcf 	 EECON1, EEPGD   ; Point to Data memory
	bsf 	 EECON1, RD         ; EE Read
	banksel EEDATA                  ; Select Bank of EEDATA
	movf 	EEADR, W                                
	return
;_________________________________________________

write
   	banksel EECON1                 ; Select Bank of EECON1
	btfsc 	EECON1, WR                ; Wait for write
	goto 	$-1                        ; to complete
	banksel EEADR                     ; Select Bank of EEADR
	movf 	NEW, W                    
	movwf 	EEADR                   ;DATA Address to write
	movf 	NEW, W ;
	movwf 	EEDATA              ; DATA Value to write
	banksel EECON1                  ; Select Bank of EECON1
	bcf 	EECON1, EEPGD        ; Point to DATA memory
	bsf 	EECON1, WREN       ; Enable writes
	bcf 	INTCON, GIE        ; Disable INTs.
	movlw 	55h 
	movwf 	EECON2              ; Write 55h
	movlw 	h'AA' 
	movwf 	EECON2                ; Write AAh
	bsf 	EECON1, WR             ; Set WR bit to begin write
	bsf 	INTCON, GIE           ; Enable INTs.
	bcf 	EECON1, WREN         ; Disable writes
        	return
 
Code:
banksel EEADR  
movf NEW, W                    
movwf EEADR                   ;DATA Address to write
movf NEW, W ;
movwf EEDATA              ; DATA Value to write



What you are doing is reading the contents of GPR 0x74 in Bank 2 (EEADR) into W and then using that for the EEPROM address. What I think you intended to do is set the EEPROM Address to 0x74.

You need to change movf NEW, W to movlw NEW

You also need to change the line in your read routine which is also doing the same thing.
 
Last edited:
Thanks I'll try that. I saw the line but was not sure about what it was doing. I know one of them is for data, and the other for address, but I didn't know if another command was needed for address aquisition. I got the code from someone here.

I assume it's the first 'movf NEW' I have to change in the write call, and the only one in the 'read' call.
 
I'm working on it.

Obviously I was not finished debugging yet... :)

I got the value to go into the EEDATA register, but it doesn't stay in. When I unplug and restart, the EEPROM in EEDATA is FF. Of course, reading the EEADR and EEDATA registers helps figuring out what is going on.

Code:
read
   	banksel EEADR ; Select Bank of EEADR
	movlw 	NEW 
	movwf 	EEADR ; Data Memory Address to read
	banksel EECON1 ; Select Bank of EECON1
	bcf 	EECON1, EEPGD; Point to Data memory
	bsf 	EECON1, RD ; EE Read
	banksel EEADR ; Select Bank of EEDATA
	movf 	EEDATA, W ; W = EEDATA    
    
	return
;_________________________________________________

write
   	banksel EECON1 ; Select Bank of EECON1
	btfsc 	EECON1, WR ; Wait for write
	goto 	$-1 ; to complete
	banksel EEADR ; Select Bank of EEADR
	movlw 	NEW 
	movwf 	EEADR ; Data Memory Address to write
	movfw 	NEW
	movwf 	EEDATA ; Data Memory Value to write
	banksel EECON1 ; Select Bank of EECON1
	bcf 	EECON1, EEPGD ; Point to DATA memory
	bsf 	EECON1, WREN ; Enable writes
	bcf 	INTCON, GIE ; Disable INTs.
	movlw 	55h ;
	movwf 	EECON2 ; Write 55h
	movlw 	h'AA' ;
	movwf 	EECON2 ; Write AAh
	bsf 	EECON1, WR ; Set WR bit to begin write
	bsf 	INTCON, GIE ; Enable INTs.
	bcf 	EECON1, WREN ; Disable writes
        	return
 
If you post all your code we can run it and work out why it isn't working. Also, how do you know it isn't working? Are you reading the EEPROM with a programmer? Setting a breakpoint after the read?

Mike.
 
Code:
banksel EEADR ; Select Bank of EEADR
    movlw     NEW 
    movwf     EEADR ; Data Memory Address to write
    movfw     NEW
    movwf     EEDATA ; Data Memory Value to write
You're doing the same thing with the EEDATA, instead of movlw NEW you do movfw NEW.

Unless you initialised the GPR register pointed to by NEW, it could have anything in it, even 0xFF.

Do this and see if you have 0x96 in EEPROM address NEW

Code:
banksel EEADR ; Select Bank of EEADR
    movlw     NEW 
    movwf     EEADR ; Data Memory Address to write
    [COLOR=Red]movlw     0x96  ; dummy data to test write[/COLOR]
    movwf     EEDATA ; Data Memory Value to write
 
If you post all your code we can run it and work out why it isn't working. Also, how do you know it isn't working? Are you reading the EEPROM with a programmer? Setting a breakpoint after the read?

Mike.

Good question Pommie, I don't really know, I get the right value in EEDATA, and go through the write sequence, then unplug, then replug, and reset the connection. I don't really know how to work with the breakpoint, and I do read the EEPROM with the programmer in debug or released mode. I suppose that could be the problem right there.... me screwing it up as usual... :)

Hi Geko, I do get the right value in EEDATA (say 0x33), then I go through the write sequence, then I unplug the programmer (Firefly) and vary the AD input, then replug the firefly, then reconnect with the MPLAB, then I get the new AD value in EEDATA (say 0x25), not the old one. I haven't tried the reset button on the firefly, or breakpoints as Pommie suggested, mostly because I don't really know how to work with breakpoints.
 
Last edited:
Good question Pommie, I don't really know, I get the right value in EEDATA, and go through the write sequence, then unplug, then replug, and reset the connection. I don't really know how to work with the breakpoint, and I do read the EEPROM with the programmer in debug or released mode. I suppose that could be the problem right there.... me screwing it up as usual... :)

Hi Geko, I do get the right value in EEDATA (say 0x33), then I go through the write sequence, then I unplug the programmer (Firefly) and vary the AD input, then replug the firefly, then reconnect with the MPLAB, then I get the new AD value in EEDATA (say 0x25), not the old one. I haven't tried the reset button on the firefly, or breakpoints as Pommie suggested, mostly because I don't really know how to work with breakpoints.

If you're getting the new value and not the old one, then it seems fairly obvious that your code is writing the new value to the EEPROM - it can't really happen by accident.

Try posting your entire code.
 
Hi Geko, I do get the right value in EEDATA (say 0x33), then I go through the write sequence,

This doesn't make sense, you get the right value in EEDATA, then go through the write sequence. Well until you've done a write you haven't written anything to the EEPROM, all you've done is load the EEDATA register with the data you want to write - unless I've misunderstood what you've written.

If you write something to EEDATA then read it back without doing an EEPROM Read then it will contain whatever you just wrote to it, not the contents of the EEPROM.

The EEPROM read and write code you originally posted appears to be straight from the example in the datasheet so it 'should' be okay.

When you want to write to the EEPROM you
1. set EEADR to the address you want to write to.
2. put the data you want to write into the EEPROM in EEDATA
3. initiate an EERPOM write.
(EEDATA will still contain whatever you loaded into it in 2. regardless of whether the EEPROM write worked or not)

When you want to read from the EEPROM you
1. set EEADR to the EEPROM address you want to read from
2. initiate an EEPROM Read.
3. the value in EEDATA will then be whatever was in the EEPROM address pointed to by EEADR, it won't change unless you do a new read, or your code writes a new value to it.

Ensure you don't start an EEPROM read if the write is still in progress. In the example code you posted, it tests for a write in progress before starting a new write but the read code doesn't do that check.
 
Hi Geko, what I do is I write a value into the EEPROM, then unplug the chip. Now I replug the chip, and reconnect with the MPLAB, this resets all the registers to FF, then I go to the program, and my first command is the read. I haven't written anything yet. That's when I don't get the value I wrote previously but the value coming out of AD if I varied the pot. It's as if the chip would go through the whole program when initializing, including the write.

Pommie says to set a breakpoint after the read, and then what?

Everything else works, this is the last bug.

Hi Nigel, I don't want to post the whole code because it's a project in the works, and I don't want the code to be public. At least not yet. I understand it's hard to work with incomplete code, but I'm near the end, and only this has to be fixed, then I'm done.
 
Hi Geko, what I do is I write a value into the EEPROM,
You know it gets written, or you assume it gets written?


then unplug the chip. Now I replug the chip, and reconnect with the MPLAB, this resets all the registers to FF,

Why do you unplug and replug the chip as opposed to cycling the power to it?

What do you reconnect to MPLAB with?

Resets all what register to FF?

When you reconnect it to MPLAB you're not reprogramming the PIC and erasing the contents of the EEPROM in the process by any chance?

then I go to the program, and my first command is the read.
"then you go to the program" where? how? what?

I haven't written anything yet. That's when I don't get the value I wrote previously but the value coming out of AD if I varied the pot.

I don't understand where the AD value comes in to it? Are you writing this to EEPROM somewhere?

As far as I can see the basic EEPROM code you included in the original post is good, the problem is likely to be in the code outside of that but you won't post it here.

but I'm near the end, and only this has to be fixed, then I'm done.
Don't bet on it:)
 
Hi,
After setting the WR bit in EECON1, don't you need to wait for it to complete writing? As below:
Code:
bsf    EECON1,    WR   ;start writing
btfsc    EECON1,    WR  ;wait for writing completion
goto    $-1
 
I'm still trying to get the EEPROM to return the proper value each time I go through a write. So far, I only get the proper value on first write, that's when I go through the programming write. After that the value doesn't change when I go through the steps. Geko says the code is fine, so I'm looking for something else that might affect the write. Perhaps it's just me as usual that doesn't use the MPLAB correctly. I am writing in debug, and release mode. I have not tried the chip out of firefly. Maybe I should do that, and see how it works.

geko: You know it gets written, or you assume it gets written?

RD: The read sequence picks up the value, so it has to be written. It writes when I write the program, then it stays in, and never changes, even after subsequent writes.


geko: Why do you unplug and replug the chip as opposed to cycling the power to it?
What do you reconnect to MPLAB with?


RD: I unplug the firefly to power off the chip. And replug to power it up. Cycling power to the chip? I don't know how to do that. Does the firefly have a function for that?



geko: Resets all what register to FF?

RD: When I power up the chip, all registers are set to FF.


geko: When you reconnect it to MPLAB you're not reprogramming the PIC and erasing the contents of the EEPROM in the process by any chance?
"then you go to the program" where? how? what?


RD: No, I just replug, and re-establish contact with the chip using the button at the top of the MPLAB, then step through the program.


geko: I don't understand where the AD value comes in to it? Are you writing this to EEPROM somewhere?

RD: Yes that's the value I have to write in EEPROM, one single value.

geko: As far as I can see the basic EEPROM code you included in the original post is good, the problem is likely to be in the code outside of that but you won't post it here.

RD: Correct, the project is commercial and I don't want to publish the code in it's complete form. If you tell me where there might be conflict, I can look it up. Perhaps the clock is too fast for the EEPROM.

geko: Don't bet on it:)

RD: The rest of the code works fine, after this, I can hope to build the circuit without problems thank you... :)



Code:
read
  	banksel EEADR ; Select Bank of EEADR
	movlw 	NEW 
	movwf 	EEADR ; Data Memory Address to read
	banksel EECON1 ; Select Bank of EECON1
	bcf 	EECON1, EEPGD; Point to Data memory
	bsf 	EECON1, RD ; EE Read
	banksel EEADR ; Select Bank of EEDATA
	movf 	EEDATA, W ; W = EEDATA    

	return

write

	banksel EEADR ; Select Bank of EEADR
	movlw 	NEW 
	movwf 	EEADR 			; Data Memory Address to write
	movfw 	NEW
	movwf 	EEDATA 			; Data Memory Value to write
	banksel EECON1          ; Select Bank of EECON1
	bcf 	EECON1, EEPGD   ; Point to DATA memory
	bsf 	EECON1, WREN    ; Enable writes
	movlw 	55h 
	movwf 	EECON2          ; Write 55h
	movlw 	h'AA' 
	movwf 	EECON2          ; Write AAh
	bsf 	EECON1, WR      ; Set WR bit to begin write
	btfsc 	EECON1, WR      ; Wait for any write
	goto 	$-1
	bcf 	EECON1, WREN     ; Disable writes
	
	return
 
Last edited:
RD: The read sequence picks up the value, so it has to be written. It writes when I write the program, then it stays in, and never changes, even after subsequent writes.
Are you saying that when you program the code into PIC you also initialise the EEPROM?
And that value reads back okay when the code is running?
But the write EEPROM code running in the PIC doesn't change it?

RD: When I power up the chip, all registers are set to FF.
You make this hard work! You still haven't said what registers? EEPROM, SFR, GPR? I guess you mean EEPROM, if so either it's not ever writing to them, or it's getting erased, or the write routine is writing OxFF into it.


If it were me I would write a very simple program that attempts to write and read back a value to the EEPROM and then signal with LED's on a couple of I/O pins whether it is reading back what it expects. Run that on the PIC in a breadboard, without any connections to MPLAB/ICD2/PICKit programmers etc. Get that working, then see if still works as expected on the Firefly.

Can't help thinking that your code is not, for some reason, actually writing to the EEPROM at all.


Perhaps the clock is too fast for the EEPROM.
Unlikely unless you're running it out of spec' - to fast - to low voltage. RTFD(atasheet)
 
I'm still trying to get the EEPROM to return the proper value each time I go through a write. So far, I only get the proper value on first write, that's when I go through the programming write. After that the value doesn't change when I go through the steps. Geko says the code is fine, so I'm looking for something else that might affect the write. Perhaps it's just me as usual that doesn't use the MPLAB correctly. I am writing in debug, and release mode. I have not tried the chip out of firefly. Maybe I should do that, and see how it works.

Does the varible "NEW" stay the same each time you run the pgm?

Did you notice that you are useing "NEW" for the address and data, or did I read that wrong?

If I am wrong don't zing me too bad, I'm still learning too.

Mike.
 
try reading the eeprom data with the programmer before you remove power - my guess is you will NOT see what you wrote there. When you read with your program, you will see the value that the programmer saw.
 
Did you notice that you are useing "NEW" for the address and data, or did I read that wrong?

Hi Mike,
The code is actually writing the content of location 0x74 (movfw) to the EEPROM at location 0x74 (movlw).

@Robert
The fact that someone who is commissioned to write a commercial program comes on here asking newbie questions really scares me.:eek: I just hope this isn't any kind of crytical component.

Mike.
 
Hi Mike,
The code is actually writing the content of location 0x74 (movfw) to the EEPROM at location 0x74 (movlw).

@Robert
The fact that someone who is commissioned to write a commercial program comes on here asking newbie questions really scares me.:eek: I just hope this isn't any kind of crytical component.

Mike.


Rest assured Pommie, it's not a program to run an autopilot... :) Nothing critical.

I wrote a short version of the EEPROM that does the same thing, I read the old value, but not the new one. I increase the old value and write in into EEPROM, then unplug, replug, and run the program again, only to get 0x00. The new value did not write into EEPROM.

Could it be a bank issue...? Maybe the NEW register is at a wrong spot. I should perhaps try to put the NEW register at another location...?

Code:
	LIST	p=16F88
	include "P16F88.inc"
	__config _CONFIG1, _WDT_OFF & _INTRC_IO & _MCLR_ON & _LVP_OFF 

 errorlevel	-302


	Cblock	0x20
	TIMER1, TIMER2, VALUE, LEDON, STARTDELAY, 
	W0, W1, W2, W3, W4, W5, count, LBYTE, 
	endc
	
	HBYTE	equ	h'7F'
	NEW   	equ h'74'   ; EEPROM data
	OLD 	equ	h'75'	

   	banksel	TRISA		;bank 1
	movlw	0x42		;1MHz clock
	movwf	OSCCON
	movlw	0x07		;turn comparators off
	movwf	CMCON

	movlw	B'11111111'
	movwf	TRISB		;all input.
	movlw	B'00000010'	;all RA ports all outputs except A/D (RA1) input
	movwf	ANSEL
	movwf	TRISA
	movlw	B'00000000'
	movwf	OPTION_REG	;make all PORTB pins 1
	banksel	PORTA
	
 	goto	start


read
  	banksel EEADR ; Select Bank of EEADR
	movlw 	NEW 
	movwf 	EEADR ; Data Memory Address to read
	banksel EECON1 ; Select Bank of EECON1
	bcf 	EECON1, EEPGD; Point to Data memory
	bsf 	EECON1, RD ; EE Read
	banksel EEADR ; Select Bank of EEDATA
	movf 	EEDATA, W ; W = EEDATA    

	return

write

	banksel EEADR ; Select Bank of EEADR
	movlw 	NEW 
	movwf 	EEADR 			; Data Memory Address to write
	movfw 	NEW
	movwf 	EEDATA 			; Data Memory Value to write
	banksel EECON1          ; Select Bank of EECON1
	bcf 	EECON1, EEPGD   ; Point to DATA memory
	bsf 	EECON1, WREN    ; Enable writes
	movlw 	55h 
	movwf 	EECON2          ; Write 55h
	movlw 	h'AA' 
	movwf 	EECON2          ; Write AAh
	bsf 	EECON1, WR      ; Set WR bit to begin write
	btfsc 	EECON1, WR      ; Wait for any write
	goto 	$-1
	bcf 	EECON1, WREN     ; Disable writes
	
	return

start

	call	read
	movwf	OLD
	incf	OLD,f
	movfw	OLD
	movwf	NEW
	call	write
	
hang
 	goto hang
	end
 
Last edited:
I modified the code above to do a read immediately after write, and it shows the write did not happen. The code is not writing.

Now I remember there is an issue with the locations of the OLD and NEW registries.

Code:
	LIST	p=16F88
	include "P16F88.inc"
	__config _CONFIG1, _WDT_OFF & _INTRC_IO & _MCLR_ON & _LVP_OFF 

 errorlevel	-302


	Cblock	0x20
	TIMER1, TIMER2, VALUE, LEDON, STARTDELAY, 
	W0, W1, W2, W3, W4, W5, count, LBYTE, 
	endc
	
	HBYTE	equ	h'7F'
	NEW   	equ h'74'   ; EEPROM data
	OLD 	equ	h'75'	

   	banksel	TRISA		;bank 1
	movlw	0x42		;1MHz clock
	movwf	OSCCON
	movlw	0x07		;turn comparators off
	movwf	CMCON

	movlw	B'11111111'
	movwf	TRISB		;all input.
	movlw	B'00000010'	;all RA ports all outputs except A/D (RA1) input
	movwf	ANSEL
	movwf	TRISA
	movlw	B'00000000'
	movwf	OPTION_REG	;make all PORTB pins 1
	banksel	PORTA

 	goto	start


read
  	banksel EEADR ; Select Bank of EEADR
	movlw 	NEW 
	movwf 	EEADR ; Data Memory Address to read
	banksel EECON1 ; Select Bank of EECON1
	bcf 	EECON1, EEPGD; Point to Data memory
	bsf 	EECON1, RD ; EE Read
	banksel EEADR ; Select Bank of EEDATA
	movf 	EEDATA, W ; W = EEDATA    

	return

write

	banksel EEADR ; Select Bank of EEADR
	movlw 	NEW 
	movwf 	EEADR 			; Data Memory Address to write
	movfw 	NEW
	movwf 	EEDATA 			; Data Memory Value to write
	banksel EECON1          ; Select Bank of EECON1
	bcf 	EECON1, EEPGD   ; Point to DATA memory
	bsf 	EECON1, WREN    ; Enable writes
	movlw 	55h 
	movwf 	EECON2          ; Write 55h
	movlw 	h'AA' 
	movwf 	EECON2          ; Write AAh
	bsf 	EECON1, WR      ; Set WR bit to begin write
	btfsc 	EECON1, WR      ; Wait for any write
	goto 	$-1
	bcf 	EECON1, WREN     ; Disable writes
	
	return

start

	call	read
	movwf	OLD
	incf	OLD,f
	movfw	OLD
	movwf	NEW
	call	write
	
	nop
	nop

	call read

hang
 	goto hang

	end
 
Last edited:
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top