Forum: Mikrocontroller und Digitale Elektronik Projektstruktur - Verständnisfrage


von Blaupause (Gast)


Lesenswert?

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

von P. S. (Gast)


Lesenswert?

Das sind absolute Grundlagenfragen - meinst du, das Forum ist dazu da, 
jedem C einzeln beizubringen?

Kauf dir ein gutes Buch:

http://www.amazon.de/Programmieren-C-ANSI-2-C-Reference/dp/3446154973/ref=sr_1_2?ie=UTF8&s=books&qid=1269259532&sr=8-2

von Karl H. (kbuchegg)


Lesenswert?

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?

von ... .. (docean) Benutzerseite


Lesenswert?

das #include "....c" ist Müll und gehört sich nicht!

Sorgt nur für Chaos.

Das makefile ist nur eine Hilfe für dich. natürlich kannst du auch alles 
immer von hand eintippen, aber ob du das willst...

Für jedes Modul gibt es eine .h und eine .c, dann wird die .h in der 
main.c per #include eingebunden

siehe auch:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
http://www.mikrocontroller.net/articles/Include-Files_(C)

von Иван S. (ivan)


Lesenswert?

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

von Blaupause (Gast)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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.

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.