www.mikrocontroller.net

Forum: Compiler & IDEs Block_Read be externem I2C-EEPROM


Autor: Michael Z. (incunabulum)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
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.

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


Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ 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
}








Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
pData[i] bringt bei void* auch net viel ein. Statt void* unsigned char* 
verwenden.

Autor: Michael Z. (incunabulum)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Florian Demski (code-wiz)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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);
   ((u08 *)pData)[i] = tmp;
 }
 i2cReadDataByte(I2C_NACK);
}

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.

Autor: Michael Z. (incunabulum)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.