Atmel AVR TWI Library - Verständnisfrage zu Pointer

OP #7552871
Lesenswert?

Guten Abend zusammen,

ich verzweifle aktuell an der Atmel AVR USI_TWI Library (siehe Anhang). Eigentlich total simple, schreiben klappt auch super aber beim Lesen komme ich nicht an die gelesenen Daten. Hardwareseitig passt alles, die Daten liegen am Bus an... ich "finde" sie nur nicht im Code.

Zum Lesen der Daten vom Bus brauche ich einen "Repeated Start", nachdem es den nativ in der Library nicht gibt muss ich den wie folgt ausführen:

1
uint8_t ReadStatusRegister(uint8_t reg, uint8_t dev, uint8_t readBytes) {
2
  
3
  uint8_t readDev = dev+0x01;
4
  
5
  uint8_t data1[2] = {dev,reg};
6
  uint8_t data2[1] = {readDev};
7
    
8
  USI_TWI_Start_Transceiver_With_Data_Stop(data1,2,FALSE);
9
  return USI_TWI_Start_Transceiver_With_Data(data2,readBytes);
10
  
11
}

Aufgerufen wird die Funktion z.B. zum Lesen von Device 0xAA, Adresse 0x20 so:

1
ReadStatusRegister(0x20,0xAA,2);

Im Anhang sieht man schön das Ergebnis (0x5E). Soweit also ok... nur wie komme ich an die Daten im Code?

Das

1
return USI_TWI_Start_Transceiver_With_Data(data2,readBytes);

liefert mir lediglich ein 0x01 für TRUE. Ich muss irgendwie auf den Pointer innerhalb der Library zugreifen. Alle Versuche dahingehend sind bisher gescheitert :(

Wenn ich die Funktion mit einem Pointer aufrufe ...

1
uint8_t val = 0x20;
2
ReadStatusRegister(&val,0xAA,2);

... habe ich in der Variable val irgendwas stehen (vermutlich die Speicheradresse).

Könnt ihr mir hier helfen? Bitte?

Angehängte Dateien:
#7552915
Lesenswert?

Oliver S. schrieb:

USI_TWI_Start_Transceiver_With_Data(unsigned char *, unsigned char); erwartet als ersten Parameter ein Array (=pointer) in passender Größe, in das die empfangenen Daten geschrieben werden.

Also schau in dein C-Buch, was ein Array ist.

Oliver

Auch wenn Pointer häufig genutzt werden um auf Arrays zuzugreifen, haben die nichts miteinander zu tun.

Ein Pointer ist sehr viel abstrakter und kann auf vollkommen beliebige Daten verweisen.

Du solltest daher deinen eigenen Tipp beherzigen, und in ein C-Buch schauen!

Moderator (Firma: Titel) Persönliche Seite #7553134
Lesenswert?

Harry L. schrieb:

Ein Pointer ist sehr viel abstrakter und kann auf vollkommen beliebige Daten verweisen.

Ein Pointer ist kann auf irgendwas zeigen (auch auf Funktionen oder auf andere Pointer oder auf Register) und der, der den Pointer bekommt, muss wissen, was er damit anzufangen hat.

Im speziellen Fall hier braucht es einfach die Anfangsadresse eines Speicherblocks. Also enthalt im Fall hier der Pointer einfach genau diese Adresse der ersten Speicherzelle des Arrays.

Harry L. schrieb:

Du solltest daher deinen eigenen Tipp beherzigen, und in ein C-Buch schauen!

Es ist generell gut, in ein paar C-Bücher zu schauen, weil manche so umständlich geschrieben sind, dass man sich fragt, ob der Autor selber das auch richtig kapiert hat.

Borsty B. schrieb:

Wenn ich die Funktion mit einem Pointer aufrufe ... uint8_t val = 0x20; ReadStatusRegister(&val,0xAA,2);

Dieser Aufruf ist prinzipiell falsch, denn die Funktion ist so definiert:

uint8_t ReadStatusRegister(uint8_t reg, uint8_t dev, uint8_t readBytes)

Da darf keine Adresse übergeben werden. Das sollte aber der Compiler schon anmäkeln...

Borsty B. schrieb:

Es hat mich allerdings auf den richtigen Weg gebracht, es funktioniert nun :)

Nachdem dir von anderen geholfen wurde, wäre es ein richtig schöner Abschluss deines Threads und wiederum eine Hilfe für andere, wenn du allen verrätst, wie du das Problem letztlich gelöst hast...

OP #7556079
Lesenswert?

Also so sieht aktuell meine Lösung aus:

1
uint8_t *ReadStatusRegister(uint8_t *reg, uint8_t *dev) {
2
  
3
uint8_t readDev = dev+0x01;
4
  
5
uint8_t data1[2] = {dev,reg};
6
static uint8_t data2[3];
7
data2[0] = readDev;
8
    
9
USI_TWI_Start_Transceiver_With_Data_Stop(data1,2,FALSE);
10
USI_TWI_Start_Transceiver_With_Data(data2,2);
11
  
12
return data2;
13
}

Die Daten werden also in das Data2 Array gelesen. Bisschen doof ist, dass ich nun nicht flexibel sagen kann wie viele Bytes ich vom Bus lesen möchte weil ich ja das Array schon fix definieren muss.

Aufgerufen wird die Funktion so:

1
uint8_t *tmp;
2
tmp = ReadStatusRegister(0x20,0xAA);
3

4
// 1. Byte vom Bus
5
tmp[1];
6

7
// 2. Byte vom Bus
8
tmp[2]
#7556402
Lesenswert?

Borsty B. schrieb:

static uint8_t data2[3];

Die Daten werden also in das Data2 Array gelesen. Bisschen doof ist, dass ich nun nicht flexibel sagen kann wie viele Bytes ich vom Bus lesen möchte weil ich ja das Array schon fix definieren muss.

Man kann einen Speicher auch zur Laufzeit allozieren mit malloc(), und wenn man ihn nicht mehr braucht, dann mit free() freigeben. Das steht oft auch in einem C-Buch.

Aber das ist wohl mehr Overhead, als ein statisches Feld, wo ein paar Bytes nicht benutzt werden. Denn mehr als 4 Lesebytes sind in der normalen I2C Wildbahn sehr selten. Also nimmt man 8, und ist bis an sein Lebensende glücklich damit.

#7556554
Lesenswert?

Hallo, Lothar M. schrieb im Beitrag #7553134:

Es ist generell gut, in ein paar C-Bücher zu schauen, weil manche so umständlich geschrieben sind, dass man sich fragt, ob der Autor selber das auch richtig kapiert hat.

Eigentlich reicht ein einziges (K/R ). Da ist das Thema erschöpfend und verständlich erklärt.

rhf

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren