Guten Morgen,
ich bin relativ neu in der Programmierung von Cortex M0/M3 und habe eine
Verständnisfrage zu der Verwendung von Structs.
Zuerst zum groben Aufbau meines Programmes:
Ich habe eine #include "globals.h", in der sind alle
variablendefinitionen für meine globalen Variablen aufgestellt. Hier
auch die Definition einer Structur.
struct Encoder
{
int ZeitDeltaA;
int ZeitDeltaAB;
float Drehzahl;
int Drehrichtung;
int Alive;
}Drehgeber;
Die "Variable" Drehgeber kann ich nun auch überall in der main, sowie in
diversen Interrupts verwenden. Der lesende, sowie schreibende Zugriff
fuktioniert soweit sehr gut.
Nun habe ich eine "Motorcontrol.h", sowoe eine "Motorcontrol.c"
geschrieben, in der ich gerne Subfunktionen für die Motorregelung
unterbringen möchte, um mein Programm übersichtlicher zu gestalten.
•
1
/* Header guard */
2
#ifndef FUNCTIONS_H
3
#define FUNCTIONS_H
4
5
6
/* Include-Dateien, je nach Funktion (SPI, USART, GPIO, RCC)*/
7
#include<stdbool.h>
8
9
/* Defines */
10
11
12
/* Typedefs, structs, unions und enums */
13
14
//struct bla {
15
// int bla;
16
//};
17
18
/* globale Variablen deklarationen */
19
//extern int bla;
20
21
/*alle Funktionsnamen hier rein*/
22
boolDrehrichtung(structEncodertest123);
23
24
25
#endif
1
//*********************************************
2
//**** Basis-Funktionen für Drehzahlerkennung und Motorregelung
3
//*********************************************
4
#include<MotorControl.h>
5
6
boolDrehrichtung(structEncodertest123)
7
{
8
returntrue;
9
}
Mein Problem ist nun, ich möchte als Übergabeparameter eine Structur
übergeben. Irgendwie habe ich haber hier scheinbar Verständnisprobleme.
Ganz abgesehen davon, dass Structuren noraleerweise nur über Pointer
angebunden werden um die Laufzeit zu optimieren, scheint es so, als wenn
er die Definition der Structur gar nicht kennen würde. Ein Aufruf in der
Main
1
intmain(void){
2
Setup();
3
test=0;
4
test2=0;
5
while(1)
6
{
7
if(SW2||test>5)
8
LED2On;
9
elseLED2Off;
10
11
if(SW3||test2>7||(Drehrichtung(Drehgeber)==true))
12
LED3On;
13
elseLED3Off;
14
15
if(SW4||Drehgeber.Drehzahl>4000.0)
16
LED4On;
17
elseLED4Off;
Kommt eine Fehlermeldung, dass die bergabearumente nicht stimmen würden.
WO hab ich den Knoten im Hirn, bzw.noch Grundlagenlücken?
Bin für jede ernst gemeinte Erklärung sehr dankbar.
struct Encoder wird in Motorcontrol.h im Funktionsargument als
Incomoplete type definiert, da struct Encoder aus globals.h nicht
definiert ist, da globals.h vorher nicht includiert wurde. An der stelle
ist ein Incomplete type aber nicht erlaubt, und eine struct definition
meist nutzlos. Drehgeber wird wiederum in globals.h definiert, das ist
der falsche Ort dafür. Entweder du teilst das auf Motorcontrol.c und
Motorcontrol.h auf, oder du erstellst ein globals.c.
H-Datei:
soundmachine schrieb:> Guten Morgen,>> ich bin relativ neu in der Programmierung von Cortex M0/M3 und habe eine> Verständnisfrage zu der Verwendung von Structs.>> Zuerst zum groben Aufbau meines Programmes:>> Ich habe eine #include "globals.h", in der sind alle> variablendefinitionen für meine globalen Variablen aufgestellt. Hier> auch die Definition einer Structur.>> struct Encoder> {> int ZeitDeltaA;> int ZeitDeltaAB;> float Drehzahl;> int Drehrichtung;> int Alive;> }Drehgeber;>
Das ist normalerweise keine gute Idee. Die Typdeklaration (alles bis zu
schließenden geschweiften Klammer) gehört tatsächlich in eine
Header-Datei.
Das nachgestellte "Drehgeber" allerdings deklariert eine globale
Variable vom Typ struct Encoder. Und zwar in allen .c-Dateien, die
diesen Header einbinden. gcc (der Linker, genauer gesagt) ist zwar so
schlau, all diese globale Variablen wieder zu einer einzigen
zusammenzuziehen, sauber ist das aber nicht. Variablendeklarationen
haben in Header-Dateien nichts verloren.
Dort gehört (nur) die Typdefinition hin:
1
structEncoder
2
{
3
intZeitDeltaA;
4
intZeitDeltaAB;
5
floatDrehzahl;
6
intDrehrichtung;
7
intAlive;
8
};
und möglicherweise die Information, daß in irgendeiner .c - Datei eine
globale Variable dieses Types deklariert wird:
1
externstructEncoderDrehgeber;
Die Deklaration gehört dann in die .c - Datei (irgend- aber nur eine):
1
structEncoderDrehgeber;
> Nun habe ich eine "Motorcontrol.h", sowoe eine "Motorcontrol.c"> geschrieben, in der ich gerne Subfunktionen für die Motorregelung> unterbringen möchte, um mein Programm übersichtlicher zu gestalten.>>
1
>/* Header guard */
2
>#ifndefFUNCTIONS_H
3
>#defineFUNCTIONS_H
4
>
5
>
6
>/* Include-Dateien, je nach Funktion (SPI, USART, GPIO, RCC)*/
7
>#include<stdbool.h>
8
>
9
>/* Defines */
10
>
11
>
12
>/* Typedefs, structs, unions und enums */
13
>
14
>//struct bla {
15
>// int bla;
16
>//};
17
>
18
>/* globale Variablen deklarationen */
19
>//extern int bla;
20
>
21
>/*alle Funktionsnamen hier rein*/
22
>boolDrehrichtung(structEncodertest123);
23
>
24
>
25
>#endif
26
>
>>>>>>>
1
>
2
>//*********************************************
3
>//**** Basis-Funktionen für Drehzahlerkennung und Motorregelung
4
>//*********************************************
5
>#include<MotorControl.h>
6
>
7
>boolDrehrichtung(structEncodertest123)
8
>{
9
>returntrue;
10
>}
11
>
12
>
>
Das hat mit deinem Problem nichts zu tun, aber eine (globale) Struktur
als Funktionsparameter zu übergeben, birgt ein paar Fallen. Die Struktur
wird byvalue übergeben, d.h. Änderungen daran finden nur an der lokalen
Kopie statt (die beim Verlassen der Funktion verworfen wird). Das kann
durchaus erwünscht sein, führt aber möglicherweise zu Verwunderung.
>> Mein Problem ist nun, ich möchte als Übergabeparameter eine Structur> übergeben. Irgendwie habe ich haber hier scheinbar Verständnisprobleme.> Ganz abgesehen davon, dass Structuren noraleerweise nur über Pointer> angebunden werden um die Laufzeit zu optimieren, scheint es so, als wenn> er die Definition der Structur gar nicht kennen würde. Ein Aufruf in der> Main>>
>>> Kommt eine Fehlermeldung, dass die bergabearumente nicht stimmen würden.>>> WO hab ich den Knoten im Hirn, bzw.noch Grundlagenlücken?>>> Bin für jede ernst gemeinte Erklärung sehr dankbar.
Wo der Fehler steckt, ist daran nicht erkennbar. Poste mal die exakte
Compiler-Fehlermeldung und die Zeilen, auf die sie verweist.
Möglicherweise hast Du vergessen, deine Header-Datei überall dort, wo
die Struct benutzt wird, zu includieren?
Hallo...
Danke an Markus und Daniel für die sehr Ausführliche Aufstellung.
Ein Paar Fragen bleiben aber noch.
Markus F. schrieb:> Variablendeklarationen> haben in Header-Dateien nichts verloren.> Dort gehört (nur) die Typdefinition hin:> struct Encoder> {> int ZeitDeltaA;> int ZeitDeltaAB;> float Drehzahl;> int Drehrichtung;> int Alive;> };>> und möglicherweise die Information, daß in irgendeiner .c - Datei eine> globale Variable dieses Types deklariert wird:> extern struct Encoder Drehgeber;>> Die Deklaration gehört dann in die .c - Datei (irgend- aber nur eine):> struct Encoder Drehgeber;
Worin liegt hier der Unterschied zu meiner Version? Mit "extern" gebe
ich ja nicht nur bekannt, dass die Variable extern irgendwo deklariert
wird,sondern er erstellt sie doch auch gleich. Ich muss sie nämlich
nichtmehr in einer .c Datei deklarieren, er kennt sie durch den extern
Aufruf und ich kann sie überall (auch in Interruptroutinen etc.)
verwenden.
Somit ist die Variable ja doch irgendwie in der .h Datei deklariert.
Zweite Frage: Ich habe bisher alle gobalen Variablen in der "globals.h"
errstellt. Also auch sowas wie z.B. int globaler_Zaehler.
In der Main hab ich die "globals.h" includiert und konnte dann diese
Variable in ALLEN Funktionen, auch Interruptroutinen verwenden. Wieso
funktioniert das bei Structuren nicht auch deckungsgleich
Dritte Frage:
Wenn die "globals.h" ausschließlich für defines und Definition von
Strukturen gedacht ist, wo deklariere ich dann "formschön" meine ganzen
globalen Variablen, und zwar so, dass ich sie auch wirklich überall
verwenden kann
soundmachine schrieb:> Mit "extern" gebe> ich ja nicht nur bekannt, dass die Variable extern irgendwo deklariert> wird,sondern er erstellt sie doch auch gleich.
Das ist falsch.
Mit extern hast du (nur) eine Deklaration und genau die gehören in die
.h
Die Definition gehört in eine .c Datei.
Wenn du die Variablen in der .h definierst, dann wird sie jedesmal neu
angelegt, wenn du sie in einer .c einbindest.
Das sind dann verschiedene Variablen.
Wenn du nur eine .c in deinem Projekt hast, fällt das nicht auf.
Hallo Dirk,
wie wäre denn dann die eigentliche saubere Vorgehensweise globale
Variablen anzulegen, die in allen über eine .h eingebundenen .c Dateien
verwendet werden können
Die Variablen werden dort definiert, wo sie gebraucht (.c Datei) werden
und in der entsprechenden .h datei mit extern deklariert.
Oder:
Du kannst alle globalen Variablen in einer global.c definieren und in
einer global.h (mit extern) deklarieren.
Die global.c fügst du dann deinem Projekt hinzu, Die global.h bindest du
mit #include dort ein, wo du die Variablen brauchst.
Speicherverbrauchender Code (Definitionen von Variablen und Funktionen)
gehört in .c
Informierender Code (Deklarationen) gehört in .h, aber nur soweit es für
die Nutzung der entsprechenden .c nötig ist.
Die .h beschreibt die Schnittstelle zur .c
Hi Dirk,
das bedeutet aber ich könnte eine "globals.h" erstellen nach dem Muster:
1
externinttest1;
2
externinttest2;
3
structteststruct
4
{inta;
5
intb;
6
}
dann eine entsprechende .c Datei
1
externinttest1;
2
externinttest2;
3
structteststructhallo;
und die Header Datei kann ich dann mehrfach includieren, also z.B. in
der Main und in meiner Motorcontrol.h-
Frage: - Ist das so richtig?
- Wird ´beim Mehrfachinkludieren der globals.h dann die Variable
nichta uch mehrfach angelegt, also in der main UND in der
Motorcontrol.c?
soundmachine schrieb:> dann eine entsprechende .c Datei> extern int test1;> extern int test2;> struct teststruct hallo;
in der c Datei, darf das extern icht mit rein.
soundmachine schrieb:> Frage: - Ist das so richtig?> - Wird ´beim Mehrfachinkludieren der globals.h dann die Variable> nichta uch mehrfach angelegt, also in der main UND in der> Motorcontrol.c?
Mir schien, als wüßtest du den Unterschied zwischen Deklaration und
Definition.
Deklaration: Bekanntgabe, dass da etwas mit dem Namen ist.
Definition: Anlegen von einem Objekt mit dem Namen.
In C beinhaltet eine Definiton auch eine Deklaration (aber nicht
umgekehrt)
Deklarieren kannst du soviel du willst.
Definieren darfst du nur einmal.
Wenn in der .h nur Deklarationen stehen, dann sollte die Anwort klar
sein. Oder?
Achja... copy paste Fehler...in der C ist selbstverständlich ein extern,
somit ist die Defnition dann an mehreren Stellen im Proramm. Die
Deklaration nur in der globals.c
In Beitrag "Re: Stuct Übergabe in C" geht es etwas
Durcheinander mit Deklarationen und Definitionen. Das Meiste ist
richtig, aber dann hat sich Markus wahrscheinlich verschrieben. Z.B.
stimmt Folgendes nicht:
Markus F. schrieb:> Variablendeklarationen> haben in Header-Dateien nichts verloren.
Doch. Definitionen haben in .h nichts zu suchen.
>> Die Deklaration gehört dann in die .c - Datei (irgend- aber nur eine):> struct Encoder Drehgeber;
Die Definition gehört in die .c-Datei.
Daher noch mal eine einfache Definition der Begriffe:
Deklaration:
Teilt dem Compiler mit dass es irgendwo die entsprechende Variable oder
Funktion gibt oder wie ein Datentyp aussieht. Belegt aber keinen
Speicherplatz. Gehört, wenn sie mit anderen Teilen des Programms geteilt
werden soll, in .h Header.
Definition:
Teilt dem Compiler mit, dass hier Speicher für eine Variable oder
Funktion belegt werden soll. Beinhaltet nebenbei auch eine Deklaration.
Gehört in .c Dateien, niemals in .h
Sonderfall: Globale Inline-Funktionen. Die kommen in .h Header. Aber das
lassen wir jetzt mal.
soundmachine schrieb:> Achja... copy paste Fehler...in der C ist selbstverständlich ein extern,> somit ist die Defnition dann an mehreren Stellen im Proramm. Die> Deklaration nur in der globals.c
Lies dir das nochmal durch, denn:
Peter II schrieb:> in der c Datei, darf das extern icht mit rein.
Er meinte *n*icht mit rein.
Und Deklaration und Definition hat Jack auch nochmal erklärt.
Hi...hoffentlich letzte Frage:
Habe jetzt DACHTE ich, die structur soweit verstanden:
In die .h gehören nur Definitionen. Also habe ich eine .h für meine
globalen Variablen nach folgendem Muster aufgebaut.
Dann habe ich in meiner Main ein #include "globals.h" eingebunden
und in meiner Motorcontrol.h ebenfalls die "globals.h" in der Hoffnung,
dass ich damit nun überall bekannt gemacht habe, dass es IRGENDWO noch
diese globalen Variablen gibt, nämlich in der im Projekt hinzugefügten
.c
Problem ist nur, dass er die Mehrfachdeklaration meiner struct scheinbar
nicht so komisch findet. Alles mündet in folgender Fehlermeldung:
P11_Testplatine/globals.h:32:8: error: redefinition of 'struct
PI_Control'
@Jack...sorry zu spät gelesen, daher geht bei mir Definition und
Deklaration schon wieder durcheinander. Habs aber jetzt verstanden. Der
Fehler bleibt weiterhin
Jap,
es sieht so aus als würde er nicht damit klar kommen, dass ich die
globals.h sowohl in der main,als auch in der Motorcontroller.h inkludert
habe.Somit definiert es das zweimal, kann das der Fehler sein?
soundmachine schrieb:> Jap,>> es sieht so aus als würde er nicht damit klar kommen, dass ich die> globals.h sowohl in der main,als auch in der Motorcontroller.h inkludert> habe.Somit definiert es das zweimal, kann das der Fehler sein?
Hast Du vielleicht ifndef / define im global.h vergessen?
Grüsse,
René