Hallo,
ich habe einen EEPROM 24C08 mit 8KB Speicher. Auf den beabsichtige
Messwerte abzulegen.
Zum Beispiel folgendermaßen:
Datum Zeit Temp.
11.05.13 20:10 +25
Das Datum besteht aus drei 8Bit Int. Die Zeit aus zwei 8Bit Int. Die
Temp. ist in einen 16Bit Int abgelegt.
Wenn ich jetzt einen Datensatz speichern möchte, dann addiere ich doch
lediglich die Größe der Datentypen.
3 Byte + 2 Byte + 2 Byte = 7 Byte
Also hab ich 7 Byte für einen Datensatz. Bei 8k Speicher (also 8192
Byte) könnte ich 1170 x 7 Datensätze speichern? Ist das so richtig?
Daniel schrieb:> ich habe einen EEPROM 24C08 mit 8KB Speicher
Das ist ein Missverständnis. Das EEPROM 24C08 verfügt über 8 kBit
Speicher, mithin also 1 kByte.
8kByte hat z.B. das 24C64 EEPROM.
Daniel schrieb:> Also 1024> Bit / 7 Bit = 146 Datensätze?
Das Ergebnis ist richtig, aber du hast dich von den Bits und Bytes
verwirren lassen :-)
1024 Bytes hat das EEPROM, 7 Byte dein Datensatz, sind also 146
Datensätze.
Du könntest pro Datensatz ein Byte sparen, indem du eine Art UNIX Zeit
(4 Bytes) einführst.
Danke Matthias :) Genau Byte und nicht Bit. Jetzt war ich total
durcheinander.
Ich hab da noch eine Frage zur Geräteadresse.
/AT24C08A, 8K SERIAL EEPROM:
Internally organized with 64 pages of 16 bytes
each, the 8K requires a 10-bit data word address for random word
addressing. /
Device Addressing:
//The 8K EEPROM only uses the A2 device address bit with the next 2 bits
being for
memory page addressing. The A2 bit must compare to its corresponding
hard-wired
input pin. The A1 and A0 pins are no connect.//
Device Adress: 1 0 1 0 A2 P1 P0 R/W
Mit P1 und P0 wähle ich die entsprechenden Pages (64 Stück gesamt) aus,
in die ich dann jeweils 16 Byte schreiben kann? Das heißt doch aber je
nachdem welchen Speicherbereich ich ansprechen möchte, muss ich die
Deviceaddress ändern?
Daniel schrieb:> Mit P1 und P0 wähle ich die entsprechenden Pages (64 Stück gesamt) aus
Nö, du kannst mit P1 und P0 doch maximal 4 Pages auswählen. Das ist aber
korrekt, denn im darauffolgenden Byte wird die Adresse innerhalb der
Page ausgewählt. Das haben die Jungs gemacht, damit das so kompatibel
wie möglich zu den kleineren 24C02 und 24C04 ist.
Daniel schrieb:> Das heißt doch aber je> nachdem welchen Speicherbereich ich ansprechen möchte, muss ich die> Deviceaddress ändern?
So isses. Page 0 würdest du also mit 0xA0 zum schreiben addressieren
(wenn der Adresspin auf Masse liegt) und mit 0xA1 zum Lesen. Page 3 wäre
also 0xA6/0xA7. Bei Adresspin auf Vcc entsprechend 0xA8/0xA9 für Page 0
und 0xAE/0xAF für Page 3.
Mit dem Adresspin meinst du A2? Kann ich dann nur zwei von denn 8K
EEPROMS an einen Bus betreiben? Weil die ersten 4 Bit sind ja fest mit
0xA und danach wähle ich doch nur mit A2 die Adresse aus wie ich es
verstehe.
Page 0 entweder mit
10100000 = 0xA0 z.B. EEPROM 1
oder
10101000 = 0xA8 z.B. EEPROM 2
Daniel schrieb:> Mit dem Adresspin meinst du A2? Kann ich dann nur zwei von denn 8K> EEPROMS an einen Bus betreiben?
Volltreffer, mehr als zwei von den Dingern gäben Adresskonflikte.
So ganz hab ich es noch verstanden, wenn ich mit P1 und P0 nur 4 Pages
ansteuere. Im Datenblatt steht doch 64 Pages of 16 bytes?
Hab mir mal einen Bsp Code von Peter Fleury für einen 24C02
herausgesucht.
Wenn ich mit der dort angegebenen Adresse von 0xA2 für meinen 24C08
arbeite, dann schreibe ich auf die Page 1 des Speichers. Wieviel Bytes
kann ich dann schreiben bis ich die Adresse so ändern müsste, dass ich
auf Page 2 schreibe?
Der Speicher hat 1024 Bytes. Mit P1 und P0 lassen sich diese in 4 x 256
Byte teilen.
Page Device Address Speicherbereich Adressbereich
1 --> 1010 0000 --> 256 byte --> 0x00-0xFF
2 --> 1010 0010 --> 256 byte --> 0x00-0xFF
3 --> 1010 0100 --> 256 byte --> 0x00-0xFF
4 --> 1010 0110 --> 256 byte --> 0x00-0xFF
Das heißt wenn ich meine Datensätze fortlang schreiben will muss ich die
deviceaddress mit ändern.
Bsp.
Beginnend mit 1010 0000 (device) kann ich danach 0x00 - 0xFF
beschreiben.
Wenn ich bei 0xFF angekommen bin, muss ich auf 1010 0010 (device)
wechseln, da mir sonst wahrscheinlich die Page 1 wieder überschrieben
würde.
Gibt es keine Möglichkeit den Speicher von vorne bis hinten forlaufend
zu beschreiben? Wenn ich jetzt meine Datensätze ablege, muss ich ja eine
Funktion schreiben, die ständig darauf achtet, welche Page ich gerade
bin und das ich nicht über 0xFF hinauskomme.
Bei 7 byte für einen Datensatz, kann ich dann gerade 36 Sätze in eine
Page schreiben (36 * 7 = 252), wobei die letzten 4 byte ungenutzt
blieben.
Daniel schrieb:> Im Datenblatt steht doch 64 Pages of 16 bytes?
Das bezieht sich auf den 'Page Write' Modus. Hier gilt tatsächlich, das
eine Page 16 Bytes gross ist.
Im Datenblatt werden P0 und P1 als 'Blockaddress' bezeichnet. Und 4
Blöcke à 256 Bytes sind ja auch genau 1024 Bytes.
Da dein Datensatz 7 Bytes lang ist, und immer die Gefahr besteht,
versehentlich eine Page Grenze zu überschreiten, kommt für dich sowieso
nur Byte Write und Byte Read in Frage. Übrigens gibt es gerade beim
24C08 erhebliche Unterschiede sowohl in der Pinbelegung als auch in der
Art und Weise des Schreibens zwischen den Herstellern. Es wird also
Zeit, zu wissen, wessen Produkt du da verwendest.
Das Zusammenbasteln der absoluten Adresse ist übrigens nicht so
schwierig. Wenn deine Speicheradresse als word (16-bit) vorliegt, kannst
du mit ein bisschen Schieben und Verodern das gut in den Griff kriegen.
Welche Programmiersprache wird benutzt?
> Das Zusammenbasteln der absoluten Adresse ist übrigens nicht so> schwierig.
Und wenn Page Write sowieso uninteressant ist, dann ist der Rest meist
einfach nur eine Frage, wie man vom Adressbuss an die Pins des EEPROM
geht. Dann muss man sich im Grunde überhaupt nicht mehr um diese Page
Sache kümmern sondern gibt die Adressen einfach so aus wie sie sind.
D.h. du kannst die ganze Sache mit den Pages einfach ignorieren. Niemand
schreibt dir vor, dass das was du im Programm als "Adressbit 2"
ansiehst, auch tatsächlich am Pin A2 beim EEPROM rauskommen muss.
D.h. indem du dir das EEPROM geschickt an die Ausgangspins ankabelst,
kannst du dafür sorgen, dass für dein Programm sich das EEPROM einfach
wie eine durchgehende Speicherfläche präsentiert, ohne Schnickschnack.
Ich hab meine Temp. auf 8 Bit reduziert. Eine Genauigkeit von 1°C reicht
mir erstmal aus. Dann könnte ich doch so meinen ersten Datensatz in die
ersten 256 byte folgendermaßen schreiben. Nutze die Peter Fleury Lib für
IIC.
Wenn ich den nächsten Datensatz schreiben will, muss ich doch die
Startadresse ändern. Ich möchte ja forlaufend schreiben. Muss ich mir
jetzt noch eine Var generieren in der ich die letzte Speicheradresse
ablege?
@ Karl Heinz: Danke ich versuche das PageWrite zu ignorieren. So ganz
habe ich deinen Post aber nicht verstanden.
Und ich muss mich korrigieren.
Die i2c_write von Fleury erwartet ein unsigned char. Damit würde ich bei
der temp Probleme bekommen, für den Fall das wir negative Temp haben.
Daniel schrieb:> @ Karl Heinz: Danke ich versuche das PageWrite zu ignorieren. So ganz> habe ich deinen Post aber nicht verstanden.
Vergiss es bitte.
Da hab ich mich ordentlich verhaut. Das ist ja ein I2C EEPROM. Daran
hatte ich gar nicht mehr gedacht.
Ist meine Funktion zum Beschreiben denn richtig? Ich hab es gerade
getestet und eigentlich sollte die richtig sein. Wo ich halt Probleme
sehe ist bei den Temperaturen. Ich versteh die Fleurylib im Detail nicht
und nutze nur seine Funktionen. Das i2c_write ein unsigned char erwartet
macht mir aber Probleme wenn ich negative Temp haben.
Daniel schrieb:> Die i2c_write von Fleury erwartet ein unsigned char. Damit würde ich bei> der temp Probleme bekommen, für den Fall das wir negative Temp haben.
Ignorier das einfach. Ob das Byte signed oder ein unsigned ist, ändert
nichts an seinem Wert. Nur DU musst wissen, was es ist und es passend
interpretieren.
Georg G. schrieb:> Ignorier das einfach. Ob das Byte signed oder ein unsigned ist, ändert> nichts an seinem Wert. Nur DU musst wissen, was es ist und es passend> interpretieren.
Das klappt wunderbar. Danke. Versteh das zwar nicht ganz, weil
int8_t -128 - 128
unsigned char 0 - 255
Die Größe beider Typen ist gleich. Dachte wenn das Byte per iic
übertragen wird, das es schon eine Rolle spielt was für ein Datentyp ich
hab.
Ein Problem hab ich allerdings noch. Wenn ich jetzt den zweiten
Datensatz speichern will, muss ich doch die Startadresse zum schreiben
ändern. Muss ich mir dafür eine Variable erstellen, die permanten schaut
bis wohin ich den Speicher bereits beschrieben habe?
Daniel schrieb:> Die Größe beider Typen ist gleich. Dachte wenn das Byte per iic> übertragen wird, das es schon eine Rolle spielt was für ein Datentyp ich> hab.
Es sind in beiden Fällen 8 Nullen oder Einsen. Du kannst es als Zahl mit
oder ohne Vorzeichen interpretieren oder als Schriftzeichen oder als...
> Ein Problem hab ich allerdings noch. Wenn ich jetzt den zweiten> Datensatz speichern will, muss ich doch die Startadresse zum schreiben> ändern. Muss ich mir dafür eine Variable erstellen, die permanten schaut> bis wohin ich den Speicher bereits beschrieben habe?
Das empfiehlt sich.
Daniel schrieb:> Georg G. schrieb:>> Ignorier das einfach. Ob das Byte signed oder ein unsigned ist, ändert>> nichts an seinem Wert. Nur DU musst wissen, was es ist und es passend>> interpretieren.>> Das klappt wunderbar. Danke. Versteh das zwar nicht ganz, weil>> int8_t -128 - 128> unsigned char 0 - 255
Das macht aber nichts. Denn 8 Bit sind 8 Bit. Ob man da dann 1 Bit als
Vorzeichenanzeiger interpretiert oder nicht, ist eine reine Frage der
Interpretation des Bytes. Für I2C spielt diese Ebene keine Rolle mehr,
da werden nur noch Bytes transportiert.
> Die Größe beider Typen ist gleich.
Eben.
> Dachte wenn das Byte per iic> übertragen wird, das es schon eine Rolle spielt was für ein Datentyp ich> hab.
Ja, ob er aus 1 Byte besteht, oder 2 Bytes oder 4 oder ....
Aber was logisch gesehen hinter diesen Bytes steht, das interessiert auf
dieser Ebene nicht mehr. Byte ist Byte.
> Ein Problem hab ich allerdings noch. Wenn ich jetzt den zweiten> Datensatz speichern will, muss ich doch die Startadresse zum schreiben> ändern. Muss ich mir dafür eine Variable erstellen, die permanten schaut> bis wohin ich den Speicher bereits beschrieben habe?
Ja. Darauf wird es wohl hinauslaufen. Von nichts kommt nichts.
Information die du nicht hast, musst du dir entweder irgendwoher
besorgen oder eben selber speichern. Das EEPROM kannst du nicht
befragen. Den für das EEPROM ist jedes Byte wie jedes andere Byte. Du
schreibst an irgendeine Adresse, du liest von irgendeiner Adresse. Mehr
interessiert das EEPROM nicht.
Karl Heinz Buchegger schrieb:> Ja. Darauf wird es wohl hinauslaufen. Von nichts kommt nichts.> Information die du nicht hast, musst du dir entweder irgendwoher> besorgen oder eben selber speichern. Das EEPROM kannst du nicht> befragen. Den für das EEPROM ist jedes Byte wie jedes andere Byte. Du> schreibst an irgendeine Adresse, du liest von irgendeiner Adresse. Mehr> interessiert das EEPROM nicht.
Ok. Ich hatte mir überlegt, dass ich nach jedem Speichervorgang (nach 6
Byte) im nächsten Byte die Adresse ablege. Das nützt mir ja aber auch
nichts weil ich ja wieder wissen müsste wo ich lesen muss um die
auszulesen.
Das heißt ich erstelle eine Var der ich die Speicheradresse für den
nächsten Schreibvorgang mitteile. Damit fahre ich im normalen Betrieb
gut. Fällt mal die Spannung weg (Batteriewechsel) dann muss ich die
ganzen Datensätze von Adresse 0x00 wieder von vorne auslesen.
Oder hat jemand eine andere Idee?
Daniel schrieb:> Oder hat jemand eine andere Idee?
Du kannsz ja auch die zuletzt benutzte Adresse im EEPROM an einer
bestimmten, immer gleichen Speicheradresse ablegen :-)
Karl Heinz Buchegger schrieb:> Du kannsz ja auch die zuletzt benutzte Adresse im EEPROM an einer> bestimmten, immer gleichen Speicheradresse ablegen :-)
:D Sehr gute Idee :) Dann mach ich das mal. Danke dir.
Kannst du mir vielleicht sagen ob es wesentlich schwieriger und
aufwendiger ist eine SD Karte zu beschreiben im Vergleich zum EEPROM?
Die Adresse einen beliebigen Datensatzes N ergibt sich doch aus
Datensatzadresse = Startadresse + (Datensatzlänge * N). Da das EEPROM
immer bei Adresse 0 anfängt, ist z.B. die Startadresse des Datensatzes
42 also 42*6 = 252.
Daniel schrieb:> Kannst du mir vielleicht sagen ob es wesentlich schwieriger und> aufwendiger ist eine SD Karte zu beschreiben im Vergleich zum EEPROM?
Ja isses, allerdings gibts da auch Bibliotheken. Wenn du allerdings mit
dem kleinen EEPROM Schwierigkeiten hast, wachsen die mit der SD Karte
eher noch.
Daniel schrieb:> Kannst du mir vielleicht sagen ob es wesentlich schwieriger und> aufwendiger ist eine SD Karte zu beschreiben im Vergleich zum EEPROM?
Ein bisschen schon, ja. Wenn du mehr Speicherplatz willst gibt es
EEPROMs aber auch idr. mit bis zu 1Mbit.
Matthias Sch. schrieb:> Die Adresse einen beliebigen Datensatzes N ergibt sich doch aus> Datensatzadresse = Startadresse + (Datensatzlänge * N). Da das EEPROM> immer bei Adresse 0 anfängt, ist z.B. die Startadresse des Datensatzes> 42 also 42*6 = 252.
Genau. Aber woher weiß der Controller welchen Datensatz ich gerade
schreiben will? Ich muss eine Var mitzählen lassen.
Und wenn ich jetzt die Batterien wechseln muss? Dann ist der Wert der
Var weg und da bietet es sich doch an die Startadresse im eeprom
abzulegen, oder nicht?
Daniel schrieb:> Und wenn ich jetzt die Batterien wechseln muss? Dann ist der Wert der> Var weg und da bietet es sich doch an die Startadresse im eeprom> abzulegen, oder nicht?
Aber aufpassen.
Welches ist die größte Adresse die vorkommen kann? Passt die in 1 Byte?
Welches ist die größte Datensatznummer, die vorkommen kann? Passt die in
1 Byte?
Was ist aufwändiger zu schreiben: 1 Byte oder 2 Bytes?
Was ist daher einfacher in der Handhabung, wenn man rein nur rechnet,
dass die Information ja auch geschrieben und gelesen werden muss?
Gelöschte Werte sind bei EEPROMs immer 0xFF, was ein ungültiger
Datensatz ist. Wenn du also eine Page löschst, bevor du sie anfängst zu
beschreiben und immer nur in eine Richtung Datensätze anhängst, kannst
du beim Start des Programms diese Variable ausrechnen (d.h. den ersten
ungültigen Datensatz im EEPROM finden).
Eine andere Strategie wäre, immer einen Datensatz zu schreiben und das
darauf folgende Byte(das wäre ja der Platz für den nächsten Datensatz)
mit 0xFF zu beschreiben. Man ist dann unabhängig vom Page löschen und
kann das EEPROM wie einen Ringbuffer behandeln, indem zumindest 169
Datensätze gültig sind.
Ich komm momentan nicht weiter. Will den Speicher der ersten 256 Byte
löschen und überall eine 1 reinschreiben. Dazu habe ich die folgenden
Funktionen. Man kann es auch mit einer machen.
1
voiddeleteEeprom(uint8_tadress){
2
i2c_start(Dev24C08+I2C_WRITE);
3
i2c_write(adress);
4
i2c_write(0x01);
5
i2c_stop();
6
}
7
8
9
voidSpeicherDel(){
10
inttemp;
11
chartempC[3];
12
13
14
for(uint8_ti=0;i<=254;i++){
15
deleteEeprom(i);
16
sprintf(tempC,"%d",i);
17
lcd_setcursor(0,2);
18
lcd_string(tempC);
19
}
Wenn ich nun den Speicher probeweise auslese, haben nicht alle Bytes
einen Wert von 1. Ich weiß nicht mehr weiter.
Die Ausgabe für den folgenden Code lautet 01.18.01 04:01
Z.B. ab 0x02
Matthias Sch. schrieb:> Eine andere Strategie wäre, immer einen Datensatz zu schreiben und das> darauf folgende Byte(das wäre ja der Platz für den nächsten Datensatz)> mit 0xFF zu beschreiben.
Eine 0xFF zu schreiben, heißt zu löschen (oder man kann es gleich
bleiben lassen).
Michael A. schrieb:> Matthias Sch. schrieb:>> Eine andere Strategie wäre, immer einen Datensatz zu schreiben und das>> darauf folgende Byte(das wäre ja der Platz für den nächsten Datensatz)>> mit 0xFF zu beschreiben.>> Eine 0xFF zu schreiben, heißt zu löschen (oder man kann es gleich> bleiben lassen).
Gut erkannt. Hättest du die Diskussion verfolgt, wüsstest du allerdings,
das wir uns überlegt haben, wie man am besten den nächsten freien
Datensatz findet. Dazu gab es eben die Ansätze des Page-löschens und
mein Vorschlag, nur den auf den aktuellen Datensatz folgenden mit dem
0xFF als frei zu markieren. Lies es einfach nochmal. Es ging hier ja
nicht darum, einen frischen EEPROM zu beschreiben, sondern ihn als
Ringbuffer zu benutzen.
Matthias Sch. schrieb:> Dazu gab es eben die Ansätze des Page-löschens und> mein Vorschlag, nur den auf den aktuellen Datensatz folgenden mit dem> 0xFF als frei zu markieren.
Man kann bei einem EEPROM ein Byte nicht mit 0xFF beschreiben. Beim
Schreiben im EEPROM werden nur Nullen geschrieben. Die Einsen entstehen
durchs Löschen.
Michael A. schrieb:> Man kann bei einem EEPROM ein Byte nicht mit 0xFF beschreiben. Beim> Schreiben im EEPROM werden nur Nullen geschrieben. Die Einsen entstehen> durchs Löschen.
Du verwechselt das mit EPROM - die Dinger mit Quarzglasfenstern und so.
Eine EEPROM Zelle (Lies den Threadtitel - es geht um ein I2C EEPROM)
wird zwar vor dem Schreiben auch gelöscht, lässt sich aber dann mit
jedem beliebigen Wert beschreiben, solange er in ein Byte passt.