Also, im Anhang mal das Programm.
Ich würde gerne hingehen und den ganzen krams, bis auf die
Hauptfunktion, in eine .h datei auslagern.
Sowas habe ich bisher noch nie gemacht und mit einem einfachen billigen
printf befehle, ausgelagert in einer Funktion, die wiederrum in einer .h
datei steht, klappt das einwandfrei.
Mein Sourcecode läuft ebenfalls einwandfrei, allerdings lässt er sich
nicht auslagern.
Ich habe einfach alles, bis auf Programm hauptteil in eine .h datei
gepackt.
Natürlich oben schön include "displayinit.h".
Dann zeigt mir der Compiler aber in allen funktionsaufrufen beim
compilieren das an: ERROR 104: MULTIPLE PUBLIC DEFINITIONS SYMBOL:
delay(DISPLAYINIT)
Woran liegt es und wo mache ich da den fehler?
Vielleicht wäre es sinnvoll, Deinen Header-Versuch auch mal zu posten.
Ich vermute aber stark, dass Du da was falsch verstanden hast: In eine
Header-Datei werden keine Funktionen an sich ausgelagert. Die
Header-Datei enthält ausschließlich Variablen- und
Funktions-(Prototypen) Deklarationen. Die eigentlichen Funktionen kommen
in eine .c-Datei, die separat kompiliert wird. Und drauf achten, dass in
der Header-Datei "extern"-Deklarationen verwendet werden.
Das extern weg, das gehört da net hin. Ganz oben in die .h
#ifndef _FUNCTIONS_H
#define
und ganz unden
#endif
rein, sonst knallts wenn du das mehrfach einbindest.
Bei den letzten beiden Funktionen hast du keinen Rückgabetyp angegeben,
sowas kann zu merkwürdigen Fehlermeldungen führen. Und zeig mal die
beiden anderen Dateien, so wie das aussieht kommt das nicht (nur) von
der functions.h.
Also wenn ich bei den letzten beiden ein void davor setze, erhalte ich
nurnoch den fehler
Type error in second_byte redeclaration
und put_to_lcd redeclaration.
Der Fehler tritt dann also bei den beiden Funktionen auf.
Das ist die test.c
#include "functions.c"
#include <reg51.h>
#include "displayinit.h"
sfr leds=0x80; //Hier ist die led low activ verschaltet.
sbit DB4=0xB0;// Die Bezeichnungen der Ports des Displays
sbit DB5=0xB1;//1 zu 1 verkabel wie der Name, also DB5 an D5
sbit DB6=0xB2;
sbit DB7=0xB3;
sbit RS=0xB4;
sbit EN=0xB5;
sfr port_B0=0xB0;
void main (void)
{
char display_ausgabe[12];
int i=0,length=12;
timer_init(); //Zuerst timer initialisieren!
display_init(); //Display init ausführen!
clear_display();
strcpy(display_ausgabe, "Hello World!");//SPEICHERRAUBEND und schreibt
müll in leere Zeichen bei length 20
do{
put_to_lcd(display_ausgabe[i]);
i++;
}
while (i<length);
while(1);
{
}
}
Aaalso:
> Das ist die test.c
#include "functions.c"
macht man üblicherweise nicht, geht aber. Normalerweise wird das beides
getrennt kompiliert (.o) und dann erst zusammengelinkt. Geht aber auch
so.
> Type error in second_byte redeclaration
und put_to_lcd redeclaration.
Guck mal in die functions.c welchen Rückgabetyp du den beiden funktionen
dort gegeben hast. Der muss mit dem in der functions.h übereinstimmen.
Also mal langsam, kein Rückgabewert bedeutet "void" (das ist dann der
Rückgabetyp) und dann schreibst du in den Code "return;" ohne irgend'nen
Wert. Funktionen ohne Angabe vom Rückgabetyp gibt es nämlich nicht, das
läuft dann zwangsläufig auf einen Fehler hinaus.
Und "return 0;" könnte alles mögliche sein. Poste doch mal die
functions.c, die fehlt.
Vielleicht solltest du dich erstmal ein bisschen mit C beschäftigen, das
gehört schon zu den grundlegendsten Grundlagen.
displayInit.h != displayinit.h
Also probiers mal mit gleicher Schreibweise... Der findet vielleicht
nicht mal die Datei.
Wenn du keinen Rückgabewert hast, muss die Funktion als void deklariert
werden, jeder anständige Compiler würde da meckern.
I_ H. wrote:
> Das extern weg, das gehört da net hin.
Stimmt natürlich, bei Funktionsprototypen ist es überflüssig (schadet
aber auch nicht)...
Hab grad gesehen, dass der gute Karl Heinz einen Wiki-Artikel zu dem
Thema verfasst hat:
http://www.mikrocontroller.net/articles/Funktionen_auslagern_%28C%29
I_ H. wrote:
> Also mal langsam, kein Rückgabewert bedeutet "void" (das ist dann der> Rückgabetyp)
Fast.
Kein angegebener Rückgabetyp bedeutet 'int'
@Oliver
Es ist aber trotzdem besser, man nutzt dieses 'Feature' nicht aus,
sondern gewöhnt sich gleich guten Stil an:
Wenn eine Funktion einen int retourniert, dann lautet das
int foo()
{
return 0;
}
Wenn eine Funktion keinen Rückgabewert hat, dann lautet das
void foo()
{
// eventuell ein mglw. vorzeitiger return;
}
Lass den Compiler sowenig Annahmen wie möglich treffen.
Oliver D. wrote:
> Ich habe mir den wiki artikel durchgelesen und danach gearbeitet.
Der Artikel ist nicht besonders gut, weil er eigentlic aus
einer Anfrage, bei der es um 'extern' gegangen ist stammt.
Hat es denn trotzdem funktioniert?
>> In meinem C buch steht übrigens garnichts zu header datein!
In deinem C-Buch stehen wahrscheinlich noch viele anderen
Praxistips zu C nicht drinnen :-)
Ich versuch mal eine Wette:
Ich wette, dass in deinem Buch eine Fahrenheit / Celsius umrechnung
drinnen ist und in dieser Umrechnung der Datentyp float vorkommt,
während double da drinn überhaupt nicht vorkommt. Generell
kann man sagen, dass im Buch als Standard-Gleitkommatyp meistens
float verwendet wird.
(Die Chancen für ein gewinnen der Wette stehen bei ca. 60%)