Hallo liebe Mikrocontroller Gemeinde,
ich habe ein Projekt in MPLAB X IDE v2.35 erstellt. Ich schreibe gerade
an einem kleinem Programm das CAN Botschaften empfängt und sendet.
Der Mikrocontroller ist der dsPIC30F4011.
Ich habe mein Projekt in mehrere C-Dateien "geteilt", hierdurch soll die
Übersicht besser erhalten bleiben.
Problem: Wenn ich in einer C-Datei eine Funktion schreibe bzw definiere
und in einer anderen verwende, dann werden Warnungen ausgeben beim
kompelieren.
Soweit ich das richtig verstanden habe, muss ich die Funktion in der
Datei, wo ich Sie genutzt habe, nochmal deklarieren.
Jetzt habe ich mir gedacht, dass ich die Funktionen einfach in einer
Headerdatei deklariere und den Header in allen C-Dateien include. Jedoch
werden dann wieder Warnungen ausgeben. Wodran liegt das? Was mache ich
falsch?
Und eine Frage nochmal direkt zu der Deklaration. Ich habe gedacht ich
kopiere einfach den "Kopf" der Funktion nochmal in das jeweilige Datei
bzw in die Header-Datei und schließe mit ; ab.
z.B.
void CAN_Send600(unsigned char variable);
Jedoch zeigt der Kompiler manchmal Fehler, (genau Formulierung habe ich
gerade nicht).
dann hilft es die Deklaration so programmieren:
void CAN_Send600();
Jetzt sind meine Fragen: Wie ist die saubere Vorgehensweise, um ein
Projekt sauber aufzubauen? Wie spielen die Dateien zusammen? Beispiel
Aufbau?
Mich fragt sich auch in welcher Reihenfolge die Dateien abgearbeitet
werden. Ich habe eine main.c, eine function.c, eine interrupt.c, eine
header.h.
Welche c-Datei wird zuerst abgearbeitet? Wie ist die Reihenfolge? Die
Dateien function.c und interrupt.c sind nicht in der main.c irgendwie
included oder ähnliches (Die Header Datei schon).
Ich freue mich schon auf eure Hilfe, damit ich mein Projekt anständig
aufbauen kann und keine Warnungen mehr angezeigt werden :)
Uwe S. schrieb:> Jetzt habe ich mir gedacht, dass ich die Funktionen einfach in einer> Headerdatei deklariere und den Header in allen C-Dateien include.
Genau so macht man das.
> Jedoch werden dann wieder Warnungen ausgeben. Wodran liegt das?> Was mache ich falsch?
Wir können leider nicht hellsehen. Welche Warnungen werden ausgegeben?
Quellcode?
Hast du schon selbst versucht, die Warnungen zu lesen, zu verstehen und
zu beheben?
Uwe S. schrieb:> Jedoch zeigt der Kompiler manchmal Fehler, (genau Formulierung habe ich> gerade nicht).
Schlecht - wie sollen wir da helfen? Meine Glaskugel ist defekt.
> dann hilft es die Deklaration so programmieren:> void CAN_Send600();
Das ist was völlig anderes als
1
voidCAN_Send600(unsignedcharvariable);
Schön, wenn es zufällig geht - richtig wird es dadurch trotzdem nicht.
Uwe S. schrieb:> Wie ist die saubere Vorgehensweise, um ein> Projekt sauber aufzubauen? Wie spielen die Dateien zusammen? Beispiel> Aufbau?> Mich fragt sich auch in welcher Reihenfolge die Dateien abgearbeitet> werden. Ich habe eine main.c, eine function.c, eine interrupt.c, eine> header.h.
Typischerweise werden nur die C-Dateien compiliert - in der vorgegebenen
Reihenfolge (Bei mir im Makefile - keine Ahnung, wie das bei MPLAB ist).
H-Dateien werden durch den Präprozessor eingebunden (#include ->
Google).
> Welche c-Datei wird zuerst abgearbeitet? Wie ist die Reihenfolge? Die> Dateien function.c und interrupt.c sind nicht in der main.c irgendwie> included oder ähnliches (Die Header Datei schon).
S. o.: Präprozessor macht Textersetzung: statt #include wird der
Dateiinhalt der H-Datei eingefügt.
Die C-Dateien hast du wohl zum Projekt hinzugefügt, d. h. MPLAB wird
diese alle compilieren und am Ende zusammen linken. Reihenfolge - keine
Ahnung.
Nachtrag: Jede C-Datei wird einzeln compiliert, d. h. "sieht" von den
anderen nichts. Das Ergebnis wird dann zusammen gelinkt.
Die Reihenfolge der Compilierung muss daher egal sein; ist sie das
nicht, ist etwas grob faul.
Uwe S. schrieb:> Ich habe mein Projekt in mehrere C-Dateien "geteilt", hierdurch soll die> Übersicht besser erhalten bleiben.
Löblich.
> Problem: Wenn ich in einer C-Datei eine Funktion schreibe bzw definiere> und in einer anderen verwende, dann werden Warnungen ausgeben beim> kompelieren.> Soweit ich das richtig verstanden habe, muss ich die Funktion in der> Datei, wo ich Sie genutzt habe, nochmal deklarieren.
Genau. Der Grund ist, dass der Compiler für unbekannte Funktionen keine
Typprüfung machen kann.
> Jetzt habe ich mir gedacht, dass ich die Funktionen einfach in einer> Headerdatei deklariere und den Header in allen C-Dateien include.
Genau richtig.
> Jedoch werden dann wieder Warnungen ausgeben. Wodran liegt das?> Was mache ich falsch?
Dass kann man so generell nicht beantworten. Manchmal liegt es daran,
dass sich Headerdateien gegenseitig inkludieren. Dann hilft das
Konstrukt
[c]
#ifndef _modul_h
#define _modul_h
... Hier hinein den eigentlichen Inhalt der Headerdatei
#endif //_modul_h
[/c}
> Und eine Frage nochmal direkt zu der Deklaration. Ich habe gedacht ich> kopiere einfach den "Kopf" der Funktion nochmal in das jeweilige Datei> bzw in die Header-Datei und schließe mit ; ab.> z.B.> void CAN_Send600(unsigned char variable);> Jedoch zeigt der Kompiler manchmal Fehler, (genau Formulierung habe ich> gerade nicht).> dann hilft es die Deklaration so programmieren:> void CAN_Send600();
Das erstere Herangehen (mit expliziten Parametertypen) ist vorzuziehen.
Wenn es Fehlermeldungen gibt, dann diese studieren und beheben.
> Jetzt sind meine Fragen: Wie ist die saubere Vorgehensweise, um ein> Projekt sauber aufzubauen? Wie spielen die Dateien zusammen? Beispiel> Aufbau?
Da gibt es viele Erfahrungswerte, z.b.:
*) Module möglichst schichten, also so, dass ein Modul B keine
Funktionen eines Moduls A benutzt, wenn das Modul A schon Funktionen von
B benutzt.
*) Schnittstellen so klein wie möglich.
*) So wenig globale Variable wie möglich.
Und natürlich unendlich viel Literatur ...
> Mich fragt sich auch in welcher Reihenfolge die Dateien abgearbeitet> werden. Ich habe eine main.c, eine function.c, eine interrupt.c, eine> header.h.> Welche c-Datei wird zuerst abgearbeitet? Wie ist die Reihenfolge? Die> Dateien function.c und interrupt.c sind nicht in der main.c irgendwie> included oder ähnliches (Die Header Datei schon).
Die Reihenfolge ist als undefiniert definiert, also als etwas, auf dass
man sich nicht verlassen darf.
> Ich freue mich schon auf eure Hilfe, damit ich mein Projekt anständig> aufbauen kann und keine Warnungen mehr angezeigt werden :)
Zeig mal die Warnungen.
LG, Sebastian
Pit schrieb:> Hallo,>> den Text in Deinen Header Dateien solltest Du in ein #ifndef / #endif> einkapseln:> #ifndef __MY_HEADER_DATEI_NAME> #define __MY_HEADER_DATEI_NAME>> //Hier Deine Definitionen ...>> #endif //__MY_HEADER_DATEI_NAME>> Dadurch erreichst Du, dass der Header nur einmal eingelesen wird und> verhinderst somit Mehrfachdefinitionen und einiges an Fehlermeldungen.
Du meinst wohl Deklaration, nicht Definition.
Deklaration:
Vielen Dank für die Vielen Antworten :), Ich habe meine Fehler jetzt
gefunden, manchmal übersieht man eine kleinigkeit die Große unterschiede
macht :)
Nochmal zurück auf Pit bzw TriHexagon.
Wenn ich eine neue Datei erstelle, ist automatisch dieser Code schon da:
#ifndef DEKLARATIONEN_H
#define DEKLARATIONEN_H
#ifdef __cplusplus
extern "C" {
#endif
!!! Hier kommt der selbst geschriebene Code hin? !!!
#ifdef __cplusplus
}
#endif
#endif /* DEKLARATIONEN_H */
Ist das richtig das der eigene Code dahin kommt, wo ich geschrieben habe
"Hier kommt der ..."? und nicht ans Ende der Datei?
Was hat es mit der cplusplus zeile auf sich?
Was sagen diese Elementeaus?
Hallo Uwe,
die Deklarationen innerhalb der Header-Datei kommen tatsächlich an die
Stelle wo Du
"!!! Hier kommt der selbst geschriebene Code hin? !!!"
geschrieben hast.
Dieser Abschnitt hier wird als Header-Guard bezeichnet. Soll verhindern,
das Header mehrfach eingebunden werden:
1
#ifndef DEKLARATIONEN_H
2
#define DEKLARATIONEN_H
3
...
4
#endif /* DEKLARATIONEN_H */
Der Block
1
#ifdef __cplusplus
2
extern "C" {
3
#endif
4
...
5
#ifdef __cplusplus
6
}
7
#endif
soll verhindern, dass Namen von Funktionen in C, der in C++-Code
eingebunden wird durch Name-Mangling nach C++ Konvention aufgelöst wird.
Stichwort Überladung.
Name Mangling bedeutet, dass Symbole, die der Compiler erzeugt (z.B.
Funktionen, globale Variablen, etc.) im Compileroutput nicht den
gleichen Namen haben wie im Quelltext.
mfg
Olaf
Uwe S. schrieb:> Wenn ich eine neue Datei erstelle, ist automatisch dieser Code schon da:>> #ifndef DEKLARATIONEN_H> #define DEKLARATIONEN_H>> #ifdef __cplusplus> extern "C" {> #endif>> !!! Hier kommt der selbst geschriebene Code hin? !!!>> #ifdef __cplusplus> }> #endif>> #endif /* DEKLARATIONEN_H */>> Ist das richtig das der eigene Code dahin kommt, wo ich geschrieben habe> "Hier kommt der ..."? und nicht ans Ende der Datei?>> Was hat es mit der cplusplus zeile auf sich?> Was sagen diese Elementeaus?
Uh, oh.
1. "DEKLARATIONEN" solltest du durch den Dateinamen der jeweiligen
Header-Datei ersetzen. Wenn dieser Codeschnipsel genau so in zwei
Header-Dateien auftaucht, dann wird der Inhalt der zweiten inkludierten
Header-Datei ja ausgeblendet, weil in der ersten schon #define
DEKLARATIONEN_H steht.
2. __cplusplus ist genau dann vom Compiler vordefiniert wenn er den Code
als C++ übersetzt. extern "C" {...} führt dann dazu, dass der Code
innerhalb von {...} quasi als C-Code übersetzt wird. Das ist nur dann
wichtig wenn man C und C++ mischt. Details hat Olaf ja schon erklärt.
Wenn du nur C oder nur C++ benutzt dann lass diesen Teil besser weg.
LG, Sebastian