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

reading writing to eeprom

Visitor

Active Member
Since MrDEB couldn't be arrsed to try the simple experiment I suggested in posts 46 and 50, I did them. Why? Because I wasn't certain how things would work, and it was easy enough to give it a try and learn a few things in the process.

In part 1, I saved byte values in 4 adjacent EEPROM locations. Reading the values back into a byte variable yielded the results expected. Reading the values back into a word variable yielded garbage of course, because each EEPROM location is byte-sized, and when a word is read, two adjacent bytes are read as a word.

In part 2, I saved word variables, each containing a byte value, into adjacent EEPROM locations. This is of course wrong, as a word requires two bytes. Reading these locations back as bytes yielded the expected numbers, but this is a happy circumstance of the order in which they were written, because stored a word writes in two EEPROM locations. It might look ok during a quick test, but it will yield unexpected results.

Reading these values back into a word variable resulted in garbage, as this reads adjacent cells as a word.

In part 3, I wrote a byte-sized word variable into every other cell. Reading back the values as bytes shows the expected result, the byte-sized number in one cell and a zero in the other (since the value stored was less than 256). Reading the word value from the expected location yielded the expected results.

When word values were read from the wrong location of the pair, garbage was the result, as byte values from two diffent words were combined un the wrong order.

Part 4 repeated part 3 with values greater than 255 (i.e., greater than byte-sized) with the expected results.

Thd output of the tests is shown here. This picture shows the EEPROM values as read by the PICkit 2.

Code:
EEPROM Test

Part 1 - Data written as bytes


EE.0 = 42, EE.1 = 43, EE.2 = 44, EE.3 = 45, stored as bytes.


Read as bytes

Addr0: 42
Addr1: 43
Addr2: 44
Addr3: 45

Read as words

Addr0: 11050
Addr1: 11307
Addr2: 11564
Addr3: 65325


===========================================================

Part 2 - Data written as words, in adjacent locations


EE.4 = 42, EE.5 = 43, EE.6 = 44, EE.7 = 45, stored as words.
Note: a word should require 2 locations.


Read as bytes

Addr4: 42
Addr5: 43
Addr6: 44
Addr7: 45

Read as words

Addr4: 11050
Addr5: 11307
Addr6: 11564
Addr7: 45


===========================================================

Part 3 - Data written as words, in every other location


EE.9 = 42, EE.11 = 43, EE.13 = 44, EE.15 = 45, stored as words.

Read as bytes

Addr8: 0
Addr9: 42
Addr10: 0
Addr11: 43
Addr12: 0
Addr13: 44
Addr14: 0
Addr15: 45
Addr16: 0

Read as words, odd cell numbers

Addr9: 42
Addr11: 43
Addr13: 44
Addr15: 45

Read as words, even cell numbers

Addr8: 10752
Addr10: 11008
Addr12: 11264
Addr14: 11520
Addr16: 65280


===========================================================

Part 4 - Data written as words, in every other location


EE.20 = 747, EE.22 = 748, EE.24 = 749, EE.26 = 750, stored as words.

Read as bytes

Addr18: 255
Addr19: 255
Addr20: 235
Addr21: 2
Addr22: 236
Addr23: 2
Addr24: 237
Addr25: 2
Addr26: 238
Addr27: 2
Addr28: 255

Read as words, even cell numbers

Addr18: 65535
Addr20: 747
Addr22: 748
Addr24: 749
Addr26: 750
Addr28: 65535

Read as words, odd cell numbers

Addr19: 60415
Addr21: 60418
Addr23: 60674
Addr25: 60930
Addr27: 65282
Addr29: 65535
 

Attachments

Pommie

Well-Known Member
Most Helpful Member
What happens if you do,
Code:
dim test as word
test=$1234
EE.write(0,test)
test=0
EE.Read(0,test)
(forgive syntax - may be wrong).
Surely, the value read back is hex 1234.
You seem to be convinced that the EE routines only deal with bytes.
I think they deal with whatever type of variable you use.

Mike.
 

be80be

Well-Known Member
Microcontroller EEPROM read and write library. Note that TAddress is byte size for devices that have less than 256 bytes of onboard EEPROM. For devices that have more than 256 of onboard EEPROM, TAddress is a word.
Write multiple items to microcontroller EEPROM. Valid argument types include boolean, char, string, byte, shortint, word, integer, longword, longint and floating point.
 

Visitor

Active Member
You seem to be convinced that the EE routines only deal with bytes.
Not at all. If a word is saved, a word will be returned as long as nothing else writes over its EEPROM locations. The same should be true for any type of variable.

You can get into trouble in two ways:

¤ If you save a variable of one type and recall it as a different type. For example, if you store a byte variable (one byte) and read it into a word variable (two bytes), you'll get garbage.

¤ If you don't allow enough space for whatever type of variable is being stored (i.e., 2 bytes for a word, 4 bytes for a long word or float), depending on the order things are saved, some of the EEPROM locations will be overwritten and the returned values will be wrong.

Finally, reading the byte values will always show what's stored. The value of whatever variable type was stored can be calculated.
 

tumbleweed

Active Member
So, what it boils down to is 'garbage in, garbage out'.

The libraries read and write the different variable types as you would expect.
Nothing extra needed except a little upfront planning for what you're saving where just like in any other system.
 

MrDEB

Well-Known Member
I did everything requested in post 46 and 50 thus I am making some progress.
my code needs some work due to the fact after I ran the code in post 75 which worked as planned I inserted into my project code and it fails to work.
I think I have best score in place of current score.
will try it today
 

granddad

Well-Known Member
Am i missing something here , your code can write byte word to EE , then via PK2 or whatever read it take a look see what it wrote ( as the Visitor post #81 ) The SF note states SF defaults to longword for EE write . If SF automatically stops GI interrupts , why does the EE library note state to stop them for other than bytes ?
 
Last edited:

Visitor

Active Member
....The SF note states SF defaults to longword for EE write......
Where did you see this? This isn't what I observed but that may be because of how I did my tests. I set variables dimensioned as bytes or words equal to the values I wanted and then explicitly saved the variable as opposed to a raw number.

Dim Vbyte as Byte

Dim Vword as Word

Vbyte = 42

Vword = 42

EE.Write(0, Vbyte)

EE.Write(2, Vword)


I did get some results I couldn't explain in my first iteration, but I attributed that to errors in my code written at two in the morning.

I will make a couple more tests later today.
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
Its in a note top of the SF EEprom library ... I loaded SF yesterday , and wondered ..
That'll be if you send constants.. The compiler won't be able to classify it... EE.write( 0, 23) will be the default... The trouble here is the read will have to be a longword even though the amount is tiny...
 

be80be

Well-Known Member
Mrdeb should test raw numbers
And format the Result for printing
Code he posted was saving everything
His last code posted was much better
But I would only read and write as needed pull out old value at start of game save at end there no use of using eeprom while playing game you get the writes in loop you'll ware out the eeprom
 

MrDEB

Well-Known Member
good point Burt
I got my code to display current score and best score but now trying to convert the scores to decimal. as in the ET subroute. Need to look at Burts suggestion about reading writing the eeprom to much.
Someone posted about the best score starting at 0
I changed it to best_score=20000
looks crazy but it worked. another issue is the eeprom is not saving info upon disconnecting power.
Code:
//add more sequences
//add the START  code
//add the second speed select code


//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Device = 18F43K22
Clock = 8
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTD.0
#option LCD_EN = PORTD.1
'#option KEYPAD_PORT = PORTC

Include "intosc.bas"
Include "setdigitalio.bas"
Include "keypad12mrd.bas"
Include "ledmatrixREV.bas"
Include "lcd.bas"
Include "utils.bas"
Include "convert.bas"
Include "isrtimer.bas"
Include "EEPROM.bas"
'Dim ledno As Byte
Dim ms As Word
Dim s As String
'Dim time As Word
Dim best_score As Word
Dim Current_Score As Word
Dim str As String
Dim tmpByte As Byte
Sub Ontimer()
    Inc(ms)
    End Sub
    
Sub ET_time()
     Timer.Stop //stop timer
        s=DecToStr(ms/1000)+"."+DecToStr((ms Mod 1000))
        WriteAt(1,1,"your Score  = " )
        'delayms(2000)
          WriteAt(1,1,"reaction     ")            //display players score
          WriteAt(2,1,"seconds   ",s,"     ")
          DelayMS(3000)
          'EE.Write(0,Current_Score)     //need to write to eeprom current score
          
          Current_Score = ms
           WriteAt(2,1,"ms = ",DecToStr(ms))//testing change to current score
           DelayMS(3000)   
           'ms=0
          
          
          DelayMS(9000)
          Cls
          'repeat
         ' WriteAt(1,1,"press START")
          'WriteAt(2,1,"to play again")
          'until (getkey()=3)
          'DelayMS(2000)
          Cls
    'DelayMS(100)
    'wend       
  End Sub
  //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  //read write to eeprom
  //zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
Sub Score_et()                         
   EE.Write(1,best_score)
    EE.Read(0,tmpByte)
    If tmpByte = $77 Then
        EE.Read(1,best_score)
        End If
        If Current_Score < best_score Then
          best_score = Current_Score  //reset BEST_SCORE if CURRENT_SCORE is lower
          EE.Write(1,best_score)  //present beast score
          
        EndIf
        If Current_Score > best_score Then
        
        EndIf
        Cls
      EE.Read(1,best_score)
 
        WriteAt(2,1,DecToStr(Current_Score))      //14388
        WriteAt(1,1,DecToStr(best_score))   // 123

    DelayMS(4000)
     Cls
    Current_Score=0
        ms=0
End Sub


    
//SEQUENCES xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Sub One()
  SetLed(1)
        Repeat
        Until (GetKey()=1)
        SetLed(7)
            Repeat
            Until (GetKey()=7)
            SetLed(4)
                Repeat
                Until (GetKey()=4)
                SetLed(10)
                  Repeat
                Until (GetKey()=10)
                     SetLed(2)
                    Repeat
                    Until (GetKey()=2)
                    SetLed(10)
                        Repeat
                        Until (GetKey()=10)
                        SetLed(6)
                            Repeat
                            Until (GetKey()=6)
                            SetLed(12)
                              Repeat
                            Until (GetKey()=12)
                                  SetLed(8)
                                Repeat
                                Until (GetKey()=8)
                                SetLed(9)
                                    Repeat
                                    Until (GetKey()=9)
                                    SetLed(1)
                                        Repeat
                                        Until (GetKey()=1)
                                        SetLed(11)
                                          Repeat
                                        Until (GetKey()=11)
                                 SetLed(0) //turn off led
     End Sub
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx               
                
 
//initialize timer    PUT THIS AS A SUBROUTE
Sub Int_Timer()
Timer.Initialize(1)
Timer.Items(0).interval=1  //ms
Timer.Items(0)[email protected]  //timer event handler
//enable timers
Timer.Items(0).enabled=true
If GetKey=12 Then   //insert this into all the sub sequences but only last key in sequence
Timer.Stop       //need to insert GETKEY
End If
End Sub
'time = 0
ms=0
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
'START=(GETKEY()=3)
// turn off analog functions
SetAllDigital()
Current_Score=0
 best_score=20000


// loop forever showing led X while key X is pressed
While (true)
    Cls
     WriteAt(1,1,"welcome")
          WriteAt(2,1,"lets begin")
          DelayMS(3000)
          Cls
          WriteAt(1,1,"when button ")
          WriteAt(2,1,"lights")
          DelayMS(3000)
          Cls
          WriteAt(2,1,"Button ")
          WriteAt(1,1,"press THAT")
          DelayMS(3000)
          WriteAt(1,1,"you will be")
          WriteAt(2,1,"TIMED ")
          Cls
          WriteAt(1,1,"lets begin")
          DelayMS(3000)
          Cls
          WriteAt(1,1,"press the")
          WriteAt(2,1,"START BUTTON")  //for test it is #1 SHOULD HAVE KEPT MCLR CONNECTED
          DelayMS(2000)
          Int_Timer()
          SetLed(3)
          Timer.Start//SetLed(GetKey())
          If (GetKey()=3) Then
    Timer.Start//SetLed(GetKey())/SetLed(GetKey())
    End If
    One()       // turn on led 1  INSERT SEQUENCES HERE AS SUBS in a for next loop
    ET_time()
    Score_et()
    
    Wend
 

tumbleweed

Active Member
That'll be if you send constants.. The compiler won't be able to classify it... EE.write( 0, 23) will be the default... The trouble here is the read will have to be a longword even though the amount is tiny...
It doesn't work that way. It evaluates the const and calls the appropriate routine
EE.write( 0, 23) uses a byte write, EE.write( 0, 1234) uses a word write, etc.

EE.Write() is a generic routine and calls different underlying code based on what you pass it.
If you want to write constant values like that it would be a lot safer to use the specific 'WriteByte, WriteWord, WriteLongword' etc calls.

If SF automatically stops GI interrupts , why does the EE library note state to stop them for other than bytes ?
Let me try this again.

When it does the low-level 'write a byte to eeprom' routine, it automatically:
- saves the current GIE
- disables interrupts
- writes the byte
- restores the GIE setting that was in effect when the routine was called

All of the upper level routines end up using that low-level function at least once and maybe multiple times.
For example, writing a longword (4 bytes) will call that routine 4 times.
If interrupts are enabled before the "EE.Writexxx()' call, then they'll get disabled/reenabled, disabled/reenabled, etc four times as it writes the four bytes.

That means that you can get an interrupt in between each of the 4 individual byte writes. That can cause issues or not, entirely based on YOUR code. If it's important that the entire 4-bytes is written without interruption then disable interrupts, call ee.write, and then reenable interrupts.

Make sense?
 

Visitor

Active Member
Code:
Sub Score_et()                         
   EE.Write(1,best_score)
    EE.Read(0,tmpByte)
    If tmpByte = $77 Then
        EE.Read(1,best_score)
        End If
        If Current_Score < best_score Then
          best_score = Current_Score  //reset BEST_SCORE if CURRENT_SCORE is lower
          EE.Write(1,best_score)  //present beast score
          
        EndIf
        If Current_Score > best_score Then
        
        EndIf
        Cls
      EE.Read(1,best_score)
 
        WriteAt(2,1,DecToStr(Current_Score))      //14388
        WriteAt(1,1,DecToStr(best_score))   // 123

    DelayMS(4000)
     Cls
    Current_Score=0
        ms=0
End Sub
It doesn't appear that you ever write to EE.0, so that location will never read as $77, so that If/Then will never get executed.

But no matter. You immediately write EE.1 with best_score at the start of the subroutine, and then later read it back.....trying to follow your logic here makes my head hurt.

But as a final step, you set current_scorecto zero, so do nothing and you win.
 

MrDEB

Well-Known Member
as it is after the first run through the
WriteAt(2,1,DecToStr(Current_Score)) //14388
WriteAt(1,1,DecToStr(best_score)) // 123
show correctly as well as all the scores thereafter BUT the scors are not converted using
s=DecToStr(ms/1000)+"."+DecToStr((ms Mod 1000))
I tried using writeat(1,1,(best_score)DecToStr(ms/1000)+"."+DecToStr((ms Mod 1000))
this worked BUT both scores are identical and I get some extra squagillie at the beginning.
will try writing to the same eeprom slot.
I looked up but no success as to what
EE.Read(0,tmpByte)
If tmpByte = $77 Then
does??
 

Visitor

Active Member
If you'd actually done stuff I said in post 46, you'd understand the "extra squagillie" at the beginning of the line. Or in the several other posts where I explained the problems with your display statements.

LOOK at the display statement. Is EVERY NUMBER handled the SAME WAY?

Hint: the answer is no.


As the what the $77 does, it's your code. You elected to include it despite several people commenting on it and saying you don't need it.


You can lead a Chevy to the levy but you can't make him drink.
 

MrDEB

Well-Known Member
the $77 seems to clear out the eeprom??
thinking of not having ms=0 but going to the subroute then write to the eeprom in a different slot then reading for the final display.
going to research what the $77 actually does.
 

Latest threads

EE World Online Articles

Loading

 
Top