Forum: Mikrocontroller und Digitale Elektronik Header File


von Mike (Gast)


Lesenswert?

Hallo zusammen

Habe leider immernoch das gleiche Problem. Habe schon mit Fritz über
mein Problem diskutiert, er meinte jedoch, dass man die extern
Anweisungen nicht ins Headerfile schreibt. Bei mir in der Schule habe
ich es jedoch so gelernt. Nun nochmals mein Problem, habe folgenden
Code geschrieben:
Hallo Zusammen, habe folgendes Problem:
-------------------------------main.h--------------------------------

#ifndef main_h
#define main_h

typedef struct drink1 {

  unsigned char menge_orangensaft;
  unsigned char menge_vodka;
};

#endif

-------------------------main.h---------------------------------------

-------------------------main.c---------------------------------------

#include "main.h"

drink1 drink_screwdriver = {12,4};

void main(void)
{
programm...
}

------------------------main.c----------------------------------------

Die im main.h file mit typdef definierte structur wird im main.c mit
drink1 drink_screwdriver = {12,4};
initialisiert. In weiteren xxx.c files greife ich wieder auf diese
structur drink1_screwdriver zu, darum habe ich mir gedacht, diese
in allen files wo die structur gebraucht wird das main.h file zu
includen. Jedoch habe ich dort immer
Fehlermeldungen, dass die structur nicht definiert ist. Weiss jemand wo
da der Fehler liegt??

von OldBug (Gast)


Lesenswert?

Hi Mike!

Zu Deinem Problem: es wird an der unvollständigen Typdeklaration
liegen!
Hier mal ein Beispiel, das "s" markiert den Namen der Struktur, das
"t" den Namen des Typen:


/* --- main.h --- */

#ifndef main_h
#define main_h

typedef struct
sDrink1
{
  unsigned char menge_orangensaft;
  unsigned char menge_vodka;
}
tDrink1;

#endif


/* --- main.c --- */

#include "main.h"

tDrink1 drink_screwdriver = { 12, 4 };

int
main(void)
{
  for(;;);
}


/* --- menu.c --- */

#include "main.h"

tDrink1 neuer_drink = { 4, 12 };

void
quickmix(void)
{
  /* whatever... */
}


"void main(void)" sollte man sich (wie schon in einigen anderen
Threads erwähnt) gar nicht erst angewöhnen, mehr dazu findest Du
warscheinlich im *-gcc Forum (ja, da finden sich auch Tipps, die man in
anderen Toolchains verwenden kann ;)

Ein Tipp zu den Structs noch: wenn Du einen oder zwei weitere(n) Member
einfügst, mit dem Du die Art des Alkoholischen Getränks und die des
Nicht-Alkoholischen angeben kannst, brauchst Du für alle Rezepte nur
einen Typen...

Gruß,
Patrick...

von Mike (Gast)


Lesenswert?

also Patrick, habe nun folgendes Programmiert:

-------------------------------main.h--------------------------------

#ifndef main_h
#define main_h

typedef struct tdrink1 {

  unsigned char menge_orangensaft;
  unsigned char menge_vodka;
}sdrink1;

typdef struct tdrink2 {
                      unsigned char menge_grapesaft;
          unsigned char menge_vodka;
          }sdrink2;


#endif

-------------------------main.h---------------------------------------

-------------------------main.c---------------------------------------

#include "main.h"

tdrink1 drink_screwdriver = {12,4};
tdrink2 drink_greyhound={15,5};

void main(void)
{
programm...
}

------------------------main.c---------------------------------------lei 
der
habe ich noch immer fehlermeldungen. ich greife wie schon gesagt in
anderen.c files auf diese structur zu
z.bsp. in dosieren.c diese file sieht folgendermassen aus:

-------------------------drinkskonfigurieren.c-------------
#include "main.h"


screw_fluessigkeits_menge=drink_screwdriver.menge_orangensaft;//aktuelle
Menge in screw_fluess.. speichern

--------------------------drinkskonfigurieren.c---------------------

dort kommt leider folgende Fehlermeldung:

Error[Pe020]: identifier "drink_screwdriver" is undefined


da ich das headerfile des main.c (main.h) includet habe, sollte er den
drink screwdriver doch kennen, oder muss ich im headerfile des main.c
den drink_screwdriver irgendwie mit extern..... implementieren??
ich will eben im main.c alle drinkrezepte initialisieren und diese in
den anderen funktionen dan entweder aufrufen oder ändern...

von OldBug (Gast)


Lesenswert?

:-) Du machst das falsch! Du hast Struct und Type vertauscht:

typedef struct
sDrink1
{
  unsigned char menge_orangensaft;
  unsigned char menge_vodka;
}
tDrink1;

Hinter "struct" muss der Name der Struktur stehen (in Deinem Fall
steht da jetzt tdrink1...) und hinter der schliessenden Klammer muss
der Name des Typen stehen (bei Dir jetzt sdrink1...).

Das "s" und "t" habe ich nur zur Verdeutlichung davor geschrieben.

von Ingo Henze (Gast)


Lesenswert?

Na dann mach Dir doch ein eigens Modul "Drinks", das nur die Daten der
Drinks enthält:
-------- drinks.h --------
#ifndef drinks_h
#define drinks_h

typedef struct {
  unsigned char menge_orangensaft;
  unsigned char menge_vodka;
}tdrink1;

typdef struct {
  unsigned char menge_grapesaft;
  unsigned char menge_vodka;
}tdrink2;

extern tdrink1 drink_screwdriver;
extern tdrink2 drink_greyhound;
#endif
-------- drinks.h --------

-------- drinks.c --------
#include "drinks.h"

tdrink1 drink_screwdriver = {12,4};
tdrink2 drink_greyhound = {15,5};
-------- drinks.c --------

und dann, in den Modulen, wo Du sie verwendest:

#include "drinks.h"

und hier dann was tolles mit den Drinks machen :-)

Gruß
Ingo

von schneidertobi (Gast)


Lesenswert?

Hi,
wenn du in dosieren.c die main.h includierst, dann weis der compiler,
wenn er auf diese datei stoest natuerlich nur, wie die struct aussieht.
Von dem screwdriver aus main.c weis er garnichts. Du musst also
dosieren.c diese variable bekannt machen. das geschiet so wie du das
schon selbst angedeutet hast mit dem extern schlüsselwort. Versuche
doch einfach mal in der main.h nach dem struct volgende zeile
einzufuegen:
extern sdrink1 drink_screwdriver;

Dabei faellt mir auf, dass du in der main.c sdrink1 statt trink1
verwenden solltest. Ich weis garnicht, ob das so in einem nicht c++
compiler ueberhaupt compiliert. ansonsten solltest du statt tdrink1
dann struct tdrink1 schreiben.

Gruß Tobias

von OldBug (Gast)


Lesenswert?

Hey, stop!
Da ist aber einiges Faul!

Lest mein letztes Posting, da steht der gröbste Fehler beschrieben, der
gemacht wird!
Zu Ingo's deklaration: er hat einfach den Namen der Struct
weggelassen, was an dieser Stelle natürlich möglich ist. Allerdings
sollte man, damit man eben nicht mehr diesen Fehler der unvollständigen
Deklaration macht, den Strukturen immer einen Namen geben. Das löst
einiges an Verwirrung auf.

Mit C++ hat das hier überhaupt nichts zu tun, das ist ganz simples
Standard-C!

Gruß,
Patrick...

von Mike (Gast)


Lesenswert?

ok, danke patrick, nun habe ich alle fehlermeldungen beseitigt. es kommt
nur noch eine warningmeldung.
weisst du was das bedeutet:

Warning[w6]: Type conflict for external/entry "mix_malibu_orange", in
module main against external/entry in module drinksmischen; prototyped
function vs K&R function
  /* In module main: */
  /* K&R Function, args 0, attr 0 */
  int mix_malibu_orange();
  /* In module drinksmischen: */
  /* Function, args 0, attr 0 */
  void mix_malibu_orange(void);

die Funktion mix_malibu_orange wird wie alle anderen Funktionen wo
getränke gemischt werden sollen aufgerufen. leider finde ich nicht
heraus, was da faul ist. unten noch die komplette funktion von
mix_malibu_orange:

void mix_malibu_orange (void)
{
unsigned char l_orangensaft=0;
unsigned char l_malibu=0;
unsigned int l_schrittmotorschritte=0;
unsigned char l_getraenkesumme=0;

l_orangensaft=drink_malibu_orange.menge_orangensaft;
l_malibu=drink_malibu_orange.menge_malibu;

l_getraenkesumme=l_orangensaft+l_malibu;     //Summe aus Teilgetränken
bilden
glas_fuellstand_kontrolle(l_getraenkesumme);    //Kontrolliert ob
Getränkemenge in Glas platz hat

if(l_orangensaft>fuellstand_orangensaftflasche)wechsle_orangensaft();
if(l_malibu>fuellstand_malibuflasche)wechsle_malibu();


lcd_comand(0x01);
lcd_dispstring(1,"Malibu Orange wird");
lcd_dispstring(2,"gemischt");
glas_nicht_entfernen();

l_schrittmotorschritte=schrittmotor_position(1);
schrittmotor(l_schrittmotorschritte);
flasche_zu_ventil();
dosiertabelle (l_orangensaft,0,0,0,0,0,0,0);
flasche_von_ventil();

l_schrittmotorschritte=schrittmotor_position(8);
schrittmotor(l_schrittmotorschritte);
flasche_zu_ventil();
dosiertabelle (0,0,0,0,0,0,l_malibu,0);
flasche_von_ventil();



glas_entnehmen();                //LCD schreibt Glas kann entnommen
werden



}

von OldBug (Gast)


Lesenswert?

Hm, brauchst nur die Fehlermeldung zu lesen ;-)

Einmal sagst Du dem Compiler, daß die Funktion "void" liefert (also
nichts) und einmal "int". Das Kollidiert natürlich.

/* In module main: */
/* K&R Function, args 0, attr 0 */
int mix_malibu_orange();

/* In module drinksmischen: */
/* Function, args 0, attr 0 */
void mix_malibu_orange(void);

So wie's scheint, musst Du den Prototypen in main.c korrigieren.

Gruß,
Patrick...

von Mike (Gast)


Lesenswert?

nein, habe den fehler gefunden. in der funktion wo der mix_malibu_orange
verwendet wird, habe ich es im headerfile vergessen zu implementieren.
Nun läuft es einwandfrei. Danke für eure Hilfe...

von OldBug (Gast)


Lesenswert?

Ok, diesen Fall hatte ich jetzt nicht berücksichtigt, weil ich das
vorausgesetzt habe ;-)
Dann hat der Compiler "angenommen", daß die Funktion "int" liefert,
was im K&R Standard so vorgeschrieben ist.

Gruß,
Patrick...

von Mike (Gast)


Lesenswert?

ja genau....
weisst du per zufall auch dies??
im main.c habe ich 2 interruptroutinen, eine für den TimerB interrupt
und die andere für den port1 interrupt. muss man diese routinen auch
ins headerfile schmeissen, wenn die funktion für den timmerinterrupt in
einem anderen xxx.c file abgelegt ist??
oder ist dies hardwaremässig verknüpft??

von OldBug (Gast)


Lesenswert?

Hm, die Frage verstehe ich nicht so ganz...
Möchtest Du die Interrupt-Service-Routinen in eine andere Datei
auslagern (bsp: interrupt.c/interrupt.h)?
So lange diese Routinen mitgelinkt werden, werden sie auch ins Binary
geschrieben. Es wird ja im Prinzip nur eine Funktion angelegt und
dessen Speicheradresse im angegebenen Interrupt-Vektor (was auch eine
Speicheradresse ist, aber halt mit eine ganz bestimmten Funktion, der
Prozessor Springt die Vektoren an, wenn das passende Ereignis auftritt)
hinterlegt.

von schneidertobi (Gast)


Lesenswert?

OldBug:
Ich komme auf C++, weil man dort eine Variable als struct definieren
kann, in dem man den namen der struct zur definition benuzt, ohne das
struct Schluesselwort.

Vollgendes geht in C++, aber ist in C nicht erlaubt:

struct meinestruct_s {
  int val;
};

meinstruct_s eineVariable={1};

In C muss das Schluesselwort struct oder ein typedef hinzu.

von Mike (Gast)


Lesenswert?

nein, ich habe folgendes Programm:

//Interrupt Routinen

//Port1 Interrupt

#pragma vector=PORT1_VECTOR
__interrupt void Port1_Interrupt (void)
{
if((P1IFG&0x01)==0x01)   //Wenn Flag von P1.0 gesetzt ist
    {
    LPM3_EXIT;
    lcd_initialisierung();
    }

P1IFG=0;   //Inerruptflag zurücksetzen
}

//Timerinterrupt

#pragma vector=TIMERB0_VECTOR
__interrupt void Timer_B (void)
{
  ist_oeffnungszeit++;
}

void main(void)
{
programm
}


in dem file dosierung.c ist die ganze timergeschichte drinnen mit dem
enable des timmerinterrupts.

muss ich nun die interruptfunktion (wie eine normale Funktion mit
extern void.....) auch in das headerfile packen, damit die Timerfuntion
in dosierung.c sieht, wo sich die interruptroutine befindet, oder
geschieht das automatisch???

von OldBug (Gast)


Lesenswert?

Das File "dosierung.c" muss vom Interrupt nichts wissen, die
"main.c" oder wo auch immer die Initialisierungsroutine für den Timer
aufgerufen wird, muss allerdings wissen, daß sich eben diese Funktion
extern befindet.

von OldBug (Gast)


Lesenswert?

Btw: Du verwendest doch IAR, richtig?

Dann kannst Du, um ein wenig mehr Übersicht in Deine Sourcen zu
bekommen, folgendes Makro verwenden:

interrupt[TIMERB0_VECTOR] void Timer_B (void)
interrupt[PORT1_VECTOR] void Port1_Interrupt (void)

Das spart dieses ganze #pragma und __interrupt gelumpe :-)

Für den msp430-gcc würde man dann:

INTERRUPT(TIMERB0_VECTOR) void Timer_B (void)
INTERRUPT(PORT1_VECTOR) void Port1_Interrupt (void)

schreiben...

von Mike (Gast)


Lesenswert?

ok, danke viel mal für deine Hilfe, hast mir sehr geholfen.
noch einen schönen tag....

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.