Den Inputparameter *hspi fülle ich mit &hspi, das ist soweit klar, also
SPI_Transmit(&hspi, ...)
Wie aber geht es nun weiter, wie fülle ich den *pTxData?
kann ich dafür einfach
uint8 daten = 1;
>> Den Inputparameter *hspi fülle ich mit &hspi, das ist soweit klar, also> SPI_Transmit(&hspi, ...)>> Wie aber geht es nun weiter, wie fülle ich den *pTxData?>> kann ich dafür einfach> uint8 daten = 1;>>
1
SPI_Transmit(&hspi,&daten);
> schreiben?
Allein aus der Signatur folgt, dass daten bei Dir ein Output-Parameter
ist. D.h. nach dem Aufruf ist daten gefüllt mit dem was vom SPI-Slave
kam.
foobar schrieb:> Wie sieht denn der Body von SPI_Transmit aus?> Aus Compilersicht kannst du das schon so schreiben.
spielt doch keine Rolle.
Es ist ja offensichtlich ganz klar was passieren soll. Die Funktion will
eine Speicheraddresse einer 8-bit Zahl. Da das ganze SPI_Transmit heißt,
sollte irgendwo in der Funktionsdoku stehen, dass das der Wert ist, der
versendet werden soll.
Was ich noch nie verstanden habe, warum man 8bit Zahlen als Pointer
übergibt. Ob jetzt die Addresse übertragen wird oder der Wert bleibt
doch völlig wurscht. In nem 32-bit System hat man sogar mehr kopiert als
wenn man Call by Value macht...
ui schrieb:> foobar schrieb:>> Wie sieht denn der Body von SPI_Transmit aus?>> Aus Compilersicht kannst du das schon so schreiben.>> spielt doch keine Rolle.> Es ist ja offensichtlich ganz klar was passieren soll. Die Funktion will> eine Speicheraddresse einer 8-bit Zahl. Da das ganze SPI_Transmit heißt,> sollte irgendwo in der Funktionsdoku stehen, dass das der Wert ist, der> versendet werden soll.> Was ich noch nie verstanden habe, warum man 8bit Zahlen als Pointer> übergibt. Ob jetzt die Addresse übertragen wird oder der Wert bleibt> doch völlig wurscht. In nem 32-bit System hat man sogar mehr kopiert als> wenn man Call by Value macht...
s.o.: OutputParameter
SPI ist immer bidirectional.
@ Pointeraufruf
Ich würde ja gerne mal die Dokumentation oder die Implementierung der
Funktion dazu sehen. Gibt es nicht einen Link darauf? Oder, falls Du sie
selbst geschrieben hast, poste doch bitte mal den Quelltext.
Wilhelm M. schrieb:> ui schrieb:>> foobar schrieb:>>> Wie sieht denn der Body von SPI_Transmit aus?>>> Aus Compilersicht kannst du das schon so schreiben.>>>> spielt doch keine Rolle.>> Es ist ja offensichtlich ganz klar was passieren soll. Die Funktion will>> eine Speicheraddresse einer 8-bit Zahl. Da das ganze SPI_Transmit heißt,>> sollte irgendwo in der Funktionsdoku stehen, dass das der Wert ist, der>> versendet werden soll.>> Was ich noch nie verstanden habe, warum man 8bit Zahlen als Pointer>> übergibt. Ob jetzt die Addresse übertragen wird oder der Wert bleibt>> doch völlig wurscht. In nem 32-bit System hat man sogar mehr kopiert als>> wenn man Call by Value macht...>> s.o.: OutputParameter>> SPI ist immer bidirectional.
ja. aber da spi mosi und miso hat, würde ich bei diesem Funktionsheader
davon ausgehen, dass man übertragen will. ansonsten receive.
Bidirektional ja, aber nicht über ein Medium.
ui schrieb:> Wilhelm M. schrieb:>> ui schrieb:>> s.o.: OutputParameter>>>> SPI ist immer bidirectional.>> ja. aber da spi mosi und miso hat, würde ich bei diesem Funktionsheader> davon ausgehen, dass man übertragen will. ansonsten receive.> Bidirektional ja, aber nicht über ein Medium.
Man füllt vom dem Senden daten mit dem zu sendenden Byte, danach ist
daten gefüllt mit dem, was vom Slave kam.
Ich hätte oben besser sagen sollen: Input-Output-Parameter.
ui schrieb:> ja. aber da spi mosi und miso hat, würde ich bei diesem Funktionsheader> davon ausgehen, dass man übertragen will. ansonsten receive.
Wenn Du per SPI ein Byte verschickst, bekommst Du automatisch im
gleichen Rutsch auch ein Byte zurück von Deinem "Gesprächspartner". Das
heisst, man sendet und empfängt bei SPI gleichzeitig. Das ist
prinzipbedingt.
Daher ist es sinnvoll, hier einen Pointer herunterzugeben. Das Byte wird
gesandt und man bekommt selbst wieder ein Byte zurück.
Frank M. schrieb:> ui schrieb:>> ja. aber da spi mosi und miso hat, würde ich bei diesem Funktionsheader>> davon ausgehen, dass man übertragen will. ansonsten receive.>> Wenn Du per SPI ein Byte verschickst, bekommst Du automatisch im> gleichen Rutsch auch ein Byte zurück von Deinem "Gesprächspartner". Das> heisst, man sendet und empfängt bei SPI gleichzeitig. Das ist> prinzipbedingt.>> Daher ist es sinnvoll, hier einen Pointer herunterzugeben. Das Byte wird> gesandt und man bekommt selbst wieder ein Byte zurück.Wilhelm M. schrieb:> Man füllt vom dem Senden daten mit dem zu sendenden Byte, danach ist> daten gefüllt mit dem, was vom Slave kam.
Ich weiß wie SPI funktioniert.
Allerdings könnte man sich auch vorstellen, dass man das Byte extra
ausliest.
Für mich bedeutet Transmit = nur Versenden
Receive = nur lesen
und Transceive ist beides.
Aber schön wie man sieht, wie man für mit demselben Begriff total
unterschiedliche Dinge assoziiert.
Frank M. schrieb:> Wenn Du per SPI ein Byte verschickst, bekommst Du automatisch im> gleichen Rutsch auch ein Byte zurück von Deinem "Gesprächspartner". Das> heisst, man sendet und empfängt bei SPI gleichzeitig. Das ist> prinzipbedingt.>> Daher ist es sinnvoll, hier einen Pointer herunterzugeben. Das Byte wird> gesandt und man bekommt selbst wieder ein Byte zurück.
Glaub ich dir so nicht.
SPI ohne MISO macht durchaus Sinn. Ich glaube mich sogar zuerinnern an
an Display geschrieben zu haben, das keinen Rückkanal hat.
SPI ohne MISO ist aus Softwaresicht genau dasselbe wie SPI mit MISO, bis
auf den Fakt, dass die empfangenen Werte Gülle sind.
Bei SPI macht "Receive" keinen Sinn, und selbst "Transmit" nur
eingeschränkt, weil SPI prinzipbedingt gleichzeitig sendet und empfängt.
Das sollte aber jedem klar sein, der mit SPI arbeitet, weil es eben kein
I2C ist.
Wilhelm M. schrieb:> Allein aus der Signatur folgt, dass daten bei Dir ein Output-Parameter> ist.
Das halte ich für eine gewagte Annahme. Das kann so sein, muss aber
nicht. Die Tatsache, daß der Parameter "pTxData" heißt, spricht dafür,
daß das die zu sendenden Daten sind (Tx als Kurzform von "transmit").
Nur weil es ein Pointer ist (und jemand das die Angelegenheit eindeutig
machende "const" weggelassen hat), würde ich hier nicht auf
Output-Parameter schließen.
Ja, da steht kein "const", aber steht das irgendwo sonst bei
Funktionsdeklarationen aus der selben Feder? So etwas wird gerne
übersehen, und dann ist das Fehlen kein Indikator für "output
parameter".
Rufus Τ. F. schrieb:> Wilhelm M. schrieb:>> Allein aus der Signatur folgt, dass daten bei Dir ein Output-Parameter>> ist.>> Das halte ich für eine gewagte Annahme. Das kann so sein, muss aber> nicht. Die Tatsache, daß der Parameter "pTxData" heißt, spricht dafür,> daß das die zu sendenden Daten sind (Tx als Kurzform von "transmit").>> Nur weil es ein Pointer ist (und jemand das die Angelegenheit eindeutig> machende "const" weggelassen hat), würde ich hier nicht auf> Output-Parameter schließen.>> Ja, da steht kein "const", aber steht das irgendwo sonst bei> Funktionsdeklarationen aus der selben Feder? So etwas wird gerne> übersehen, und dann ist das Fehlen kein Indikator für "output> parameter".
Wenn das so ist (und deswegen keine Parameterübergabe per-value
stattfindet), dann würde ich das entweder nicht benutzen oder
umschreiben:
"Ein Schnittstelle soll einfach richtig und schwer falsch zu benutzen
sein"
pointer-to-non-const sind (input)output-parameter
Allerdings wäre noch der Typ der Funktion interessant: ist er bool oder
ggf. uint8_t oder optional<uint8_t> (bei C++), wobei letzteres nur bei
C++ geht und dann der uint8_t* vollkommen sinnlos ist ...
Rufus Τ. F. schrieb:> Das halte ich für eine gewagte Annahme. Das kann so sein, muss aber> nicht. Die Tatsache, daß der Parameter "pTxData" heißt, spricht dafür,> daß das die zu sendenden Daten sind (Tx als Kurzform von "transmit").>> Nur weil es ein Pointer ist (und jemand das die Angelegenheit eindeutig> machende "const" weggelassen hat), würde ich hier nicht auf> Output-Parameter schließen.>> Ja, da steht kein "const", aber steht das irgendwo sonst bei> Funktionsdeklarationen aus der selben Feder? So etwas wird gerne> übersehen, und dann ist das Fehlen kein Indikator für "output> parameter".
Seh ich genauso, wenn auch nicht so ausführlich erklärt.
Wilhelm M. schrieb:> Wenn das so ist (und deswegen keine Parameterübergabe per-value> stattfindet), dann würde ich das entweder nicht benutzen oder> umschreiben:>> "Ein Schnittstelle soll einfach richtig und schwer falsch zu benutzen> sein">> pointer-to-non-const sind (input)output-parameter
Es hat keiner Gesagt, dass die Library gut ist.
Ich bleib dabei:
Transmit = nur senden
ui schrieb:>> Es hat keiner Gesagt, dass die Library gut ist.> Ich bleib dabei:> Transmit = nur senden
Bezogen auf die Benennung der Funktion und des Parameters gebe ich Dir
recht. Aber wie gesagt macht für SPI ein "nur Senden" technisch keinen
Sinn. man empfängt zwangsläufig was (auch wenn der Pin gar nicht
angeschlossen ist). Ein Receive allein im Gegenzug macht ebenfalls
keinen Sinn, weil man ohne Transmit kein Receive durchführen kann ...
Zum Thema Schnittstelle vllt noch folgender Link:
https://isocpp.org/wiki/faq/const-correctness
Zudem ist ja ein pointer-type größer als ein uint8_t und man sich ja die
zusätzliche Stacktiefe ersparen kann, wenn nur Input.
Also es sprechen m.E. mehr Punkte dafür, dass es ein
Input/Output-Parameter ist.
Natürlich kann es auch sein, dass der Entwickler dieses Interfaces so
gar nicht nachgedacht hat: bei der Wahl der Typen, beim weglassen des
const, bei der Benennung, ...
Wilhelm M. schrieb:> Aber wie gesagt macht für SPI ein "nur Senden" technisch keinen Sinn.
Aber sicher kann das einen Sinn haben. Ein per SPI angesteuerter DAC
beispielsweise hat in Gegenrechtung wenig mitzuteilen, ein per SPI
angesteuertes Schieberegister (an dem z.B. irgendwelche LEDs hängen)
sieht da nicht anders aus.
> man empfängt zwangsläufig was (auch wenn der Pin gar nicht angeschlossen> ist).
Das ist zwar so, aber wenn man mit Datensenken (s.o.) redet, senden die
nichts zurück und man muss, um nichts zu empfangen, auch keinen
Übergabeparameter verwenden.
> Ein Receive allein im Gegenzug macht ebenfalls keinen Sinn, weil man> ohne Transmit kein Receive durchführen kann ...Das ist korrekt. Aber kennen wir die anderen Deklarationen aus der
Codesammlung, aus der die hier diskutierte Funktion stammt?
> Zudem ist ja ein pointer-type größer als ein uint8_t und man sich ja die> zusätzliche Stacktiefe ersparen kann, wenn nur Input.
O nein, das können ja auch mehrere uint8_t sein, ein Array, und die
Anzahl der zu sendenden Elemente ist entweder in der anderen übergebenen
Struktur verborgen, implizit festgelegt oder wie z.B. bei in C
verwendeten Stringfunktionen durch ein Endezeichen (\0 o.ä.) definiert.
Das kann man der Funktion so alles nicht ansehen.
> Zum Thema Schnittstelle vllt noch folgender Link:> https://isocpp.org/wiki/faq/const-correctness
Das ist die Lehrbuchmeinung, aber --wie schon mehrfach erwähnt-- kann
man ohne die restlichen Funktionen aus der gleichen Feder zu kennen, das
nicht als gegeben ansehen.
"const" ist eines der am meisten ignorierten (d.h. weggelassenen)
Schlüsselwörter in C/C++.
Rufus Τ. F. schrieb:> Wilhelm M. schrieb:>> Aber wie gesagt macht für SPI ein "nur Senden" technisch keinen Sinn.>> Aber sicher kann das einen Sinn haben. Ein per SPI angesteuerter DAC> beispielsweise hat in Gegenrechtung wenig mitzuteilen, ein per SPI> angesteuertes Schieberegister (an dem z.B. irgendwelche LEDs hängen)> sieht da nicht anders aus.
Aber die HW-SPI Schnittstelle empfänger per-definitionem immer etwas -
in dem Fall dann hoffentlich nur "0" oder "1", weil der MISO geklemmt
ist.
>>> man empfängt zwangsläufig was (auch wenn der Pin gar nicht angeschlossen>> ist).>> Das ist zwar so, aber wenn man mit Datensenken (s.o.) redet, senden die> nichts zurück und man muss, um nichts zu empfangen, auch keinen> Übergabeparameter verwenden.
Genau deswegen meine ich ja, das es ein Input/Output-Parameter ist.
>>> Ein Receive allein im Gegenzug macht ebenfalls keinen Sinn, weil man>> ohne Transmit kein Receive durchführen kann ...>> Das ist korrekt. Aber kennen wir die anderen Deklarationen aus der> Codesammlung, aus der die hier diskutierte Funktion stammt?>>> Zudem ist ja ein pointer-type größer als ein uint8_t und man sich ja die>> zusätzliche Stacktiefe ersparen kann, wenn nur Input.>> O nein, das können ja auch mehrere uint8_t sein, ein Array, und die> Anzahl der zu sendenden Elemente ist entweder in der anderen übergebenen> Struktur verborgen,
Du meinst, man muss erst mit einer anderen Funktion die Länge des rohen
Arrays festlegen - Gott bewahre!
> implizit festgelegt oder wie z.B. bei in C> verwendeten Stringfunktionen durch ein Endezeichen (\0 o.ä.) definiert.
Oh je!!! Dann sollte es besser ein const char* sein, weil man dort per
Konvention den definitv ungültigen Wert '\0' gibt als Senstinel
erwartet. Bei primitiven DT ausser Zeiger gibt es per Definitionem keine
ungültigen Werte, die als Sentinel dienen könnten. Sonst könnte man ja
bspw. keine Werte 0 mehr senden.
>> Das kann man der Funktion so alles nicht ansehen.>>> Zum Thema Schnittstelle vllt noch folgender Link:>> https://isocpp.org/wiki/faq/const-correctness>> Das ist die Lehrbuchmeinung, aber --wie schon mehrfach erwähnt-- kann> man ohne die restlichen Funktionen aus der gleichen Feder zu kennen, das> nicht als gegeben ansehen.>> "const" ist eines der am meisten ignorierten (d.h. weggelassenen)> Schlüsselwörter in C/C++.
Es ist eines der wichtigsten, neben constexpr!
Weitere Spekulationen sind müßig - der Threadstarter müsste zumindest
mal die anderen zum Softwarepaket gehörenden Funktionsprotoypen
verraten, oder vielleicht auch einfach die Quelle nennen.
Da er sich hier aber noch nicht wieder hat blicken lassen ...
Googelt man übrigens nach dem Funktionsprototypen, so findet man /das
hier/ hier: