Hallo zusammen, ich bin noch etwas unbeholfen, daher vielleicht die dämliche Frage. Die Suchfunktion bringt hier ja an die 10^10 Treffer beim Thema Entprellroutine. Mir geht es aber auch nicht um deren Funktion oder ähnliches, sondern nur um die korrekte Einbindung. Ist es korrekt, dass ich die Entprellroutine als Headerdatei einbinde? Oder gehört die Routine garnicht über eine zweite Datei eingebunden? Oder als C-File? Soweit ich bisher weiß, mache ich doch eigentlich in einer Headerdatei nur die Funktionen dem Compiler/Präprozessor bekannt? Hinzugefügt habe ich der beigefügten Haderdateie das typische #ifndef KEY_ROUTINES_H_ #define KEY_ROUTINES_H_ #endif Im Anhang sind meine beiden Dateien. Was mich gewundert hat: Beim einbinden als C-File bekomme ich Fehlermeldungen, als H-File keine. Gemeckert wurde (glaube ich) über die doppelte Bekanntmachung der Funktionen und den Vektor 16 (TIMER0_OVF). Scheinbar ist der Unterschied zwischen .h und .c doch größer. Aufgespielt hatte ich den Code noch nicht, werde ich gleich mal nachholen. Mir geht es natürlich auch um die Funktion, aber auch ob ich das so richtig mache. Ich will ja nichts falsches lernen oder Unsinn machen, den andere auf die Palme bringen ;) Daher lieber mal vorsichtig nachgefragt. Ich freue mich auf eure Antworten :) Vielen Dank! Schönen Abend, Nils PS: Ich hoffe das war das richtige Forum, war mir nicht sicher ob das nicht nach Compiler/Ide gehört...
In Header-Dateien gehört kein Programcode, sondern nur Funktions-Prototypen und Makros Du solltest dich erstmal informieren wie man C-Programme strukturiert
Hallo Nils, Ein C Programm kann aus unterschiedlichen C - Dateien bestehen, über die H - Dateien deklariert man u.a. die Schnittstellen, also die öffentlichen Funktionen oder auch öffentliche (global) Variable. Die C - Dateien werden durch den Compiler übersetzt (*.o) und im Linkerlauf verbunden und mit den noch benötigten Bibliotheken "verbunden". Daraus erhält man das ausführbare Programm.
Solange es bei einer C-Datei bleibt wird das funktionieren. Der Compiler sieht ja nur ein langes Programm. Ab der zweiten, die auch "Keyboard" inkludiert gibt es einige doppelte Labels, da die "Key"-irgendwas Funktionen dann mehrfach übersetzt wurden. Deshalb Trennung von Deklaration und Definition. Im .h stehen Funktionsprototypen und extern deklarierte Daten. Ein .c enthält die (in nur genau diesem vorkommende) Implementierung.
Nils R. schrieb: > war mir nicht sicher ob das nicht nach Compiler/Ide gehört... Nur wenn du konkret Fragen zum Verhalten eines bestimmten Compilers oder einer Toolchain hast. Kirsch hat fast völlig Recht. Allerdings können einzelne Zeilen Programmcode durchaus in Form von Makros in einem Headerfile auftauchen. Keinesfalls aber komplette Funktionen...
:
Bearbeitet durch Moderator
Hallo Nils In der Programmiersprache C ist es normalerweiße überlich die Funktionen in eine c-Datei und die Funktionsdefinitionen für öffentliche Funktionen in eine h-Datei zu schreiben. Sprich, in deinem Fall müsstest du dir eine c-Datei anlegen und den Code aus der h-Datei dort hinein kopieren. In der main-Datei wie schon von dir richtig implementiert, die h-Datei einbinden. Der Include-Guard kommt / bleibt in der h-Datei. Gruß Leo
OK, danke für die Ratschläge. Einiges war mir zwar bewusst, wusste es aber aufgrund von Fehlermeldungen nicht umzusetzen. Nachdem ich nun verstanden habe, warum die Fehlermeldungen da waren, habe ich es entsprechend umgeschrieben. Im Anhang nochmal die Dateien. Die main.c bindet nur key-routines.h ein und erledigt die konfigartion des Timers. In der key-routines.h sind jetzt nur #defines und die fünf Funktionsprototypen. Die Datei key-routines.c enthält die drei benötigen Variabeln, die ISR und die fünf Funktionen. Weiterhin werden hier auch die für diese Datei benötigten Headerdateien (wie auch key-routines.h) eingebunden. Wäre das so jetzt richtig, oder ist das immer noch totaler Käse? Tut mir leid für die Fragen, aber ich bin etwas erschlagen von der schieren Informationsflut. Dafür reichen meine C-Kenntnise einfach noch nicht aus. Schonmal ein dickes Danke von mir! :)
Sieht gut aus. Pack aber die includes in der key-routines.c noch in die Headerdatei mit rein. Wenn man dein Modul "key-routines" in einem anderen main-Programm einbindet hat man automatisch die notwendigen includes für das Modul schon mit der einzigen Headerdatei key-routines.h erschlagen. Vielleicht noch ein Tipp für die Zukunft: Du darfst bei deinem Moduldesign nicht davon ausgehen, dass der User die notwendigen Includes neben deiner Modulheaderdatei selbst einbindet. Beispiel key-routines.h:
1 | #define KEY_DDR DDRB |
Hoppla, was ist denn "DDRB" ? => Du erwartest, dass <avr/io.h> vorher eingebunden wird
1 | uint8_t get_key_press( uint8_t key_mask ); |
Hoppla, was ist denn "uint8_t" ? => Du erwartest, dass <stdint.h> vorher eingebunden wird. Das ist schlechtes Design!
Ok, danke für die Hinweise. Das macht natürlich Sinn :) Jetzt stehen alle includes, außer "#include key-routines.h", in der Headerdatei. Bleibt nur noch die Frage, ob das nicht trotzdem Blödsinn war, das ganze auszulagern. Wie handhabt ihr das? Ich hatte das hier mal so versucht, da auch die LCD-Routine ausgelagert war. Gut, die ist auch einiges größer. Und schreibt man eigentlich die Konfiguration der Ports und Pins in die jeweilige Headerdatei, oder lieber alles an einer Stelle ins Hauptprogramm? Bestimmt wird das schnell unübersichtlich, wenn alles auf mehrere Dateien verteilt ist. Gut, dass es so ein tolles Forum gibt. Da kann man einiges an Erfahrung sammeln :)
Auslagern ist gut, wenn das Projekt dadurch übersichtlicher wird oder wenn man den Quelltext dadurch leichter in andere Projekte kopieren kann. Lass den Compiler ruhig für Dich arbeiten.
Denk doch einfach mal daran, dass du im Laufe deines Lebens viele Programme schreiben wirst für (erstmal) den selben Mikrocontroller. Einfaches Beispiel: UART Modul zur Ausgabe von Daten am PC. Wenn du dieses Modul so anwendungsunabhängig machst wie nur möglich, kopierst du den UART Ordner in jedes neue Programm und hast sofort einen Kommunikationskanal.
Nils R. schrieb: > OK, danke für die Ratschläge. Einiges war mir zwar bewusst, wusste es > aber aufgrund von Fehlermeldungen nicht umzusetzen. Ein paar Ratschläge brauchst du aber noch. Lies mal: #define KEY_DDR DDRB #define KEY_PORT PORTB #define KEY_PIN PINB #define KEY0 0 #define KEY1 1 #define KEY2 2 #define ALL_KEYS (1<<KEY0 | 1<<KEY1 | 1<<KEY2) Nun? Fällt dir was auf? Ich sag's mal so: Wenn du ins Postamt gehst und dort einen Brief abgibst, interessiert es dich eigentlich nur, daß er richtig ankommt. Aber mit welchem Postauto er transportiert wird, sollte dich nix angehen - das ist ne interne Sache der Post. Übersetzt nach C lautet das: 1. Schreibe in ein Headerfile wirklich nur das hinein, was andere Programmteile über das Innenleben der zugehörigen C-Datei unbedingt wissen müssen - und nicht mehr. 2. Schreibe Treiber. Jaja, richtige Treiber. Das sind Programmteile, die ein Stück Hardware abstrahieren. Für einen Tasten-Treiber brauchst du eigentlich eher nur sowas (nimm mir das Neu-Denglisch mal nicht übel):
1 | #define id_Enter 1
|
2 | #define id_Rauf 2
|
3 | #define id_Runter 3
|
4 | // usw. je nach Gusto
|
5 | |
6 | // liefert TRUE, wenn ein neuer Tastendruck vorliegt
|
7 | // oder die Repetierfunktion zugeschlagen hat
|
8 | extern bool KeyID_Available (void); |
9 | |
10 | // liefert das Zeichen, was die gedrückte Taste
|
11 | // geliefert hat
|
12 | extern char Get_KeyID (void); |
13 | |
14 | // liefert TRUE, solange die betreffende Taste gedrückt ist
|
15 | extern bool IsKeyPressed (char KeyID); |
und mehr braucht in der Headerdatei nicht zu stehen. Schließlich ist es dem aufrufenden Programm ja egal, an welchem Port des µC die Entertaste oder die vier Cursortasten angelötet sind. Es will ja nur wissen, ob es einen Tastendruck (und zwar einen NEUEN Tastendruck, deswegen ja die Entprellung) zu verarbeiten hat oder nicht. Die letzte Funktion braucht man nur, wenn man (wie bei PC-Spielen) irgendwas machen will, solange irgend eine Taste im gedrückten Zustand ist. Tja - und alles andere treiberinterne Zeugs kommt in die C-Datei. W.S.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.