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.

Accessing EEPROM

Status
Not open for further replies.

Clayton

New Member
Hi,

Im just starting out with the PICs. Im currently using the PIC16F628 to play with.

My objective is to make an LED controller that has multiple light patterns, etc. Thanks to Nigel Goodwin's site and others I have that part covered. I will be using a momentary switch to change the patterns. Again, that has been adequately explained.

Now I am stuck on saving the pattern. That is, I want to be able to store pattern number 8 as the startup pattern instead of having to cycle through 7 other patterns every time I start up the LEDs.

My first guess is using the 128bytes of EEPROM, however I am more than willing to entertain other suggestions. I am sure this has been addressed, however I have been unsuccessful in my attempt to find the code or tutorial applicable.

Thanks,
Clayton
 
I have run into another problem. I have attempted to use the EE_Write and EE_read subroutines from the above tutorial, yet my chip doesnt cooperate. It works fine w/o the eeprom routines.

Here are the routines as I have them now, with minor modifications to meet my program:

EE_Read
bsf STATUS, RP0 ; Bank 1
movlw EEPROM_Addr
movwf EEADR ; Address to read
bsf EECON1, RD ; EE Read
movf EEDATA, W ; W = EEDATA
bcf STATUS, RP0 ; Bank 0
movwf PatternCount ; returns value of pattern
call CheckSwitch ; calls routine to select pattern

EE_Write
movfw PatternCount ; read current value
bsf STATUS, RP0 ; Bank 1
bsf EECON1, WREN ; Enable write
movwf EEDATA ; set EEPROM data
movlw EEPROM_Addr
movwf EEADR ; set EEPROM address
movlw 0x55
movwf EECON2 ; Write 55h
movlw 0xAA
movwf EECON2 ; Write AAh
bsf EECON1, WR ; Set WR bit
; 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
retlw 0x00

PatternCount is my defined variable.
I have defined EEPROM_Addr as Equ 0x00.

I did not see any of the other labels being defined in Nigel's tutorial so I presume they are understood by the MPLAB IDE.

Again, I have searched around, including on this site, but I cant make heads or tails of this matter. Any and all help greatly appreciated.

Thanks,
Clayton
 
You should not define EEPROM_Addr as equ 00.

You should define EEPROM_Addr to somewhere that is user RAM. Such as 0x20. You should then write zero to EEPROM_Addr.

So, at the top of your code you would have,

EEPROM_Addr Equ 0x20

Or some other address that is not used for something else.

And then in you main code you would have either,
clrf EEPROM_Addr
Or,
movlw 0x00
movwf EEPROM_Addr

HTH

Mike.
 
P.S. You can see if your write routine is working by putting the chip back in the programmer and reading it.

Mike.
 
Pommie,

I see what you're getting at. I modifed the above to look like this:

movf 0x00, w ; read current value
bsf STATUS, RP0 ; Bank 1
bsf EECON1, WREN ; Enable write
movwf EEDATA ; set EEPROM data
movlw 0x2100
movwf EEADR ; set EEPROM address
movlw 0x55
movwf EECON2 ; Write 55h
movlw 0xAA
movwf EECON2 ; Write AAh
bsf EECON1, WR ; Set WR bit
; 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
movlw 0x02
movwf PORTB
retlw 0x00

As you see, I changed the address of EEADR to 0x2100. The LED at 0x02 on PORTB lights up indicating completion of the routine, but the change in not reflected when I read the chip. Any other suggestions?

Thanks,
Clayton
 
So how do you expect to fit 0x2100 in an 8 bit variable?.

My tutorial routine is fully working, why not use it 'as is' to prove it works, THEN try and modify it to do exactly what you want.
 
As always, Mr. Goodwin, you are doing a fine job of exposing poor PIC/electronics understanding by us new guys. Believe it or not, I do appreciate it.

As to your suggestion, I did take it. Here it is in its current version.

EE_Write
movf PatternCount, w ; read current value
bsf STATUS, RP0 ; Bank 1
bsf EECON1, WREN ; Enable write
movwf EEDATA ; set EEPROM data
movlw 0x00
movwf EEADR ; set EEPROM address
movlw 0x55
movwf EECON2 ; Write 55h
movlw 0xAA
movwf EECON2 ; Write AAh
bsf EECON1, WR ; Set WR bit
; 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
retlw 0x00

As you see, not much has changed. I changed the initial f register to PatternCount and I hard coded 0x00 into EEADR instead of using a constant. Minor change, really.

Refresher on my program, I am using a table to sequence the LEDs. PatternCount is what I am using to store the counter in. Each time the switch is pressed, PatternCount is increased. I know this part is working as the LED patterns do change. However, the EE_Write is not writing this to the EEPROM. I have the Call to EE_Write immediately before the increment counter commands in the same routine. Therefore, every time the pattern is changed EE_Write should be firing and updating the EEPROM. However, that is not the case. I am hoping that either you or someone else might have an idea.

Thanks,
Clayton
 
Nigel,

Due to the size of the program (252 lines) I decided to email it to you. It went to the lpilsley.co.uk account.

Anyone else interested in helping, I will be glad to email other copies after I wake up this afternoon.

Thanks,
Clayton
 
Ok, I just found out how to post the code in that scrolling window. So here is the program.

Code:
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Sequence of LEDs						;
;Author Clayton Bradley					;
;This version cycles through different	;
;possibilities.  Also allows selection	;
;of a specific pattern by means of a 	;
;momentary switch 						;
;Credit due to Nigel Goodwin for various;
;routines borrowed throughout this 		;
;program.								;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


	LIST	p=16F628			;tell assembler what chip we are using
	include "P16F628.inc"		;include the defaults for the chip
	__config 0x3D18				;sets the configuration settings (oscillator type etc.)

	cblock 	0x20 				;start of general purpose registers
		count1 					;used in delay routine
		counta 					;used in delay routine 
		countb 					;used in delay routine
		LightVal				;the lit LED
		StrobeCount 			;Counter for number of times the LED strobes
		StrobeTimes				;number of times the LED strobes
		PatternCount			;Choose pattern
	endc

	SWPORT equ PORTB
	SW1 equ	0x00
	AllLEDs equ b'11000110'		;Just a bunch of easy to use mnemonics for the LEDs
	LeftLEDs equ b'00000110'
	RightLEDs equ b'11000000'
	TopLEDs equ b'01000010'
	BottomLEDs equ b'10000100'
	LeftXLEDs equ b'10000010'
	RightXLEDs equ b'01000100'
	LED1 equ b'00000010'
	LED2 equ b'00000100'
	LED3 equ b'01000000'
	LED4 equ b'10000000'
	PatternNumber equ 0x07
	org		0x0000				;org sets the origin, 0x0000 for the 16F628,
								;this is where the program starts running	
	movlw	0x07
	movwf	CMCON				;turn comparators off (make it like a 16F84)
   	bsf 	STATUS,		RP0		;select bank 1
   	movlw 	b'00000001'			;set PortB all outputs except port 0
   	movwf 	TRISB
	bcf		STATUS,		RP0		;select bank 0
	movlw 	0x03				;moves the number 3 into StrobeTimes
	movwf	StrobeTimes			;number of times the LEDs strobe
	clrf	PatternCount		;initialize Pattern Count
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;Start of Program routine;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	call	EE_Read

CheckSwitch
	call	EE_Write
CSDelay
	call	Delay_On				;allow time for debounce
	btfss	SWPORT,	SW1				;check if momentary switch has returned to open
	call	CSDelay					;if not, cycle through again
	incf	PatternCount, 0			;increase pattern count, so as to cycle through next pattern
	xorlw	PatternNumber			;check for last entry by xoring value in Pattern Number with Pattern Count
	btfsc	STATUS,	Z				;check status bit to see if set, if so, Pattern Count higher than Pattern Number
	clrf	PatternCount			;if status set, reset Pattern Count
	movfw	PatternCount			;move value of Pattern Count to W to be used in choosing from table
	incf	PatternCount			;increase Pattern Count to next value
	call 	PatternTable			;now got to Pattern Table to select the next pattern

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;CODE TO STROBE LEDS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Strobe_LED						;code for strobing the LEDs

	movwf 	LightVal			;moves the LED code in the W reg into LightVal for safekeeping
	movfw 	StrobeTimes			;moves the value of StrobeTimes into the W register
	movwf	StrobeCount			;moves the value to the W register into StrobeCount

StrobeLoop
	movfw	LightVal			;move LightVal into W
	movwf	PORTB				;move W into PORTB to turn on selected LEDs
	btfss	SWPORT,	SW1
	call	CheckSwitch
	call	Delay_On			;call the delay we set for LED on time
	movlw	0x00				;moves value for LEDs off into W
	movwf 	PORTB				;sets PORTB to off
	btfss	SWPORT,	SW1
	call	CheckSwitch
	call	Delay_Off			;calls the delay set for time LED off
	decfsz	StrobeCount, 1		;decreases StrobeCount, skip if zero
	call	StrobeLoop			;loops back for another flash
	retlw 	0x00				;return code

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EEPROM ROUTINE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

EE_Write
	movf	PatternCount,	w	; read current value
	bsf 	STATUS,	RP0 		; Bank 1
	bsf		EECON1,	WREN 		; Enable write
	movwf	EEDATA				; set EEPROM data
	movlw	0x00
	movwf	EEADR				; set EEPROM address
	movlw	0x55
	movwf	EECON2 				; Write 55h
	movlw	0xAA
	movwf	EECON2 				; Write AAh
	bsf		EECON1,	WR 			; Set WR bit
									; 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
	retlw 0x00

EE_Read		
	bsf 	STATUS,	RP0 		; Bank 1
	movlw 	0x00
	movwf 	EEADR				; Address to read
	bsf 	EECON1,	RD 			; EE Read
	movf 	EEDATA,	W 			; W = EEDATA
	bcf 	STATUS,	RP0 		; Bank 0
	movwf	PatternCount		; restore previous value
	retlw	0x00

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;LED LOOPS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

WigWag_Loop						;loop for the WigWag option
	call 	WigWag_LEDs			;calls the actual code of WigWag
	goto 	WigWag_Loop			;continuous loop
	
X_Loop
	call 	X_LEDs				;calls the actual code of X_LED
	goto	X_Loop

TopAndBottom_Loop				;loop for TopAndBottom option
	call 	TopAndBottom_LEDs	;calls the actual code of TopAndBottom
	goto 	TopAndBottom_Loop	;continuous loop

Sequence_Loop					;loop for Sequence option
	call	Sequence_LEDs		;calls the actual code of Sequence
	goto	Sequence_Loop			;continuous loop

ZigZag_Loop						;loop for ZigZag
	call 	ZigZag_LEDs			;calls the actual code of ZigZag
	goto 	ZigZag_Loop			;continuous loop

All_Loop						;calls a variety of flash patterns
	call 	All_LEDs
	call 	All_LEDs
	call 	WigWag_LEDs
	call 	WigWag_LEDs
	call	X_LEDs
	call	X_LEDs
	call 	TopAndBottom_LEDs
	call 	TopAndBottom_LEDs
	call 	Sequence_LEDs
	movlw	LED1			
	call 	Strobe_LED
	call 	ZigZag_LEDs
	movlw	LED1				
	call 	Strobe_LED
	goto	All_Loop			


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;LED CALLS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


All_LEDs						;code for flashing all LEDs
	movlw AllLEDs				;move all LEDs into W
	call Strobe_LED				;strobe
	retlw 0x00					;return code

WigWag_LEDs						;code for WigWag pattern
	movlw	LeftLEDs			;move left LEDs into W
	call 	Strobe_LED			;strobe
	movlw	RightLEDs			;move right LEDs into W
	call 	Strobe_LED			;strobe
	retlw 	0x00				;return code

X_LEDs							;code for flashing an X pattern
	movlw 	LeftXLEDs			;move top left and bottom right LEDs into W
	call 	Strobe_LED			;strobe
	movlw 	RightXLEDs			;move bottom left and top right LEDs into W
	call	Strobe_LED			;strobe
	retlw	0x00				;return code

TopAndBottom_LEDs				;code for top and bottom pattern
	movlw	TopLEDs				;move top row of LEDs into W
	call 	Strobe_LED			;strobe
	movlw	BottomLEDs			;move bottom row of LEDs into W
	call 	Strobe_LED			;strobe
	retlw 	0x00				;return code

Sequence_LEDs					;code for sequence of LEDs
	movlw	LED1				;move top left LED into W
	call 	Strobe_LED			;strobe
	movlw	LED2				;move bottom left LED into W
	call 	Strobe_LED			;strobe
	movlw	LED3				;move top right LED into W
	call 	Strobe_LED			;strobe
	movlw	LED4				;move bottom right LED into W
	call 	Strobe_LED			;strobe
	movlw	LED3				;move top right LED into W
	call 	Strobe_LED			;strobe
	movlw	LED2				;move bottom left LED into W
	call 	Strobe_LED			;strobe
	retlw 	0x00				;return code

ZigZag_LEDs						;code for zigzagging LEDs
	movlw	LED1				;move top left LED into W
	call 	Strobe_LED			;strobe
	movlw	LED3				;move top right LED into W
	call 	Strobe_LED			;strobe
	movlw	LED2				;move bottom left LED into W
	call 	Strobe_LED			;strobe
	movlw	LED4				;move bottom right LED into W
	call 	Strobe_LED			;strobe
	movlw	LED2				;move bottom left LED into W
	call 	Strobe_LED			;strobe
	movlw	LED3				;move top right LED into W
	call 	Strobe_LED			;strobe
	retlw 	0x00				;return code


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;DELAY CODE;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Delay_On						
	movlw	d'40'				;delay 40 ms (4 MHz clock)
	movwf	count1
d1	movlw	0xC7
	movwf	counta
	movlw	0x01
	movwf	countb
Delay_0
	decfsz	counta, f
	goto	$+2
	decfsz	countb, f
	goto	Delay_0

	decfsz	count1	,f
	goto	d1
	retlw	0x00

Delay_Off	
	movlw	d'75'				;delay 75 ms (4 MHz clock)
	movwf	count1
d2	movlw	0xC7
	movwf	counta
	movlw	0x01
	movwf	countb
Delay_1
	decfsz	counta, f
	goto	$+2
	decfsz	countb, f
	goto	Delay_1

	decfsz	count1,	f
	goto	d2
	retlw	0x00
	


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;LED PATTERN TABLE;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PatternTable
	addwf	PCL, f					;add W from Check Switch to the PCL to select proper pattern
	call 	WigWag_Loop
	call 	TopAndBottom_Loop
	call	X_Loop	
	call 	Sequence_Loop
	call 	ZigZag_Loop
	call	All_Loop			
end

Any help greatly appreciated.

Thanks,
Clayton
 
Last edited:
Turns out, I was having some stack overflow issues also. They never became a problem until I tried to use the EEPROM routines.

Thanks again to any and all who scratched their heads on my behalf.
Clayton
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top