PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Seltsamer Effekt bei externen EEProm



Rage_Empire
07.01.2006, 12:12
Hallo,

ich hab nen Source geschrieben, welcher mir als Subs erleichtern soll Variabeln in ein 24C64 zu speichern und zu lesen. Möglich sind bei mir damit auch word uns Singles zu verarveiten.
Jedoch tritt hier ein seltsamer Effekt auf. Wenn ich z.B. die Single 12.65 speichr möchte geschieht folgendes:
Die Single im Ram wird zu 12.649999....

Ok, kann ja sein, da es sich um Singles und nich um Doubles handelt....wäre für mich ok. Aber wenn ich diesen Wert wieder aus dem EEprom lese ist er 12.625!

Wie kommt das? Ich selbst kam dem rätsel noch nicht auf die Spur, aber vieleicht kann mmir von euch jemand sagen, was hier passiert.

Source auf Single-Variabeln gekürzt:

$lib "i2c.lib"
Config Scl = Portc.0 'PIN für I2C Bus
Config Sda = Portc.1
I2cinit


Config I2cdelay = 3

Dim Eesingle As Single
Dim Eeword(2) As Word At Eesingle Overlay
Dim Eebyte(6) As Byte At Eesingle Overlay
Dim Eebanz As Byte
Dim Ee_adresse As Word

Const 24c64w = &B10100000
Const 24c64r = &B10100001


'Definition der Funktionen ++++++++++++++++++++++++++++++++++++++++++++++++++ ++

Declare Function Loadsingle(byval Ee_adresse As Word) As Single

Declare Sub Savesingle(byval Ee_daten As Single , Byval Ee_adresse As Word )

Goto 001


Sub Savesingle(byval Ee_daten As Single , Byref Ee_adresse As Word )
Eesingle = Ee_daten
Ee_adresse = Ee_adresse
Eebanz = 4 : Gosub Write_ee
End Sub


Function Loadsingle(byref Ee_adresse As Word) As Single
Ee_adresse = Ee_adresse
Eebanz = 4 : Gosub Read_ee
Loadsingle = Eesingle
End Function






'Routine zum schreiben von Daten in das EEPROM ++++++++++++++++++++++++++++++++
Write_ee:
Eebanz = Eebanz + 2

Eebyte(1) = High(ee_adresse)
Eebyte(2) = Low(ee_adresse)
I2csend 24c64w , Eebyte(1) , Eebanz
Waitms 30
Return


'Routine zum lesen von Daten aus dem EEPROM ++++++++++++++++++++++++++++++++++++
Read_ee:

Eebyte(1) = High(ee_adresse)
Eebyte(2) = Low(ee_adresse)

I2csend 24c64w , Eebyte(1) , 2
Waitms 5
I2creceive 24c64r , Eebyte(3) , 0 , Eebanz
Waitms 25

Return
001:


Dim Ins As Single
Dim Inw As Word
Dim Inb As Byte


Do
Input "Single: " , Ins
Call Savesingle(ins , 100)
Print "gespeicherter Wert: ";ins
Ins = 0
Ins = Loadsingle(100)
Print "geladener Wert: " ; Ins

Loop

PicNick
07.01.2006, 13:55
*murmel* Ich versteh' deine Definition nicht so ganz:


1 ... eesingle.....eeword(1)....eebyte(1)............ overlay adresse
2.... eesingle.....eeword(1)....eebyte(2)
3.... eesingle.....eeword(2)....eebyte(3)
4.....eesingle.....eeword(2)....eebyte(4)
5........................................eebyte(5)
6........................................eebyte(6)
7.....eebanz
8.....eeaddr1
9.....eeaddr2

Beim write-ee zerschmetterst du ja zwei bytes vom single


Eebyte(1) = High(ee_adresse)
Eebyte(2) = Low(ee_adresse)


Vorschlag, wenn ich richtig interpretiere, was du wohl meinst :


Dim Eehead(2) As Byte
Dim Eedata(4) As Byte
Dim Eesingle As Single At Eedata Overlay
Dim Eeword(2) As Word At Eedata Overlay

Write_ee:
Eebanz = Eebanz + 2
Eehead(1) = High(ee_adresse)
Eehead(2) = Low(ee_adresse)
I2csend 24c64w , Eehead(1) , Eebanz
return

Read_ee:
Eehead(1) = High(ee_adresse)
Eehead(2) = Low(ee_adresse)

I2csend 24c64w , Eehead(1) , 2
Waitms 5
I2creceive 24c64r , Eedata(1) , 0 , Eebanz
Waitms 25
return

Versuch' mal !

Rage_Empire
07.01.2006, 14:03
Hallo PicNick,

gedacht war es so:

eesingle....eeword(2)......eebyte(6)
eesingle....eeword(2)......eebyte(5)
eesingle....eeword(1)......eebyte(4)
eesingle....eeword(1)......eebyte(3)
....................................eebyte(2)----------für Adresse(HighByte)
....................................eebyte(1)----------für Adresse(LowByte)

Mit Words funktionierts ganz gut, nur mit singles nicht:



$lib "i2c.lib"
Config Scl = Portc.0 'PIN für I2C Bus
Config Sda = Portc.1
I2cinit

Config I2cdelay = 3

Dim Eesingle As Single
Dim Eeword(2) As Word At Eesingle Overlay
Dim Eebyte(6) As Byte At Eesingle Overlay
Dim Eebanz As Byte
Dim Ee_adresse As Word
Dim Ee_adr(2) As Byte At Ee_adresse Overlay

Const 24c64w = &B10100000
Const 24c64r = &B10100001

'Definition der Funktionen ++++++++++++++++++++++++++++++++++++++++++++++++++ ++
Declare Function Loadbyte(byval Ee_adresse As Word) As Byte
Declare Function Loadword(byval Ee_adresse As Word) As Word
Declare Function Loadsingle(byval Ee_adresse As Word) As Single
Declare Sub Savebyte(byval Ee_daten As Byte , Byval Ee_adresse As Word)
Declare Sub Saveword(byval Ee_daten As Word , Byval Ee_adresse As Word)
Declare Sub Savesingle(byval Ee_daten As Single , Byval Ee_adresse As Word )

Goto 001

Sub Savebyte(byval Ee_daten As Byte , Byval Ee_adresse As Word)
Eebyte(3) = Ee_daten
Ee_adresse = Ee_adresse
Eebanz = 1 + 2 : Gosub Write_ee
End Sub

Sub Saveword(byval Ee_daten As Word , Byval Ee_adresse As Word)
Eeword(2) = Ee_daten
Ee_adresse = Ee_adresse
Eebanz = 2 + 2 : Gosub Write_ee
End Sub

Sub Savesingle(byval Ee_daten As Single , Byval Ee_adresse As Word )
Eesingle = Ee_daten
Ee_adresse = Ee_adresse
Eebanz = 4 + 2 : Gosub Write_ee
End Sub


Function Loadbyte(byval Ee_adresse As Word) As Byte
Ee_adresse = Ee_adresse
Eebanz = 1 : Gosub Read_ee
Loadbyte = Eebyte(3)
End Function

Function Loadword(byval Ee_adresse As Word) As Word
Ee_adresse = Ee_adresse
Eebanz = 2 : Gosub Read_ee
Loadword = Eeword(2)
End Function

Function Loadsingle(byval Ee_adresse As Word) As Single
Ee_adresse = Ee_adresse
Eebanz = 4 : Gosub Read_ee
Loadsingle = Eesingle
End Function






'Routine zum schreiben von Daten in das EEPROM ++++++++++++++++++++++++++++++++
Write_ee:

Eebyte(1) = Ee_adr(1)
Eebyte(2) = Ee_adr(2)
I2csend 24c64w , Eebyte(1) , Eebanz
Waitms 30
Return


'Routine zum lesen von Daten aus dem EEPROM ++++++++++++++++++++++++++++++++++++
Read_ee:

Eebyte(1) = Ee_adr(1)
Eebyte(2) = Ee_adr(2)

I2csend 24c64w , Eebyte(1) , 2
Waitms 5
I2creceive 24c64r , Eebyte(3) , 0 , Eebanz
Waitms 25

Return
001:

Dim Ins As Single
Dim Inw As Word
Dim Inb As Byte


Do
Input "Single: " , Ins
Call Savesingle(ins , 100)
Print "gespeicherter Wert: ";ins
Ins = Loadsingle(100)
Print "geladener Wert: " ; Ins

Input "Word: " , Inw
Call Saveword(inw , 100)
Print "gespeicherter Wert: " ; Inw
Inw = Loadword(100)
Print "geladener Wert: " ; Inw

Input "Byte: " , Inb
Call Savebyte(inb , 100)
Print "gespeicherter Wert: " ; Inb
Inb = Loadbyte(100)
Print "geladener Wert: " ; Inb
Loop

Rage_Empire
07.01.2006, 14:07
ups, fehler von mir.....

Die Routinen sollten so Aussehen:



'Routine zum schreiben von Daten in das EEPROM ++++++++++++++++++++++++++++++++
Write_ee:

Eebyte(1) = Low(ee_adresse)
Eebyte(2) = High(ee_adresse)
I2csend 24c64w , Eebyte(1) , Eebanz
Waitms 30
Return


'Routine zum lesen von Daten aus dem EEPROM ++++++++++++++++++++++++++++++++++++
Read_ee:

Eebyte(1) = Low(ee_adresse)
Eebyte(2) = High(ee_adresse)

I2csend 24c64w , Eebyte(1) , 2
Waitms 5
I2creceive 24c64r , Eebyte(3) , 0 , Eebanz
Waitms 25

Return

Rage_Empire
07.01.2006, 14:14
juhu, es geht...danke PicNick.....

war ein Fehler meiner gedanken. Natürlich muß ich die Overlayadadresse um 2 Verschieben....jetzt gehts!!


$lib "i2c.lib"
Config Scl = Portc.0 'PIN für I2C Bus
Config Sda = Portc.1
I2cinit

Config I2cdelay = 3

Dim Eesingle As Single
Dim Eeword(2) As Word At Eesingle Overlay
Dim Eebyte(6) As Byte At Eesingle + 2 Overlay '<------um 2 verschoben!!!
Dim Eebanz As Byte
Dim Ee_adresse As Word

Const 24c64w = &B10100000
Const 24c64r = &B10100001

Const Eetest = 0

'Definition der Funktionen ++++++++++++++++++++++++++++++++++++++++++++++++++ ++
Declare Function Loadbyte(byval Ee_adresse As Word) As Byte
Declare Function Loadword(byval Ee_adresse As Word) As Word
Declare Function Loadsingle(byval Ee_adresse As Word) As Single
Declare Sub Savebyte(byval Ee_daten As Byte , Byval Ee_adresse As Word)
Declare Sub Saveword(byval Ee_daten As Word , Byval Ee_adresse As Word)
Declare Sub Savesingle(byval Ee_daten As Single , Byval Ee_adresse As Word )

Goto 001

Sub Savebyte(byval Ee_daten As Byte , Byval Ee_adresse As Word)
Eebyte(3) = Ee_daten
Ee_adresse = Ee_adresse
Eebanz = 1 + 2 : Gosub Write_ee
End Sub

Sub Saveword(byval Ee_daten As Word , Byval Ee_adresse As Word)
Eeword(2) = Ee_daten
Ee_adresse = Ee_adresse
Eebanz = 2 + 2 : Gosub Write_ee
End Sub

Sub Savesingle(byval Ee_daten As Single , Byval Ee_adresse As Word )
Eesingle = Ee_daten
Ee_adresse = Ee_adresse
Eebanz = 4 + 2 : Gosub Write_ee
End Sub


Function Loadbyte(byval Ee_adresse As Word) As Byte
Ee_adresse = Ee_adresse
Eebanz = 1 : Gosub Read_ee
Loadbyte = Eebyte(3)
End Function

Function Loadword(byval Ee_adresse As Word) As Word
Ee_adresse = Ee_adresse
Eebanz = 2 : Gosub Read_ee
Loadword = Eeword(2)
End Function

Function Loadsingle(byval Ee_adresse As Word) As Single
Ee_adresse = Ee_adresse
Eebanz = 4 : Gosub Read_ee
Loadsingle = Eesingle
End Function






'Routine zum schreiben von Daten in das EEPROM ++++++++++++++++++++++++++++++++
Write_ee:

Eebyte(1) = Low(ee_adresse)
Eebyte(2) = High(ee_adresse)
I2csend 24c64w , Eebyte(1) , Eebanz
Waitms 30
Return


'Routine zum lesen von Daten aus dem EEPROM ++++++++++++++++++++++++++++++++++++
Read_ee:

Eebyte(1) = Low(ee_adresse)
Eebyte(2) = High(ee_adresse)

I2csend 24c64w , Eebyte(1) , 2
Waitms 5
I2creceive 24c64r , Eebyte(3) , 0 , Eebanz
Waitms 25

Return
001:

Dim Ins As Single
Dim Inw As Word
Dim Inb As Byte


Do
Input "Single: " , Ins
Call Savesingle(ins , 100)
Print "gespeicherter Wert: ";ins
Ins = Loadsingle(100)
Print "geladener Wert: " ; Ins

Input "Word: " , Inw
Call Saveword(inw , 100)
Print "gespeicherter Wert: " ; Inw
Inw = Loadword(100)
Print "geladener Wert: " ; Inw

Input "Byte: " , Inb
Call Savebyte(inb , 100)
Print "gespeicherter Wert: " ; Inb
Inb = Loadbyte(100)
Print "geladener Wert: " ; Inb
Loop

PicNick
07.01.2006, 14:15
Ja, aber eebyte(1) ist direkt im single drinnen.
und beim lesen: eebyte(3) ist ja schon das dritte byte vom single.
also, die Sub's sind nicht das Schlimme, die definition ist ungünstig.
Schau genau, was ich anders ge"dim"t habe

Daß der Fehler so seltsam scheint, liegt daran, daß du nur die beiden Low bytes von single vernichtet hast. dadurch sind es immer ~12.6 geblieben

Rage_Empire
07.01.2006, 14:24
Aber PicNick, ich bin mir nicht sicher ob deine Senderoutine noch laufen würde, da du ja nur die Adresse schicken würdest und keine Daten Mehr.

PicNick
07.01.2006, 15:39
Wenn du von irgendein x-beliebigen addresse 4+2 byte schicken tust, dann kennt er keine Feldgrenzen mehr (das single steht ja direkt hinter head )


I2csend 24c64w , Eehead(1) , Eebanz
Aber egal, du hast hast das Problem ja erkannt, und wenn's jetzt funzt, dann funzt's

Und wenn's nicht funzt, dann zeichne deine Datenfeldern und Bytes so richtig auf kariertem Papier auf. Mir z.B. hilft das, ich bin ein visueller Typ.

Rage_Empire
07.01.2006, 17:01
Hab das ganze mal nach deinen Vorgaben umgestrickt und es funktioniert wunderbar. Werden den Source evtl. ins Download-Verzeichnis stellen, da vieleicht noch der eine oder andere sich sonst den kopf darüber zerbricht....man muß das Rad ja nich immer neu erfinden ;-)


Config Scl = Portc.0 'PIN für I2C Bus
Config Sda = Portc.1
I2cinit

Dim Eehead(2) As Byte
Dim Eebyte(4) As Byte
Dim Eesingle As Single At Eebyte Overlay
Dim Eeword(2) As Word At Eebyte Overlay
Dim Eebanz As Byte
Dim Ee_adresse As Word

Const 24c64w = &B10100000
Const 24c64r = &B10100001

'Definition der Funktionen ++++++++++++++++++++++++++++++++++++++++++++++++++ ++
Declare Function Loadbyte(byval Ee_adresse As Word) As Byte
Declare Function Loadword(byval Ee_adresse As Word) As Word
Declare Function Loadsingle(byval Ee_adresse As Word) As Single
Declare Sub Savebyte(byval Ee_daten As Byte , Byval Ee_adresse As Word)
Declare Sub Saveword(byval Ee_daten As Word , Byval Ee_adresse As Word)
Declare Sub Savesingle(byval Ee_daten As Single , Byval Ee_adresse As Word )

Goto 001

Sub Savebyte(byval Ee_daten As Byte , Byval Ee_adresse As Word)
Eebyte(3) = Ee_daten
Ee_adresse = Ee_adresse
Eebanz = 1 + 2 : Gosub Write_ee
End Sub

Sub Saveword(byval Ee_daten As Word , Byval Ee_adresse As Word)
Eeword(2) = Ee_daten
Ee_adresse = Ee_adresse
Eebanz = 2 + 2 : Gosub Write_ee
End Sub

Sub Savesingle(byval Ee_daten As Single , Byval Ee_adresse As Word )
Eesingle = Ee_daten
Ee_adresse = Ee_adresse
Eebanz = 4 + 2 : Gosub Write_ee
End Sub


Function Loadbyte(byval Ee_adresse As Word) As Byte
Ee_adresse = Ee_adresse
Eebanz = 1 : Gosub Read_ee
Loadbyte = Eebyte(3)
End Function

Function Loadword(byval Ee_adresse As Word) As Word
Ee_adresse = Ee_adresse
Eebanz = 2 : Gosub Read_ee
Loadword = Eeword(2)
End Function

Function Loadsingle(byval Ee_adresse As Word) As Single
Ee_adresse = Ee_adresse
Eebanz = 4 : Gosub Read_ee
Loadsingle = Eesingle
End Function






'Routine zum schreiben von Daten in das EEPROM ++++++++++++++++++++++++++++++++
Write_ee:

Eehead(1) = High(ee_adresse)
Eehead(2) = Low(ee_adresse)
I2csend 24c64w , Eehead(1) , Eebanz
Waitus 40000
Return


'Routine zum lesen von Daten aus dem EEPROM ++++++++++++++++++++++++++++++++++++
Read_ee:

Eehead(1) = High(ee_adresse)
Eehead(2) = Low(ee_adresse)

I2csend 24c64w , Eehead(1) , 2
Waitus 20000
I2creceive 24c64r , Eebyte(1) , 0 , Eebanz
Waitus 40000

Return
001:

Dim Ins As Single
Dim Inw As Word
Dim Inb As Byte


Do
Input "Single: " , Ins
Call Savesingle(ins , 100)
Print "gespeicherter Wert: ";ins
Ins = Loadsingle(100)
Print "geladener Wert: " ; Ins

Input "Word: " , Inw
Call Saveword(inw , 100)
Print "gespeicherter Wert: " ; Inw
Inw = Loadword(100)
Print "geladener Wert: " ; Inw

Input "Byte: " , Inb
Call Savebyte(inb , 100)
Print "gespeicherter Wert: " ; Inb
Inb = Loadbyte(100)
Print "geladener Wert: " ; Inb
Loop

PicNick
07.01.2006, 18:17
Na klar, stell es rein, gerade dieses Rad wird ja mit Begeisterung immer wieder neu erfunden.