Forum: Mikrocontroller und Digitale Elektronik Funktion mit Pointerübergabe


von Sebastian Kaulitz (Gast)


Lesenswert?

Hallo zusammen

Ich habe mir zu Pointern nun einiges durchgelesen, aber bzgl. meines 
Problems habe ich nichts Konkretes gefunden. Immer wenn es interessant 
wurde, was mein Problem fast gelöst hätte, wurde die notwendige 
Erklärung irgendwie ausgelassen.

Nun versuche ich dies selbst zu implementieren und habe da einige 
Fragen.

Ich habe hier im def.h einen struct definiert.
Im sendperiph.h bzw. c eine Funktion mit dem Typ struct Numbers.
Im main habe ich einen struct erzeugt.

Jetzt ist es mein Ziel, der Funktion transmit den struct zu übergeben 
bzw. die Adresse des ersten Elements, sodass ich mir aussuchen kann, ob 
ich zuerst die 0, 1 oder 2 schicke mittels SPI.
Wie mache ich das jetzt am Besten?

So wie unten ausgeführt heisst es im header-file, dass die Deklaration 
von struct Numbers ausserhalb der Funktion nicht sichtbar ist als 
Warnung und als error conflicting types for transmitCode.

Ich hätte jetzt gemeint, dass ich einen pointer übergeben muss, denn 
damit übergebe ich ja die Adresse des structs. Aber diese ist vom Typ 
struct Numbers und die SPI Funktion verlangt einen pointer vom Typ 
uint8_t.
Ich verstehe irgendwie nicht wie das funktionieren soll. Casten kann man 
ja auch nicht so einfach.

Könnte mir hierbei jemand vielleicht behilflich sein?

Übrigens ist die SPI-Funkt. vom STM32. Die sind ja immer gleich 
aufgebaut.
1
#ifndef DEF_H
2
#define DEF_H
3
4
struct Numbers{
5
uint8_t zero,  
6
        one,
7
        two;
8
};

1
#ifndef sendperiph_H
2
#define sendperiph_H
3
4
void transmit(struct Numbers *number);
5
6
#endif

sendperiph.c
1
void transmit(struct Numbers *number)
2
{
3
      HAL_SPI_Transmit(&hspi1,  &number , sizeof(number), x_ms);
4
      angenommen hier werden neben der SPI Transmit noch andere Operationen 
5
      mit dem Pointer number ausgeführt.
6
7
}
1
int main(void)
2
{
3
4
  struct Numbers numbers = {0x7E, 0x30, 0x6D};
5
  struct Numbers *pNumber;
6
  pNumber = &numbers;
7
  
8
  transmit(pNumber);

von N2 (Gast)


Lesenswert?

Hi,

Warum nutzt Du überhaupt eine struct, wenn die SPI_Transmit ein uint_8* 
erwartet ?
Oder Lehrzwecke ?

Seis drum:

struct Numbers{
 uint8_t data[3];
};

HAL_SPI_Transmit(&hspi1,  (uint8_t*) number->data , 
sizeof(number->data), x_ms);


Gruß

von Teo D. (teoderix)


Lesenswert?

Sebastian Kaulitz schrieb:
> struct Numbers *pNumber;
>   pNumber = &numbers;

???

transmit(&numbers);

von N2 (Gast)


Lesenswert?

Hi Teo,


Ist umständlich, aber nicht falsch...

Gruß

von devzero (Gast)


Lesenswert?

Warum castest du nicht einfach auf uint8_t*? Sollte eigentlich klappen 
in dem Fall.

Compilerfehlermeldung?

von devzero (Gast)


Lesenswert?

Sowas wie (uint8_t*) &numbers.zero stelle ich mir vor

von Rolf M. (rmagnus)


Lesenswert?

Sebastian Kaulitz schrieb:
> So wie unten ausgeführt heisst es im header-file, dass die Deklaration
> von struct Numbers ausserhalb der Funktion nicht sichtbar ist als
> Warnung und als error conflicting types for transmitCode.

Das stimmt ja auch.

> Ich verstehe irgendwie nicht wie das funktionieren soll. Casten kann man
> ja auch nicht so einfach.

Kann man schon. Besser ist es aber, das Programm so zu schreiben, dass 
möglichst wenig Casts nötig sind. Hier wäre der Cast nötig, weil du eine 
struct statt ein Array verwendet hast. Und weil HAL_SPI_Transmit aus 
irgendeinem Grund einen uint8_t* statt einen void* haben will.

> Übrigens ist die SPI-Funkt. vom STM32. Die sind ja immer gleich
> aufgebaut.
> #ifndef DEF_H
> #define DEF_H
>
> struct Numbers{
> uint8_t zero,
>         one,
>         two;
> };
>
> #ifndef sendperiph_H
> #define sendperiph_H
>
> void transmit(struct Numbers *number);
>
> #endif

Werden diese beiden Header auch irgendwo verwedet?

> sendperiph.c
> void transmit(struct Numbers *number)
> {
>       HAL_SPI_Transmit(&hspi1,  &number , sizeof(number), x_ms);
>       angenommen hier werden neben der SPI Transmit noch andere
> Operationen
>       mit dem Pointer number ausgeführt.

So überträgst du den Zeiger, nicht das, worauf er zeigt. number ist ein 
Zeiger auf deine Daten, aber du übergibst nicht den Zeiger, sondern 
seine Adresse an die Transmit-Funktion. Und auch das sizeof ermittelt 
die Größe des Zeigers und nicht die von dem, worauf er zeigt.

: Bearbeitet durch User
von jzjjf (Gast)


Lesenswert?

1
struct Numbers{
2
uint8_t zero,  
3
        one,
4
        two;
5
};
6
7
void transmit(struct Numbers *number )
8
{
9
  HAL_SPI_Transmit(&hspi1,(uint8_t*)number ,sizeof(struct Numbers), x_ms);
10
11
  number->zero = 0;
12
  number->one++;
13
  
14
}
15
16
int main(void)
17
{
18
  struct Numbers numbers = {0x7E, 0x30, 0x6D};
19
20
21
  
22
  transmit( &numbers );

das funzt auch nur wenn alle member uint8_t sind.
sonst muss man sich was einfallen lassen wegen aligning und der 
bytereihenfolge

von fop (Gast)


Lesenswert?

Sebastian Kaulitz schrieb:
> HAL_SPI_Transmit(&hspi1,  &number , sizeof(number), x_ms);

Mal abgesehen davon, wie es Andere viel toller machen würden, denke ich, 
dass hier Dein Fehler liegt. &number ergibt einen Zeiger auf einen 
Zeiger auf ein Struct. Das ist vermutlich nicht das, was die 
HAL_SPI_Transmit erwartet.
Sollte wohl ein
1
HAL_SPI_Transmit(&hspi1,  &(number->one) , sizeof(number->one), x_ms);
sein, oder ? Wobei ein -> zwei Dinge auf einmal macht :
- den Inhalt auf den der Zeiger zeigt rauskramen, wie man es sonst mit 
dem Ausdruck *Zeiger macht
- ein Element des Structs auszuwählen, was man sonst mit Struct.Element 
macht

Ansonsten hast Du Dein Beispiel so weit gekürzt, dass man nicht mehr 
sieht, was in welcher Reihenfolge eingebunden wird. Die def.h muss immer 
eingebunden sein, bevor Du den Namen Numbers benutzt. Also auch bevor Du 
sendperiph.h einbindest.

von Peter D. (peda)


Lesenswert?

Sebastian Kaulitz schrieb:
> struct Numbers{
> uint8_t zero,
>         one,
>         two;
> };

Was hast Du dir dabei gedacht?
Warum kein Array, wie es jeder macht?

Sebastian Kaulitz schrieb:
> void transmit(struct Numbers *number)
> {
>       HAL_SPI_Transmit(&hspi1,  &number , sizeof(number), x_ms);

Das ist Bullshit, Du mußt die Länge des Arrays übergeben.
Die Größe eines Pointers ist konstant 4 Byte aufm ARM.

Man kann auch die Länge mit in einem Struct übergeben:
1
  struct tx_buff{
2
    uint8_t len;
3
    uint8_t tx_data[20];
4
  };

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Sebastian Kaulitz schrieb:
> HAL_SPI_Transmit(&hspi1,  &number , sizeof(number), x_ms);

Das &number im Aufruf ist schon falsch, da number bereits ein Pointer 
ist. Pointer von Pointer ist hier Murks. sizeof() wird ebenso falsch 
angewendet, weil das der Größe des Pointers entspricht und nicht der 
Länge der Daten.

Allein schon wegen dem möglichen Alignment, welches auf bestimmten 
Prozessoren dafür sorgt, dass zwischen den Struct-Members Lücken 
auftreten, sollte man hier auf eine Struct verzichten und einfach ein 
Array nehmen:
1
void transmit(uint8_t * number_ptr, int len)
2
{
3
     HAL_SPI_Transmit(&hspi1, number_ptr, len, x_ms);
4
}
5
6
int main(void)
7
{
8
    uint8_t numbers[3] = { 0x7E, 0x30, 0x6D };
9
    transmit(numbers, 3);
10
    return 0;
11
}

: Bearbeitet durch Moderator
von Sebastian Kaulitz (Gast)


Lesenswert?

Hallo zusammen

Einige Beiträge wurden hier irgendwie entfernt. ZB das von mir und Dr. 
Sommer.

Ich würde gerne wissen, woher ihr das Wissen habt. Ich habe nun schon 
etwas über structs gelesen, aber von Alignment etc. habe ich noch nichts 
gehört oder gesehen.
Wo findet man denn eine Lektüre, welches die Grundlagen von C wirklich 
behandelt?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Sebastian Kaulitz schrieb:
> Einige Beiträge wurden hier irgendwie entfernt. ZB das von mir und Dr.
> Sommer.

Nein, hier wurde nichts gelöscht. Du verwechselst offenbar diesen Thread 
mit jenem hier, den Du ebenso eröffnet hast:

  Beitrag "SPI DMA Adresse"

Auch dort wurde nichts gelöscht. Die Beiträge von Dr. Sommer sind dort 
alle sichtbar.

von Dr. Sommer (Gast)


Lesenswert?

Sebastian Kaulitz schrieb:
> Ich würde gerne wissen, woher ihr das Wissen habt

Aus C++ Büchern.

Sebastian Kaulitz schrieb:
> von Alignment etc. habe ich noch nichts
> gehört oder gesehen.
Das ist auch von C bzw. C++ nicht spezifiziert; in einem korrekten 
Programm bekommt man davon nichts mit. Wenn man aber einfach Pointer 
umcastet und z.B. ein struct als char-Array betrachtet fangen die fiesen 
plattformspezifischen Details an. Siehe auch: Serialisierung

von Sebastian Kaulitz (Gast)


Lesenswert?

aus welchen Büchern?
Welche sind denn gut zu empfehlen?

von Dr. Sommer (Gast)


Lesenswert?

Sebastian Kaulitz schrieb:
> aus welchen Büchern?
> Welche sind denn gut zu empfehlen?

Leider gibt es viele schlechte Bücher; hier ist eine gute Liste:
https://stackoverflow.com/a/388282

von Dirk B. (dirkb2)


Lesenswert?

Sebastian Kaulitz schrieb:
> Wo findet man denn eine Lektüre, welches die Grundlagen von C wirklich
> behande

Der K&R (in der zweiten Ausgabe) und der ISO-Standard zu C (gibt es auch 
als freien Draft im Netz)

von Pointerübergabe (Gast)


Lesenswert?

Sebastian Kaulitz schrieb:
> Wo findet man denn eine Lektüre, welches die Grundlagen von C wirklich
> behande

Ich finde

Harbison & Steele, C: A Reference Manual, 5th Edition | Pearson

https://www.pearson.com/us/higher-education/progra...

deutlich besser als den K&R.

Ein Kommentar auf https://news.ycombinator.com/item?id=1245535
sieht's ähnlich:
I personally find Steele's C: A Reference Manual far more useful in day 
to day hacking.

und:

I found K&R great ... until I got to the arrays and pointers chapter. It 
wasn't my inability to get the concept, I think, the Lions' Commentary n 
UNIX 6th Edition, with Source Code which I tried next did the trick.
And nowadays I too keep Harbison and Steele handy, I lost track of my 
copy of K&R sometime in the '80s.

von Dirk B. (dirkb2)


Lesenswert?

Bei
https://www.c-plusplus.net/forum/topic/300567/linkliste-für-neulinge
Gibt es u.a. die Links zu den ISO Standards.

Die sind nicht zum lernen gedacht, sondern beschreiben, was wie wenn 
überhaupt oder nicht gemacht werden muss/kann/darf.

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.