Hallo Leute,
ich habe eine Frage.
Und zwar bin ich gerade dabei das Funkuhr Projekt hier im Forum
nachzuempfinden.
http://www.mikrocontroller.net/articles/DCF77-Funkwecker_mit_AVR
Ich habe dazu ein paar Fragen.
1. Warum werden die Projekte in c und header files zerlegt? Wie geht man
hier am besten vor? Es ist scheinbar für jedes Main-Feature eine eigene
Kombination aus Header und C-File vorhanden.
Dann werden im header globale variablen sowie funktionen und ISR's
deklariert und in die .c eingebunden. Richtig?!
Die dcf77.c wird in der main per #include eingebunden und in der dcf77.c
wird der header dcf77.h eingebunden.
2. Im header wiederum sind mir zwei dinge nicht ganz klar.
Warum macht man den bedingten define in Zeile 1,2?! warum schreibt man
den header nicht einfach ohne??
3. Warum werden im header die funktion
dcf77_init,plausibilitaetscheck,dcf77_exec und die ISR's intialisiert
wenn in der .c doch wieder genau dasselbe gemacht wird? Ist das ein
Hinweis für den Compiler?
4. Als letzte Frage. Wozu dient das makefile? Ich sage dem Compiler doch
mit allen includes, was er einbinden soll und was nicht?!
So ich hoffe mal einer nimmt sich meiner an :-)
Dank euch
Blaupause schrieb:
> Ich habe dazu ein paar Fragen.>> 1. Warum werden die Projekte in c und header files zerlegt? Wie geht man> hier am besten vor? Es ist scheinbar für jedes Main-Feature eine eigene> Kombination aus Header und C-File vorhanden.
Die normale Vorgehensweise sieht so aus:
Man identifiziert Funktionen, die zu einem Themenkreis gehören. Diese
Funktionen werden in einer *.c Datei gesammelt. Dort drinnen befindet
sich also die Implementierung der Funktionen. Denjenigen, der die
Funktionen benutzt, soll die Implementierung normalerweise nicht
interessieren. Ihn interessiert nur, welche Funktionen es gibt, wie ihre
Argumentlisten aussehen und wenn dort spezielle Datentstrukturen
vorkommen, wie diese aussehen.
Grob gesagt ist die Unterteilung also
im .c ist die Implementierung
im zugehörigen .h ist die Schnittstellenbeschreibung, die für
denjenigen interessant ist, der dieses Modul benutzen möchte.
So ein Themenkreis könnte zb sein: Alles was zum Betrieb einer linearen
Liste notwendig ist, alles was zur Ansteuerung eines LCD notwendig ist,
alles was man benötigt um eine UART zu betreiben.
Das ist die generelle Idee. Natürlich kommmt es auch manchmal vor, dass
man Funktionen nur deshalb in eine eigene *.c auslagert, damit sie an
der verwendenden Stelle aus dem Weg sind.
Hat man zb ein Menü, bestehend aus 5 Menüpunkten und ist jeder Menüpunkt
ziemlich aufwändig, so kann es schon sein, dass man jeden Menüpunkt in
eine eigene Datei auslagert. Einzig und alleine aus dem Grund, dass man
studieren und lesen des Codes von einem Menüpunkt nicht durch die
IMplementierungen der anderen Menüpunkte abgelenkt ist.
Letztendlich geht es im Grunde um 2 Dinge
* Schaffung von Modulen, so dass diese Module möglichst rasch
und universell in jedes beliebige Projekt übernommen werden können
* Gewinnung von Übersicht, in dem man alles nicht relevant ausblendet
und sich so auf gewisse Codeteile konzentrieren kann.
Es gibt hier auch keine starren Regeln. Wie genau man die Unterteilung
und Aufteilung in verschiedene *.c macht, hängt von den persönlichen
Vorlieben und nicht zuletzt von seiner Erfahrung ab.
> Die dcf77.c wird in der main per #include eingebunden und in der dcf77.c> wird der header dcf77.h eingebunden.
*c Files werden nie mittels #include eingebunden.
Eingebunden werden immer nur Header Files.
Einzelne *.c werden getrennt compiliert und die Einzelteile zum
kompletten Programm gelinkt.
> 2. Im header wiederum sind mir zwei dinge nicht ganz klar.> Warum macht man den bedingten define in Zeile 1,2?! warum schreibt man> den header nicht einfach ohne??
Worauf beziehst du dich?
Hallo Blaupause,
ich arbeite zwar weder mit AVR noch benutze ich regelmässig C und das
Funkuhrprojekt im speziellen kenne ich auch nicht, ich hoffe trotzdem
Dir helfen zu können ;-)
> 1. Warum werden die Projekte in c und header files zerlegt? Wie geht man> hier am besten vor? Es ist scheinbar für jedes Main-Feature eine eigene> Kombination aus Header und C-File vorhanden.
Üblicher Weise stehen in der Headerdatei die Funktionsdeklarationen,
praktisch eine Art "Interface-Beschreibung". Die Quelltextdatei (.c)
enthält die konkrete Implementierung.
> Dann werden im header globale variablen sowie funktionen und ISR's> deklariert und in die .c eingebunden. Richtig?!
In der Headerdatei wird deklariert, in der C-Datei implementiert.
> 2. Im header wiederum sind mir zwei dinge nicht ganz klar.> Warum macht man den bedingten define in Zeile 1,2?! warum schreibt man> den header nicht einfach ohne??
Du beziehst dich vermutlich auf Konstrukte wie dem Folgenden:
#ifndef TIMERFUNCTIONS_H
#define TIMERFUNCTIONS_H
// some declarations here
#endif
Das ist ein sogenannter Guard, welcher dazu dient, mehrfaches Einbinden,
welches zu Fehlern führt, von vornherein auszuschließen.
> 3. Warum werden im header die funktion> dcf77_init,plausibilitaetscheck,dcf77_exec und die ISR's intialisiert> wenn in der .c doch wieder genau dasselbe gemacht wird? Ist das ein> Hinweis für den Compiler?
Wie gesagt, im Header wird die Schnittstelle definiert. Du kannst also
die Deklaration einer Funktion hier im Header einsehen, ohne den
Quelltext betatschen zu müssen.
> Die dcf77.c wird in der main per #include eingebunden und in der dcf77.c> wird der header dcf77.h eingebunden.
Das ist hier bei diesem konkretem Projekt in der Tat nicht sauber
gelöst, IMO.
> 4. Als letzte Frage. Wozu dient das makefile? Ich sage dem Compiler doch> mit allen includes, was er einbinden soll und was nicht?!
Was hindert Dich eigentlich daran, in die für Dich interessanten Dateien
einfach 'mal reinzuschauen? Einen Editor wirst Du ja wohl haben.
Dieses Makefile enthält Compileroptionen, Linkerflags und offensichtlich
einstellungen für ein mir nicht bekanntes Programm namens "Avrdude".
> So ich hoffe mal einer nimmt sich meiner an :-)
hth, Iwan
Hey danke, dass doch mal einige raufgeguckt haben :-)
Normalerweise reagier ich nicht auf getrolle, aber trotzdem:
Peter Stegemann schrieb:
> Das sind absolute Grundlagenfragen - meinst du, das Forum ist dazu da,>> jedem C einzeln beizubringen?> Kauf dir ein gutes Buch:
Ich habe sehr wohl ein C Buch (Helmut Erlenkötter) und habe dieses auch
gelesen. Leider werden hierdrin die ganzen Dinge um den Präprozessor nur
sehr stiefmütterlich behandelt. Deswegen ist man ja heil froh, dass es
Leute gibt, die ebn nicht nur dieses Buch zu Hause haben...
Иван S. schrieb:
> Das ist hier bei diesem konkretem Projekt in der Tat nicht sauber>> gelöst, IMO.
Das würd ich im makefile wie folgt lösen:
SRC = $(TARGET).c _7_segment.c dcf77.c timerfunctions.c
Richtig?!
Alternativ generiert das AVR Studio ja automatisch ein makefile. Das
heißt, wenn meine Datei im Ordner "Source Files" drinsteht wird sie auch
mit kompiliert und im makefile eingetragen. Jawoll?
Blaupause schrieb:
>> jedem C einzeln beizubringen?>> Kauf dir ein gutes Buch:>> Ich habe sehr wohl ein C Buch (Helmut Erlenkötter) und habe dieses auch> gelesen. Leider werden hierdrin die ganzen Dinge um den Präprozessor nur> sehr stiefmütterlich behandelt.
Dann ist das Buch nicht viel Wert.
Der Präprozessor ist mächtig, ist aber auch eine Waffe.
Eine Waffe mit der man umgehen lernen muss.
> Das würd ich im makefile wie folgt lösen:>> SRC = $(TARGET).c _7_segment.c dcf77.c timerfunctions.c>> Richtig?!
Sieht gut aus.
Es ist übrigens nicht verboten, Dinge auszuprobieren. Selbst wenn sich
das Ausprobierte als 'so gehts nicht' entpuppt: Eigene Erfahrung ist
durch nichts zu ersetzen.
> Alternativ generiert das AVR Studio ja automatisch ein makefile. Das> heißt, wenn meine Datei im Ordner "Source Files" drinsteht wird sie auch> mit kompiliert und im makefile eingetragen. Jawoll?
Ja.