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.

Data EEPROM write problem

Status
Not open for further replies.

Nigel Goodwin

Super Moderator
Most Helpful Member
Can anyone see why this data EEPROM routine doesn't work?, it's driving me mad :D

I'm using a 16F648a, and I've used the same routine on the 16F628 in the past.

Code:
; ***********************************************************************
; EE_Write - Routine to write a byte to EEPROM 
; Address in EE_Address, data in W
EE_Write
				bsf 	STATUS,	RP0 		; Bank 1
				bsf		EECON1,	WREN 		; Enable write
				bcf 	INTCON, GIE 		; Disable INTs
				movwf	EEDATA				; set EEPROM data
				movfw	EE_Address
				movwf	EEADR				; set EEPROM address
				movlw	0x55
				movwf	EECON2 				; Write 55h
				movlw	0xAA
				movwf	EECON2 				; Write AAh
				bsf		EECON1,	WR 			; Set WR bit
				bsf 	INTCON, GIE 		; Enable INTs
											; begin write
				bcf 	STATUS,	RP0 		; Bank 0
		
				btfss	PIR1,	EEIF		; wait for write to complete.
				goto	$-1
				bcf		PIR1,	EEIF		; and clear the 'write complete' flag
				bsf 	STATUS,	RP0 		; Bank 1
				bcf		EECON1,	WREN 		; Disable write
				bcf 	STATUS,	RP0 		; Bank 0
				return
 
Interfering interrupt, maybe?

Hola Nigel,

Since you enable interrupts prior the writing is complete, is it possible that another interrupt is interfering with it?
 
Hola Nigel,

Since you enable interrupts prior the writing is complete, is it possible that another interrupt is interfering with it?

I don't think so, the interrupts are only enabled after the write - however, I've just tried moving the enable to the end of the routione, and it still doesn't work.
 
Are you sure it's your write and not your read that is messed up? Or do you see it hanging in ICD?

Do you have the WDT running?

What happens if you poll the eecon1 WR bit instead of the EEIF?

Are you sure the EEPROM isn't "overburned"?
 
Are you sure it's your write and not your read that is messed up? Or do you see it hanging in ICD?

It doesn't hang, the content just doesn't change.

I've read it back via PICKit2 as well to confirm it's not changed.

Do you have the WDT running?

No.

What happens if you poll the eecon1 WR bit instead of the EEIF?

I tried it, no change.

Are you sure the EEPROM isn't "overburned"?

It's a new PIC, and the EEPROM programmes fine from the PICKit2.

I've got another somewhere, I'll have to try it.
 
hi Nigel,
Set the EE_Address at 0x7F, the shared Banking, if its in the lower Bank0 is dosn't work, at 0x7F it writes OK.

Code:
    list      p=16F648A           
    #include <p16F648A.inc>
    errorlevel  -302  , -207        

EE_Address equ 0x7f

     org 0x000
    goto start
    
        
start:
    org 0x0004
    
    movlw 0x11
    movwf EE_Address
    movlw "A"
    call EE_Write
    
    movlw 0x12
    movwf EE_Address    
    movlw "B"
    call EE_Write

trap: goto trap

; ***********************************************************************
; EE_Write - Routine to write a byte to EEPROM 
; Address in EE_Address, data in W
EE_Write
                bsf     STATUS,    RP0         ; Bank 1
                bsf    EECON1,    WREN         ; Enable write
                bcf     INTCON, GIE         ; Disable INTs
                movwf    EEDATA                ; set EEPROM data
                            
                movfw    EE_Address
                movwf    EEADR                ; set EEPROM address
                movlw    0x55
                movwf    EECON2                 ; Write 55h
                movlw    0xAA
                movwf    EECON2                 ; Write AAh
                bsf    EECON1,    WR             ; Set WR bit
                bsf     INTCON, GIE         ; Enable INTs
                                            ; begin write
                bcf     STATUS,    RP0         ; Bank 0
        
                btfss    PIR1,    EEIF        ; wait for write to complete.
                goto    $-1
                bcf        PIR1,    EEIF        ; and clear the 'write complete' flag
                bsf     STATUS,    RP0         ; Bank 1
                bcf        EECON1,    WREN         ; Disable write
                bcf     STATUS,    RP0         ; Bank 0
                return
                
                
                end
 

Attachments

  • AAesp04.gif
    AAesp04.gif
    9.5 KB · Views: 225
Last edited:
Can anyone see why this data EEPROM routine doesn't work?, it's driving me mad :D

I'm using a 16F648a, and I've used the same routine on the 16F628 in the past.

What bank is the GP RAM register labeled EE_Address in? If it's in Bank 0 it will not pull the address stored in that register into EEADR while you're in bank 1.

Also, interrupts should not be enabled until after the write is complete. You can still poll the EEIF without the interrupts being enabled.

On my write routine I usually poll EECON1,WR instead of PIR1,EEIF so that I don't have to switch banks until the write is complete (EECON1,WR gets cleared by the hardware once the write is complete). Then I clear EECON1,WREN, switch banks, then clear PIR1,EEIF. Also, I get the address and data written to EEADR and EEDATA prior to calling the write routine.

Here's the code I typically use for the 16F628 -

Code:
;EEPROM Write Setup Code (Pre-Write Call)			
			
				movlw		value of EEPROM write addres
				banksel		EEADR		;bank 1
				movwf		EEADR		;copy address value to EEADR
				banksel		0x00		;bank 0
				movfw		Address containing data to be written
				banksel		EEDATA		;bank 1
				movwf		EEDATA		;copy data to be written to EEPROM to EEDATA
				call		EE_Write	;call EEPROM Write subroutine



; ***********************************************************************
; EE_Write - Routine to write a byte to EEPROM 
; Address in EE_Address, data in W
EE_Write				
				bcf		INTCON,GIE		;disable interrupts
				banksel		EECON1			;Bank 1
				bsf		EECON1,WREN		;enable Write
				movlw		0x55			;write unlock codes
				movwf		EECON2
				movlw		0xAA
				movwf		EECON2
				bsf		EECON1,WR		;start write
				btfsc		EECON1,WR		;is write complete?
				goto		$-1                     ;no, go back and wait for write to complete
				bcf		EECON1,WREN		;yes, disable write
				banksel		PIR1			;bank 0
				bcf		PIR1,EEIF		;clear write complete flag
				bsf		INTCON,GIE		;enable interrupts
				return

Hope this helps.
 
Last edited:
I use this for the 16f886

This bit of code, uses the FSR to write blocks of GPR into EEPROM.

Code:
EEpromWrite;  write 'Tmp3' number of GPR bytes into EEPROM address starting at 'wreg' value. FSR preloaded to GPR start addr.
		;FSR set for bank0,1, ; bank 2,3 GPR requires 'bsf STATUS,IRP' for FSR to work on those GPR. Preset this b4 calling this code.
	banksel EEADR
	movwf EEADR ; store dest. eprom address
	incf Tmp3,f ; compensate for decfsz. Tmp3 is a multibank register
EEWloop	decfsz Tmp3,f ; skip next if 0, else
	goto Dowrite 
	clrf STATUS; bank0, irp clr etc.
        return
Dowrite ; perform write of a gpr byte to eeprom.
	movf INDF,w;get gpr data
Dwrite	movwf EEDAT ; data value to write
	banksel EECON1
	bcf EECON1,EEPGD; set to ee data mem
	bsf EECON1,WREN; enable ee write
	bcf INTCON,GIE; halt ISRs
	btfsc INTCON,GIE
	goto $-2 ; verify isr halts
	
	movlw 0x55 ; required
	movwf EECON2; required
	movlw 0xAA; required
	movwf EECON2 ; write AA
	bsf EECON1,WR; begin write
	
; now test if write is complete
	btfsc	EECON1,WR	;WAIT FOR
	goto	$-1		;WRITE TO FINISH
	bsf INTCON,GIE; enable isrs
	bcf EECON1,WREN; disable write
	banksel EEADR
	incf FSR,f ; pt to next GPR byte, bank 0/1
	incfsz EEADR,f ; next EEprom byte, skip if overflow of the eeprom bank.
	goto EEWloop
	clrf STATUS; bank0, irp clr etc.
	return
 
On my write routine I usually poll EECON1,WR instead of PIR1,EEIF so that I don't have to switch banks until the write is complete (EECON1,WR gets cleared by the hardware once the write is complete). Then I clear EECON1,WREN, switch banks, then clear PIR1,EEIF. Also, I get the address and data written to EEADR and EEDATA prior to calling the write routine.

I agree.Also I assign the EEPROM memory locations before the end directive.

ex :
ORG 0x2100
DE 0x00, 0x01, 0x02, 0x03
 
I agree.Also I assign the EEPROM memory locations before the end directive.

ex :
ORG 0x2100
DE 0x00, 0x01, 0x02, 0x03

I already do that, it's actually for storing the phone number to call, but it needs to be able to be updated via a text message - the original number (programmed in) works fine, but the update routine doesn't alter it at all, and in fact doesn't alter ANY of the 256 EEPROM locations, which I presume eliminates the GPR bank problem? (but I'll still give it a try tonight).

It's really annoying! :D
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top