Hi,
stehe gerade vor einem gröberen Problem und weiß nicht was richtig ist,
einerseits gibt es in der Literatur Beispiele, wie das EPROM 24LC64 oder
24LC512 beschrieben wird (z.B. Stefan Hoffmann: ..BASCOM)
Hier gibts ein Beispiel für einen Datenlogger (Seite 442), der immer 10
Bytes schreibt - ich benötige soetwas in meiner Applikation und
programmiere das in etwa so
<code>
I2cinit
I2cstart
I2cwbyte Eprom_write '160
Err = 0
Wrd = 0
I2cwbyte AdrHigh
I2cwbyte AdrLow
I2cwbyte Lngbytes(1)
I2cwbyte Lngbytes(2)
I2cwbyte Lngbytes(3)
I2cwbyte Lngbytes(4)
I2cwbyte Lngbytes2(1)
I2cwbyte Lngbytes2(2)
I2cwbyte Lngbytes2(3)
I2cwbyte Lngbytes2(4)
I2cwbyte Byt
I2cwbyte Bytfunktion
I2cstop
</code>
Ich hab das so ähnlich für einen Datenlogger programmiert. Nun lese ich
auf diversen Seiten, dass der page-Write nicht so einfach wäre,
z.B. hier: http://www.grzesina.de/avr/i2c/i2c.html
Es müssen die Bytes immer in der 128-Byte Seite (von null begonnen)
liegen
Also wenn immer 10 Bytes geschrieben werden
0-10-20-30-40-50-60-70-80-90-100-110-120
gibts beim 13.Log Eintrag ab Adresse 120 ein Problem,
in diesem Fall werden die 10 Bytes auf 120-127 und 128-129 geschrieben,
das können (angeblich) die EPROMS nicht und vergessen die Bytes 128-129
Wenn das wirklich so ist, dann ist das Buch von Stefan Hoffmann und
diverse andere Literatur deutlich zu überarbeiten...
Soll ich jetzt die Bytes einzeln schreiben oder muss ich mein Programm
so (kompliziert) überarbeiten, dass erkannt wird, in welchem
Paging-Bereich ich schreibe und bei Schreiben ab Adresse 120 muss ich
dann 2x schreiben (einmal 120-127 und den 2. Schreibvorgang mit 128-129)
Aus dem Datenblatt zum 24LC512 geht das leider auch nicht so recht
hervor, bzw. steht nicht explizit, dass der SRAM-Buffer mit 128 Bytes
auch genau einer 128-Byte Seite im EPROM zugeordnet werden muss
Manfred S. schrieb:> Aus dem Datenblatt zum 24LC512 geht das leider auch nicht so recht> hervor
Also im Atmel Datenblatt steht das ganz eindeutig drin:
"The data word address lower 7 bits are internally incremented following
the receipt of each data
word. The higher data word address bits are not incremented, retaining
the memory page row
location. When the word address, internally generated, reaches the page
boundary, the following
byte is placed at the beginning of the same page. If more than 128 data
words are
transmitted to the EEPROM, the data word address will “roll over” and
previous data will be
overwritten. The address roll over during write is from the last byte of
the current page to the first
byte of the same page."
Manfred S. schrieb:> in diesem Fall werden die 10 Bytes auf 120-127 und 128-129 geschrieben,> das können (angeblich) die EPROMS nicht und vergessen die Bytes 128-129
Nö, der EEPROM schreibt Byte 128, 129 dann auf Adresse 0 und 1.
Das ist mit "The address roll over" gemeint.
Manfred S. schrieb:> Soll ich jetzt die Bytes einzeln schreiben oder muss ich mein Programm> so (kompliziert) überarbeiten
Das Testen ist ganz einfach möglich, indem man die nächste Adresse mit
einer Maske für die unteren Bits undiert und dann 0 rauskommt.
In C sieht das so aus:
1
do
2
si2c_w(*sram++);
3
while(--len&&(++eeaddr&(PAGE_SIZE-1)));// end or next page
Anbei die komplette Routine in C (ich benutze kein Basic).
Peter
Danke, Peter für die rasche Rückmeldung
Peter Dannegger schrieb:> Also im Atmel Datenblatt steht das ganz eindeutig drin:>> "The data word address lower 7 bits are internally incremented following> the receipt of each data> word. The higher data word address bits are not incremented, retaining> the memory page row> location. When the word address, internally generated, reaches the page> boundary, the following> byte is placed at the beginning of the same page. If more than 128 data> words are> transmitted to the EEPROM, the data word address will “roll over” and> previous data will be> overwritten. The address roll over during write is from the last byte of> the current page to the first> byte of the same page."
mea culpa - tja, sollt man halt nicht einfach so überfliegen..
> Manfred S. schrieb:>> in diesem Fall werden die 10 Bytes auf 120-127 und 128-129 geschrieben,>> das können (angeblich) die EPROMS nicht und vergessen die Bytes 128-129>> Nö, der EEPROM schreibt Byte 128, 129 dann auf Adresse 0 und 1.> Das ist mit "The address roll over" gemeint.>>> Manfred S. schrieb:>> Soll ich jetzt die Bytes einzeln schreiben oder muss ich mein Programm>> so (kompliziert) überarbeiten>> Das Testen ist ganz einfach möglich, indem man die nächste Adresse mit> einer Maske für die unteren Bits undiert und dann 0 rauskommt.> In C sieht das so aus:>
1
>do
2
>si2c_w(*sram++);
3
>while(--len&&(++eeaddr&(PAGE_SIZE-1)));// end or next page
4
>
>> Anbei die komplette Routine in C (ich benutze kein Basic).>>> Peter
Tja, werd den Algorithmus für Bascom wohl anpassen müssen, dazwischen
muss ich dann noch das acknowledge polling einbauen oder ich schreib die
10 Bytes einzeln mit acknowledge polling - werd das morgen einmal
testen!
Vielleicht sollte Stefan Hoffmann bei der nächsten Auflage das alles
auch noch berücksichtigen... sein Buch in Ehren, ist wirklich super für
Anfänger - aber das mit dem Page-Writing sollte kurz erwähnt sein!
Manfred S. schrieb:> Aus dem Datenblatt zum 24LC512 geht das leider auch nicht so recht> hervor, bzw. steht nicht explizit, dass der SRAM-Buffer mit 128 Bytes> auch genau einer 128-Byte Seite im EPROM zugeordnet werden muss
Das steht doch sehr genau im DB, unter:
Page write operations are limited to writing bytes within a single
physical page, regardless of the number of bytes ...
Und für die weiter Fortgeschrittenen, hier die Variante mit Acknowledge
Polling - vielleicht schafft es jemand, das Acknowledge Polling
ausschließlich mit Bascom zu realisieren. Aber die I2C-Routinen sind
sehr "eigen".
Und der ganze TWI-Bus zu Fuß codiert - wir benötigen überhaupt keine
Bascom Library oder Bascom I2c-Befehle
So und jeztt die Frage: welche Variante ist die Beste?
Manfred S. schrieb:> Function Fxi2cstart(byval Byti2cadr As Byte) As Byte> 'Acknowledge Polling, Wert zu groß=Timeout Fehler> Local Bytzaehler As Byte> Bytzaehler = 0> Do> Incr Bytzaehler 'Beschäftigung, wenn kein Zähler, dann Waitus 1> Twcr = &B10100100 'entspricht I2CWrite_EpromWrite> Do> Loop Until Twcr.twint = 1 'entspricht I2CStart> Twdr = Byti2cadr> Twcr = &B10000100> Do> Loop Until Twcr.twint = 1> Loop Until Twsr.5 = 0 Or Bytzaehler = 255 'TWSR.5 = Bit, ob
Ack empfangen wurde, wird 0 bei ACK
> Fxi2cstart = Bytzaehler> End Function
Brrr, grausam. Wenn der restliche Codes auch so aufgeblasen ist und der
vernünftig geschrieben würde, dann bliebe ja nix mehr über um den µC
voll zu bekommen. :D
Acknowlede Polling geht so:
1
Do
2
I2cstart
3
I2cwbyte EEProm_Write_Address
4
Loop Until Err = 0
Manfred S. schrieb:> Aber die I2C-Routinen sind sehr "eigen".
Übersetzung: Habe keine Ahnung.
naja, die I2C-Routinen in Bascom sind standardmäßig Soft-I2C,
es sei denn der User ruft die Lib auf.
Bei dem Befehl I2CStart macht Bascom in der Soft-I2C-Variante
einen Restart statt einen reinen Start, das kann einem schon den Tag
versauen wenn ein TWI-Slave das nicht mag ... hatt ich nämlich schon
und hab erst mit dem Oszi nach Stunden das Problem gefunden weil
ewig im Code nach Fehlern gesucht.
Fhutdhb Ufzjjuz schrieb:> Bei dem Befehl I2CStart macht Bascom in der Soft-I2C-Variante> einen Restart statt einen reinen Start
Da hast Du auch noch in der aktuellen Version Recht.
> es sei denn der User ruft die Lib auf.
Was der TE offensichtlich macht, sonst würde er nicht selbst im TWCR
rumwerken.
Manfred S. schrieb:> Acknowdlege Polling geht sicherer so:
Was ist sicherer ?
Wenn die I2C-HW zuverlässig funktioniert, dann geht die einfachste
Version, wenn Err = 0 ist, dann wurde der Befehl erfolgreich ausgeführt.
Was soll da unsicher sein ?
Wenn die HW dagegen unzuverlässig ist, dann kann man nach Belieben immer
noch Sicherheiten, Zähler, Timeouts, etc. dazu bauen.
War aber nicht die Frage, die war: Wie geht's mit Bascom-Mitteln ?
MWS schrieb:> Manfred S. schrieb:>> Acknowdlege Polling geht sicherer so:>> Was ist sicherer ?> Wenn die I2C-HW zuverlässig funktioniert, dann geht die einfachste> Version, wenn Err = 0 ist, dann wurde der Befehl erfolgreich ausgeführt.> Was soll da unsicher sein ?>> Wenn die HW dagegen unzuverlässig ist, dann kann man nach Belieben immer> noch Sicherheiten, Zähler, Timeouts, etc. dazu bauen.>> War aber nicht die Frage, die war: Wie geht's mit Bascom-Mitteln ?
Naja, es sollt halt dann nicht gleich eine Endlosschleife sein - ein
Timeout bei Hardwarefehlern muss einfach gegeben sein.
> Manfred S. schrieb:>> Aber die I2C-Routinen sind sehr "eigen".> Übersetzung: Habe keine Ahnung.
Tja, hätt ich gern, da ist aber Bascom zu wenig ausführlich dokumentiert
Warum wird beim IC2INIT nicht gleich das TWI mit TWSR, TWBR richtig
initialisiert, sondern erst beim I2CSTART - Und wo steht das in der
Doku?
Wann wird ERR=1 gesetzt, wird dann TWSR ausgelesen oder wie genau wird
ERR gesetzt? - manchmal ist ERR=1 nicht nachvollziehbar!
Fragen über Fragen..
Also da fühl ich mich dann auf der Registerebene einfach sicherer
Manfred S. schrieb:> Naja, es sollt halt dann nicht gleich eine Endlosschleife sein - ein> Timeout bei Hardwarefehlern muss einfach gegeben sein.
Kommt drauf an, wenn die komplette Schaltung z.B. auf
Konfigurationsdaten des I2C-EEProms angewiesen ist und ohne nicht
funktioniert, dann machst Du genau was ?
Und wenn's sicherheitskritisch ist, nimmt man den WD.
Die Bascom HW-I2C Routine selbst blockiert ja nicht, die hat ein eigenes
Timeout drin. Wenn man also aufgrund Unwägbarkeiten einen sicheren Exit
braucht, dann zählt man die Aufrufe in denen es einen Error gab und
bricht nach 'ner bestimmten Anzahl ab.
Aber sowas bringt doch jeder selbst zustande, das muss ich doch nicht
extra zu meinem Beispiel dazuschreiben.
Manfred S. schrieb:> Warum wird beim IC2INIT nicht gleich das TWI mit TWSR, TWBR richtig> initialisiert, sondern erst beim I2CSTART - Und wo steht das in der> Doku?
Hättest Du Dir nur einmal das zugehörige Beispiel (TWI-master.bas)
angesehen, dann wüsstest Du daß die Prescaler-Bits im TWSR und das TWBR
von "Config TWI" gesetzt werden.
Zitat:
Config Twi = 100000 ' wanted clock frequency
'will set TWBR and TWSR
So steht's auch in der Hilfe, kann Bascom doch nix dafür, daß Du weder
die Hilfe liest, noch Dir die Beispiele anschaust.
Beim I2CStart wird im Übrigen für TWBR/TWSR auch nix initialisiert.
Wenn Du Config TWI vergisst, dann bleiben die Prescalerbits als auch das
Bitrateregister eben leer und die I2C arbeitet mit Maxspeed.
Ob das die angeschlossenen Busteilnehmer mitmachen, ist dann 'ne andere
Sache.
MWS schrieb:> Manfred S. schrieb:>> Warum wird beim IC2INIT nicht gleich das TWI mit TWSR, TWBR richtig>> initialisiert, sondern erst beim I2CSTART - Und wo steht das in der>> Doku?>> Hättest Du Dir nur einmal das zugehörige Beispiel (TWI-master.bas)> angesehen, dann wüsstest Du daß die Prescaler-Bits im TWSR und das TWBR> von "Config TWI" gesetzt werden.> Zitat:> Config Twi = 100000 ' wanted clock frequency> 'will set TWBR and TWSR>
OK, überlesen -danke , auch gerade gelesen I2CINIT ist dann gar nicht
notwendig, da beim Reset des Prozessors die Hardware TWI eh richtig
gesetzt ist.
Aber eine Frage bleibt noch:
wie und wann genau wird ERR gesetzt beim Hardware TWI?
Manfred S. schrieb:> auch gerade gelesen I2CINIT ist dann gar nicht> notwendig, da beim Reset des Prozessors die Hardware TWI eh richtig> gesetzt ist.
I2CInit setzt das DDRx richtig und aktiviert die internen Pullups, falls
man keine externen verwenden muss/möchte.
Manfred S. schrieb:> wie und wann genau wird ERR gesetzt beim Hardware TWI?
Wenn vor dem Timeout kein TWINT kam, bricht I2CStart ab und es wird Bit
2 von Err gesetzt.
> Wenn vor dem Timeout kein TWINT kam, bricht I2CStart ab und es wird Bit> 2 von Err gesetzt.
Ja, für I2CStart und auch die anderen I2C-Routinen, die auf TWINT warten
stimmt da.
I2CWByte und I2CRByte können aber viel mehr. Hab mir gerade den
Bascom-Assembler angesehen, entgegen anders lautenden Infoquellen (z.B.
http://www.rn-wissen.de/index.php/Bascom_I2C_Master) wird bei I2CWrite
sehr wohl das Statusregister TWSR eingehend geprüft.
Bei I2CWByte konkret:
1) TWINT Timeout (wie bei allen)
2) TWSR, Prescaler Bits maskieren
3) Timeout, solange TWSR $F8 bleibt
4) wenn TWSR nicht einen der Werte $18, $28, $40 oder $50 hat -> Fehler
Die Antwort gibt allerdings nur undifferenziert Bit2 des ERR-Registers
zurück - wer will kann ja dann noch spezifischer testen: beim Starten
der Kommunikation mit dem EEPROM als Slave sind nur die Stati $18 und
$20 relevant, $18, Bit 5=0 = ACK empfangen und $20, Bit5=1 =NACK, daher
habe ich spezifisch auf TWSR Bit5 getestet (übrigens Super Tabelle in
den Atmega-Datenblättern, sh. "Formats and States in the Master
Transmitter Mode"). Universeller ist natürlich die Prüfung auf ERR=1,
weil sie alle Fehler umfasst.
Hier nun der "finale" Bascom-Code, um EEproms mit PageWrite (gilt schon
ab 2 Bytes !!) zu beschreiben. Bitte beim Testen aufpassen, dass das
EEPROM nicht in einer Endlosschleife getestet wird..