Hallo zusammen
Erstmals, ich weiss etwas merkwürdiger Titel, aber ich wusste nicht was
ich da schreiben könnte.
Folgendes Szenario.
Ich habe hier zwei Funkmodule vom Typ CC2500
Angesprochen werden diese von einem Atmega48
Den Treiber dafür habe ich selbst geschrieben mit Codestücken aus den Ti
Simpiciti sourcen.
Was funktioniert:
- Initialisierung, problemlos
- Register ein und auslesen, problemlos
- Übertragen undefinierter Daten, problemlos reproduzierbar (dazu komme
ich später)
Was nicht funktioniert:
- Übertragung definierter Daten
Also, meine Transmit Funktion erwartet einen Pointer auf ein Struct mit
den zu sendenden Daten.
Das erste Byte im Frame gibt an, wie lange das Frame selbst ist.
Hier das Struct:
1 | typedef struct
| 2 | {
| 3 | unsigned char frame[MRFD_MAX_FRAME_SIZE]; // MAX Wert ist 20
| 4 | unsigned char crc[MRFD_ADDITION_SIZE]; //CRC Byte
| 5 | } mrfdPacket_t;
|
Hier mein Code-schnippsel zum senden:
1 | mrfdPacket_t *myPacket;
| 2 |
| 3 | myPacket->frame[0] = 10; //Testbefüllung
| 4 | myPacket->frame[1] = 0xBB;
| 5 | myPacket->frame[2] = 0xCC;
| 6 |
| 7 | LED3_1; //Power LED
| 8 | while(1)
| 9 | {
| 10 |
| 11 | if(Taster)
| 12 | {
| 13 | LED1_1;
| 14 | MRFD_TransmitPacket(&myPacket[0]); //Hier weiss ich nicht wie man es korrekt übergibt
| 15 | LED1_0;
| 16 | while(Taster);
| 17 | }
| 18 | }
|
Wenn ich nun folgendes schreibe,
1 | MRFD_TransmitPacket(&myPacket);
|
Kommen wirre Zeichen an, genauergesagt diese folge: 1 | 0x19,0xC5,0xFF,0x02,0x02,0x00,0x18,0x34,0x57,0x69,0x6C,0x6C,0x6B,0x6F,0x6D,0x6D,0x65,0x6E,0x20,0x62,0x65,0x69,0x6D,0x20,0x4D,0x52,
|
Dies habe ich in der Transmit funktion also nach der Übergabe
abgefangen.
Diese Bytes werden sofort übertragen und kommen Fehlerfrei beim
Empfangsmodul an.
Haben jedoch nichts mit meinem eigentlichen Frame zu tun.
Wenn ich jedoch folgendes Programmiere 1 | MRFD_TransmitPacket(&myPacket[0]);
|
Kommen wirklich meine Bytes an die Funktion.
1 | 0x19,0xBB,0xCC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
Jedoch kommt nun nichts mehr an der gegenseite an.
Pin GDO0 des CC2500 Moduls bleibt high (high->low = Präambel erkannt =
neues Paket)
Ich verstehe das ganze nicht.
Was ist hier der unterschied?
Die von mir gposteten Daten sind wirklich 1:1 jene welche in den TX FIFO
des Modules geschrieben werden.
Hoffe jemand hat eine IDEE
Claudio Hediger schrieb:
> Hier mein Code-schnippsel zum senden:
>
> mrfdPacket_t *myPacket;
>
> myPacket->frame[0] = 10; //Testbefüllung
> myPacket->frame[1] = 0xBB;
> myPacket->frame[2] = 0xCC;
Das ist zu wenig.
Wenn du einen Pointer hast, musst du dich IMMER sofort fragen: Wo ist
der Speicher, auf den der Pointer zeigt.
Und bei dir zeigt er, ähm, nirgendwohin.
D.h. du hast gar keinen Speicher, in dem du Werte ablegen könntest.
(d.h. natürlich hast du Speicher. Der Speicher liegt immer nur einfach
so rum. Aber er gehört nicht zu einem mrfdPacket_t Objekt. De Fakto
bügelst du mit deinen Zuweisungen irgendwas anderes im Speicher nieder,
was halt zufällig dort im Speicher stand, wo der Pointer hinzeigte. Denn
natürlich hat auch der einen Wert. Keinen definierten, aber er hat
einen)
Du bist da auf etwas hineingefallen:
Nur weil eine Funktion einen Pointer haben will, bedeutet das nicht
automatisch, dass der Aufrufer auch einen Pointer haben muss.
Gedacht ist die Verwendung dieser Funktion so: 1 | mrfdPacket_t dasPacket; // ein tatsächliches Objekt.
| 2 | // nicht nur ein Pointer auf so eines!
| 3 |
| 4 | dasPacket.frame[0] = 10; // geht natürlich. Denn dasPacket ist
| 5 | .... // ja ein Objekt. Da liegt auch wirklich
| 6 | .... // Speicher dahinter.
| 7 |
| 8 |
| 9 | MRFD_TransmitPacket( &dasPacket );
|
d.h. die Funktion erwartet einen Pointer, weil du die Adresse eines
tatsächlichen Objektes übergeben musst!
Adresse deshalb, weil ansonsten eine Kopie des Objektes gemacht werden
würde und das zeit und resourcenaufwändig ist. Daher werden
Strukturobjekte oft so übergeben, dass man die Adresse des Objektes
übergibt.
Also: Bei Pointern in Funktionsargumentlisten immer ein bischen
vorsichtig sein. Oft bedeutet das nur, dass du die Adresse eines
tatsächlichen Objektes übergeben musst.
Vielen Dank für deine Ausführliche Antwort Heinz
Karl Heinz Buchegger schrieb:
> mrfdPacket_t dasPacket; // ein tatsächliches Objekt.
Doch wenn ich da das Pointer Asterisk wegmache, kommt folgendes
1 | ../main.c:107: error: invalid type argument of '->' (have 'mrfdPacket_t')
|
Bei diesem hier:
1 | myPacket->frame[0] = 2;
| 2 | myPacket->frame[1] = 0xBB;
| 3 | myPacket->frame[2] = 0xCC;
|
Ich habe mir schon gedacht, dass ich da mit dem Asterisk was falsch
mache, aber da er ansonsten motzt, hab ichs dummerweise gelassen.
Hab das Problem grad gefunden.
Ich muss anstelle von '->' einfach einen '.' machen...
Kannst du mir noch den unterschied zwischen dem -> und dem . erklären
bitte?
Weshalb brauche ich hier einen ->
1 | txBufLen = pPacket->frame[0]+1;
|
und kann nicht mit einem punkt zugreifen?
Juhuuuu mein Treiber läuft :) Danke vielmaaals :)
Claudio Hediger schrieb:
> Kannst du mir noch den unterschied zwischen dem -> und dem . erklären
> bitte?
Ist ganz einfach.
Der . ist der Operator mit dem man auf einen Member eines
Strukturobjektes zugreift.
struct time
{
int day;
int month;
};
struct time birthDay;
birthDay.day = 8;
birthDay.month = 4;
das ist der Normalfall.
So. Jetzt hast du einen Pointer und dieser Pointer zeige auf so ein
Objekt
struct time * userDate = &birthDay;
userDate birthDay
+----------+ +--------------+
| o------------------>| day: 8 |
+----------+ | month: 4 |
+--------------+
wie geht jetzt der Zugriff?
Zunächst mal muss der Pointer dereferenziert werden, also
*userDate
damit ist man beim struct time Objekt (dem Kasten rechts) und von diesem
Komplettobjekt hätte man zb gerne den day Member
*userDate.day
das hat jetzt nur ein Problem. Die Operatoren-Reihenfolge ist falsch.
Der Compiler würde das als
*(userDate.day)
lesen. Nur: userDate ist ein Pointer! Der hat keine Member. Das Objekt
auf das er zeigt, das hat den Member. Aber als Pointer hat er nichts.
Den Pointer kann man nur dereferenzieren oder mit eiem anderen Pointer
vergleichen und ein bischen Offset-rechnen. Aber Member, also einen
inneren Aufbau, hat der keine.
D.h. das müsste man so schreiben
(*userDate).day
jetzt passt alles. Jetzt ist die Dereferenzierung an den Pointer
gebunden und erst von diesem Ergebnis (dem Objekt) nimmt man den day
Member.
Da man aber in C in einem durchschnittlichen Programm viele tausend
derartige Operationen hat, und die (*xx).yy Notation ziemlich
besch...eiden zu tippen ist, gibt es dafür eine Kurzform
userDate->day
Die Notation
xx->yy
ist also nichts anderes als eine kürzere Schreibweise für
(*xx).yy
die man benötigt, wenn xx ein Pointer ist und man auf einen Member
zugreifen möchte, der in einem Objekt steckt auf das der Pointer zeigt.
genauso wie i++ eine kürzere Schreibweise für i = i+1 ist
Vielen Vielen Dank Karl Heinz :)
Nun hab ich es verstanden.
Hoffentlich hilft es auch noch ein paar anderen weiter.
Gruss
aus der Schweiz
Claudio
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|