PDA

View Full Version : PIC16F684 + LCD to use the 256bytes of EEPROM - HELP



xnihilo
- 6th March 2008, 00:22
Hi guys,

I'm trying to use EEPROM fro PIC16F684 to keep some variables values stores for when the power is turned of.
When I write to EEPROM and then read it back, I get only crap, can you check it out?
I think it may be the LCDout of my variables contents because I use a led that blinks to show the value (i.e.: blink 3X if the value is 3)

Here is the code.

Thanks for any help.



----



DEFINE OSC 8 'set OSC value to 8MHz for instructions PAUSE, PAUSEus and SOUND. will use 8mhz int hs osc (default after reset: 4MHz)

'-----------------------------------------

'DEFINES FOR LCD
'MEMO: LCD can take about 1s to initialize

' Set LCD Data port
DEFINE LCD_DREG PORTC

' Set starting Data bit (0 or 4) if 4-bit bus = portC bit 0 for LCD Data bit 4
DEFINE LCD_DBIT 0

' Set LCD Register Select port, ENABLER WPU pour ce bit !!!!!!!!!!!!!!
DEFINE LCD_RSREG PORTA

' Set LCD Register Select bit
DEFINE LCD_RSBIT 4

' Set LCD Enable port
DEFINE LCD_EREG PORTA

' Set LCD Enable bit
DEFINE LCD_EBIT 5

' Set LCD bus size (4 or 8 bits)
DEFINE LCD_BITS 4

' Set number of lines on LCD
DEFINE LCD_LINES 2

' Set command delay time in us
DEFINE LCD_COMMANDUS 2000

' Set data delay time in us
DEFINE LCD_DATAUS 50



'-----------------------------------------
'PIC16F684: 2048 WORDS of flash program memory (datasheet p1)

'MEMO: PIC16F684 has 256 BYTES of EEPROM memory (datasheet p71-p74)
'Access: using WRITE and READ instruction in PBPpro
'Related registers: EECON1, EEDAT, EEADR
'EEIF bit (PIR1<7>) interrupt flag is set when write is complete. It must be cleared in software.
'INTERRUPTS MUST be disabled during read !!!!
'good practice: verify the data written after a write.
'IF USING assembler code to read and write, there is a specific sequence for instructions, see datasheet, p73

'WRITE
'WRITE Address,Value
'Write Value to the on-chip EEPROM at the specified Address.
'WRITE is used to set the values of the on-chip EEPROM at runtime.
'To set the values of the on-chip EEPROM at programming-time, use the DATA or EEPROM statement.
'Each WRITE is self-timed and takes about 10 milliseconds to execute on a PICmicro.
'If interrupts are used in a program, they must be turned off (masked, not DISABLEd) before executing a WRITE, and turned back on (if desired) after the write instruction is complete. An interrupt occurring during a WRITE may cause it to fail.
' WRITE 5,B0 ' Send value in B0 to EEPROM location 5
'To write a word, each of the 2 bytes that make up the word must be written separately:
'w Var Word
'WRITE 0,w.BYTE0
'WRITE 1,w.BYTE1
'READ
'READ Address,Var
'Read the on-chip EEPROM at the specified Address and stores the result in Var.
' READ 5,B2 ' Put the value at EEPROM location 5 into B2
'To read a word, each of the 2 bytes that make up the word must be read separately:
'w Var Word
'READ 0, w. BYTE0
'READ 1, w. BYTE1
'-----------------------------------------

'VARIABLES

max_mags VAR BYTE 'max carried mags
max_medics VAR BYTE 'max carried medic kits
rem_mags VAR BYTE 'remaining mags
rem_medics VAR BYTE 'remaining medic kits
i VAR BYTE 'counter var

'EEPROM memory locations for the backup of the variables
mem_max_mags CON 1
mem_max_medics CON 2
mem_rem_mags CON 3
mem_rem_medics CON 4

'--------------------------------------------------------------------------------------------------------------------------------------------


CLEAR


OSCCON = %01110001 'int osc, hs, 8mhz

CMCON0 = %00000111 'comparators OFF, val = 7

ANSEL = %00000000 'choose digital i/o, val = 0


OPTION_REG = %01111111 'enable internal porta weak pullups resistors (no weak pull-up available for porta.3), p12. they bring pin to High state; to set a change, pull pin to ground
WPUA = %010011 'enable weak pull ups individually on portA, rem: porta.3 (MCLR) has no internal weak pullups

INTCON = %10001000 'enable GIE and porta interrupts on change, datasheet p13
IOCA = %000011 'enable interrupts on change individually (for porta)


TRISA = %000011 'a4 and a5 are outputs (to lcd pins)
TRISC = %000000

PORTA = %000000 'turn off porta pins (initialize to Low state = 0v)
PORTC = %000000 'turn off portc pins (initialize to Low state = 0v)
'porta pins with weak pullups will be set to high (i.e. 5v by the pullups)

'--------------------------------------------------------------------------------------------------------------------------------------------


Symbol ammo = PORTA.0 'for interrupt request
Symbol medic = PORTA.1
'Symbol unuseda1 = PORTA.2
'Symbol unuseda2 = PORTA.3
Symbol en = PORTA.4
Symbol rs = PORTA.5

Symbol data0 = PORTC.0
Symbol data1 = PORTC.1
Symbol data2 = PORTC.2
Symbol data3 = PORTC.3
Symbol backlight = PORTC.4
Symbol signal = PORTC.5

'--------------------------------------------------------------------------------------------------------------------------------------------

'SETTING VARIABLES 'CLEAR command has reset them

max_mags = 1 'available ammo mag when device is turned on
max_medics = 2 'available medic kits when device is turned on
rem_mags = 3 'remaining ammo mags
rem_medics = 4 'remaining medic kits


'--------------------------------------------------------------------------------------------------------------------------------------------






ON INTERRUPT GOTO mainroutine 'when interrupt occurs on portA pin a0 or pin a1 go to int routine

'--------------------------------------------------------------------------------------------------------------------------------------------


START:

FLAGS = 0 'IF LCD IS powered off while in action



HIGH signal
PAUSE 500
LOW signal
HIGH signal
PAUSE 500
LOW signal
HIGH signal
PAUSE 500
LOW signal
HIGH signal
PAUSE 500
LOW signal

HIGH backlight 'turn on backlight
LCDOUT $FE, 1 'clear
LCDOUT $FE, 2 'to home position
LCDOUT "SUPPLIER"
LCDOUT $FE, $c0 'move at begining of 2nd line
LCDOUT "MODULE"
PAUSE 3000 'pause 3s
LCDOUT $FE, 1 'clear
LOW backlight 'turn of backlight

HIGH signal
PAUSE 500
LOW signal
HIGH signal
PAUSE 500
LOW signal
HIGH signal
PAUSE 500
LOW signal
HIGH signal
PAUSE 500
LOW signal

GOSUB displayval

max_mags = 0 'available ammo mag when device is turned on
max_medics = 0 'available medic kits when device is turned on
rem_mags = 0 'remaining ammo mags
rem_medics = 0 'remaining medic kits

GOSUB displayval


WRITE mem_max_mags,5
WRITE mem_max_medics,6
WRITE mem_rem_mags,7
WRITE mem_rem_medics,8


READ mem_max_mags,max_mags
READ mem_max_medics,max_medics
READ mem_rem_mags,rem_mags
READ mem_rem_medics,rem_medics

GOSUB displayval












'--------------------------------------------------------------------------------------------------------------------------------------------



loop1: 'main program is a stupid loop waiting for a int on change triggered on porta.0 or porta.1 (high to low)
'shortest pause possible to quickly jump to int routine

'at 8MHz, minimum delay is 12 uS (or 24 uS at 4MHz)
HIGH signal
PAUSE 500
LOW signal
PAUSE 500

GOTO loop1



'or should we use SLEEP, an int will wake the uc up (uses WatchDogTimer !)

'--------------------------------------------------------------------------------------------------------------------------------------------

DISABLE 'disable interrupts while executing the interrupt routine (do not put check interrupts calls after each instruction)
mainroutine: 'int routine code starts here
'-------------
donothing:
RESUME 'resume program where it left for the interrupt routine
ENABLE










displayval:
HIGH backlight
LCDOUT $FE, 1 'clear
LCDOUT $FE, 2 'to home position
LCDOUT "maxmag"
LCDOUT $FE, $c0 'move at begining of 2nd line
LCDOUT max_mags
PAUSE 2000 'pause 3s
LCDOUT $FE, 1

FOR i = 0 to max_mags
HIGH signal
PAUSE 300
LOW signal
next i

'clear

LCDOUT $FE, 1 'clear
LCDOUT $FE, 2 'to home position
LCDOUT "maxmed"
LCDOUT $FE, $c0 'move at begining of 2nd line
LCDOUT max_medics
PAUSE 2000 'pause 3s
LCDOUT $FE, 1 'clear

FOR i = 0 to max_medics
HIGH signal
PAUSE 300
LOW signal
next i

LCDOUT $FE, 1 'clear
LCDOUT $FE, 2 'to home position
LCDOUT "remmag"
LCDOUT $FE, $c0 'move at begining of 2nd line
LCDOUT rem_mags
PAUSE 2000 'pause 3s
LCDOUT $FE, 1 'clear

FOR i = 0 to rem_mags
HIGH signal
PAUSE 300
LOW signal
next i

LCDOUT $FE, 1 'clear
LCDOUT $FE, 2 'to home position
LCDOUT "remmed"
LCDOUT $FE, $c0 'move at begining of 2nd line
LCDOUT rem_medics
PAUSE 2000 'pause 3s
LCDOUT $FE, 1

FOR i = 0 to rem_medics
HIGH signal
PAUSE 300
LOW signal
next i

LOW backlight
RETURN

END

skimask
- 6th March 2008, 14:36
DEFINE OSC 8
DEFINE LCD_DREG PORTC
DEFINE LCD_DBIT 0
DEFINE LCD_RSREG PORTA
DEFINE LCD_RSBIT 4
DEFINE LCD_EREG PORTA
DEFINE LCD_EBIT 5
DEFINE LCD_BITS 4
DEFINE LCD_LINES 2
DEFINE LCD_COMMANDUS 2000
DEFINE LCD_DATAUS 50
max_mags var byte:max_medics var byte:rem_mags var byte:rem_medics var byte
i var byte:mem_max_mags con 1:mem_max_medics con 2:mem_rem_mags con 3
mem_rem_medics con 4:ammo var porta.0:medic var porta.1:backlight var portc.4
signal var portc.5:blinkcount var byte:delaytemp var word:clear:osccon=$71
cmcon0=7:ansel=0:option_reg=$7f:wpua=$13:intcon=$8 8:ioca=3:trisa=3:trisc=0
porta=0:portc=0:max_mags=1:max_medics=2:rem_mags=3 :rem_medics=4
ON INTERRUPT GOTO mainroutine
START: flags=0:for blinkcount=1 to 5:signal=1:pause 500:signal=0:pause 500
next blinkcount:backlight=1:lcdout $fe,1,"SUPPLIER",$fe,$c0,"MODULE"
pause 3000:backlight=0:for blinkcount=1 to 5:signal=1:pause 500:signal=0
pause 500:next blinkcount:gosub displayval:max_mags=0:max_medics=0:rem_mags=0
rem_medics=0:gosub displayval
DISABLE 'DISABLE ANY SOFTWARE INTERRUPTS
intcon.7 = 0 'DISABLE INTERRUPTs IN HARDWARE
write mem_max_mags,5:pause 25:write mem_max_medics,6:pause 25
write mem_rem_mags,7:pause 25:write mem_rem_medics,8:pause 25
intcon.7 = 1 'RE-ENABLE INTERRUPTs IN HARDWARE
ENABLE 'RE-ENABLE PBP SOFTWARE INTERRUPTS
read mem_max_mags,max_mags:read mem_max_medics,max_medics
read mem_rem_mags,rem_mags:READ mem_rem_medics,rem_medics:GOSUB displayval
loop1: gosub blinksignalx5:goto loop1
DISABLE
mainroutine:
donothing:
RESUME
ENABLE
displayval: backlight=1:lcdout $fe,1,"maxmag",$fe,$c0,dec3 max_mags
pause 2000:lcdout $fe,1:for i=0 to max_mags:signal=1:pause 300:signal=0
pause 300:next i:lcdout $fe,1,"maxmed",$fe,$c0,dec3 max_medics:pause 2000
for i=0 to max_medics:signal=1:pause 300:signal=0:pause 300:next i
lcdout $fe,1,"remmag",$fe,$c0,dec3 rem_mags:pause 2000:for i=0 to rem_mags
signal=1:pause 300:signal=0:pause 300:next i
lcdout $fe,1,"remmed",$FE, $c0,DEC3 rem_medics:pause 2000
for i=0 to rem_medics:signal=1:pause 300:signal=0:pause 300:next i:backlight=0
return
END

Give that a shot and see if it works...

xnihilo
- 6th March 2008, 22:34
Hi guys,

Thanks for your help.
Today, I read the docs for PICBASIC pro compiler and discovered that a # had to be added to display the ascii value. In fact I read this before but it never occured to me it could be important.
I wrothe a #before the variable name and ... miracle, the value displayed right on my LCD, inf fact it was just displaying *some* value of the byte, not in ascii so I was seeing strange characters.

I still have a technical question.
I read that if used as Input pin, the pin 4 (RA3) had to be linked to VDD thoough a pull up resistor to prevent erratic behavior of the PIC. Is that right? What then should be the value of the resistor? 10K?

As for now, no pull up is connected to the MCLR pin and everything works fine.

skimask
- 7th March 2008, 14:19
Thanks for your help.
Today, I read the docs for PICBASIC pro compiler and discovered that a # had to be added to display the ascii value. In fact I read this before but it never occured to me it could be important.
Which is what I did with DEC3.


I still have a technical question.
I read that if used as Input pin, the pin 4 (RA3) had to be linked to VDD thoough a pull up resistor to prevent erratic behavior of the PIC. Is that right? What then should be the value of the resistor? 10K?
10K is fine.