Forum: Mikrocontroller und Digitale Elektronik Atmel AVR TWI Library - Verständnisfrage zu Pointer


von Borsty B. (mantabernd)


Angehängte Dateien:

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?

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

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

von Harry L. (mysth)


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!

: Bearbeitet durch User
von Borsty B. (mantabernd)


Lesenswert?

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

Danke dafür!!

von Oliver S. (oliverso)


Lesenswert?

Harry L. schrieb:
> 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.

In C sind Array und Pointer gerade als Funktionsparameter, um die es 
hier geht, aber sowas von eng verwandt, enger geht es gar nicht.

Oliver

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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...

von Steve van de Grens (roehrmond)


Lesenswert?

Eventuell hilft es, alle Warnungen des Compilers einzuschalten. Vor 
möglichen Fehler (wie Pointer mit Integer vertauscht) warnt er dann. 
Außerdem empfehle ich die QT Creator IDE, die zeigt nämlich noch eine 
ganze Reihe weitere mögliche Fehler schon beim Editieren an, und zwar 
mehr als alle anderen mir bekannten IDEs. 
http://stefanfrings.de/avr_ide/index.html#qtcreator

von Borsty B. (mantabernd)


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]

von Oliver S. (oliverso)


Lesenswert?

Borsty B. schrieb:
> 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.

Wie viele Daten gelesen werden sollen, kannst du doch angeben. Wenn das 
weniger sind, als das Datenarray gross ist, dann ist das halt so.

Oliver

: Bearbeitet durch User
von Peter (pittyj)


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.

von Roland F. (rhf)


Lesenswert?

Hallo,
Lothar M. schrieb:
> 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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.