Moin!
Ich versuche gerade, für ein externes I2C-Eeprom, block-read und
block-write zu implementieren. Byteweises schreiben & lesen
funktioniert. Nur hapert es jetzt am C :-)
So sieht es im Main aus:
1
u16value=16;
2
i2cEepReadBlock(eepAddr,20,2,&value);
Aufbauend auf den Methodendefinitionen der avr-libcs (eeprom_read_block
+ write) sieht meine ReadBlock methode aus wie folgt:
In der for-Schleife lese ich nacheinander (auto-increment mode) die
entsprechenden Bytes. Diese sollen nun byteweise nacheinander in der
Variable "value" im Main geschrieben werden.
Nur wie? Pointer sind nicht meine Stärke. Der Compiler meckert
jedenfalls über "'void*' is not a pointer-to-object type". Und da muss
ich zur Zeit noch passen...
cu, Michael
@ Michael Z. (incunabulum)
>Ich versuche gerade, für ein externes I2C-Eeprom, block-read und>block-write zu implementieren. Byteweises schreiben & lesen>funktioniert. Nur hapert es jetzt am C :-)>So sieht es im Main aus:>u16 value = 16;>i2cEepReadBlock(eepAddr, 20, 2, &value);>Aufbauend auf den Methodendefinitionen der avr-libcs (eeprom_read_block>+ write) sieht meine ReadBlock methode aus wie folgt:>void i2cEepReadBlock(u08 i2cAddr, u32 memAddr, u16 sizebytes, void *pData) {>// I2C Kram + 1. Adresse setzen>for (u08 i = 0; i < sizebytes; i++) {> u08 tmp = i2cReadDataByte(I2C_ACK);> *pData[i] = tmp;>}>i2cReadDataByte(I2C_NACK);>}>In der for-Schleife lese ich nacheinander (auto-increment mode) die>entsprechenden Bytes. Diese sollen nun byteweise nacheinander in der>Variable "value" im Main geschrieben werden.
Na das ist ein wenig sinnlos, da kannst du ja gleich einzelne Bytes
lesen und ausgeben. Der Sinn von Blockzugriffen ist ja, dass man mehrere
Bytes transportiert. Und dazu reichen einfache variablen nciht aus, du
brauchst ein Array.
u16 value[16];
Dann natürlcih der Aufruf mit
i2cEepReadBlock(eepAddr, 20, 2, value);
Ohne Adrerssoperator vor value, denn bei Arrays ist der Name bereits ein
Zeiger!
>Nur wie? Pointer sind nicht meine Stärke. Der Compiler meckert
Na dann solltest du mal schleunigst die Grundlagen nachholen.
>jedenfalls über "'void*' is not a pointer-to-object type". Und da muss>ich zur Zeit noch passen...
Du würfelst ja auch einiges durcheinander. Ein einfaches
pData[i] = tmp;
ist hier vollkommen ausreichend. Durch den Index wird schon
referenziert.
Ausserdem hast du noch einen kleinen logischen Bug drin. Du musst
in der Schleife ein Byte weniger lesen als per Funktionsaufruf
gefordert,
for (u08 i = 0; i < (sizebytes-1); i++) {
damit dann der letzte Zugriff den I2C Bus abschliesst (mit NAK). Und
dann natürlich ein STOP auf dem I2C Bus.
MFG
Falk
Nochmal alles auf einen Blick
//Main
u16 value[16]; // 16 Byte Array
i2cEepReadBlock(eepAddr, 20, 2, value);
void i2cEepReadBlock(u08 i2cAddr, u32 memAddr, u16 sizebytes, void
*pData) {
// I2C Kram + 1. Adresse setzen
for (u08 i = 0; i < (sizebytes-1); i++) {
pData[i] = i2cReadDataByte(I2C_ACK);
}
i2cReadDataByte(I2C_NACK);
// I2C STOP
}
Danke erstmal für das Feedback!
Ich geb zu, dass Beispiel ist nicht besonders klug gewählt...
@Falk:
Was ich will, ist beliebige (!) Daten über die BlockRead + Write
Funktionen schreiben zu können. Also unter anderem auch long int, float,
structs etc. So ähnlich wie hier:
Beitrag "uint32_t aus eeprom lesen/schreiben"
Schau dir mal die avr-libc eeprom_block_read Signatur an. Daher auch
mein Ansatz, u. a. ein u16 als Array von 2 Bytes zu handhaben.
Der Einwand hinsichtlich des I2C_NACK und I2C_STOP ist allerdings
berechtigt.
@Andreas
Unsigned char hatte ich zuerst. Nur was mach ich, wenn ich ein Struct
lesen + Schreiben will? Bei "unsigned char" als Pointer meckert der
Compiler auch, wenn ich ein long int verwenden will.
Kurz,
ich will für beliebige Datenstrukturen beliebigen Typs einen Pointer auf
das erste Byte erzeugen, diesen an die Methode übergeben und dort dann
entsprechend interativ die einzelnen Bytes beschreiben.
cu, Michael
Abgesehen davon, dass i2cAddr und memAddr nicht verwendet werden, sollte
die Änderung in der Zuweisung aus Deinem void nun ein u08 machen und
pro Durchlauf ein u08 in pData schreiben.
Das muss aber Fehler und/oder Warnungen gehagelt haben, einem void *
einen Wert zuzuweisen, da der Compiler nicht wissen kann, wie groß der
Zieltyp ist.
Florian Demski wrote:
> Abgesehen davon, dass i2cAddr und memAddr nicht verwendet werden, sollte> die Änderung in der Zuweisung aus Deinem void nun ein u08 machen und> pro Durchlauf ein u08 in pData schreiben.
Mit ((u08 *)pData)[i] = tmp; funktioniert dies, wie ich es mir
vorstelle. Im nachhinein auch verständlich, da ansonsten der Compilier
nicht weiss, wie lange ein Datenblock ist.... muss man erstmal
draufkommen.
Danke dir! Michael