Forum: Mikrocontroller und Digitale Elektronik Kleines Problem mit Includes


von Paul (Gast)


Angehängte Dateien:

Lesenswert?

Moin!

Bei meinem aktuellen AVR-Projekt (ich benutze AVR-GCC) habe ich ein 
kleines Problem mit Include-Files.
Ich habe eine Datei "strings.h", die ein paar in anderen Includes 
verwendete Konstanten enthält.
Die möchte ich gerne in die "main.h" packen. Doch dann bekomme ich X 
Fehlermeldungen, weil die Konstanten dann anscheinend mehrfach definiert 
sind.
Jetzt muss ich das #include "strings.h" direkt in die main.c schreiben, 
dann gehts.

Nur zweifle ich jetzt irgendwie an der Wirksamkeit dieser 
"Header-Guards"
(#ifndef __STRINGS.H__
 #define
 ...
 #endif)..

Kann hier jemand vllt. kurz einen Blick in meinen Code werfen und mir 
sagen, wie ich das mit den Includes am besten löse?

Die entsprechenden Dateien (sind nur ein paar) habe ich angehängt.

Ich bin leider noch ein C-Anfänger und bekomme es wirklich nicht besser 
hin..
Wenn mir jemand helfen und sagen könnte, was Sache ist, wäre ich ihm 
sehr verbunden. ;-)

Gruß und guten Rutsch,
Paul

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Die header guards sind OK, aber bitte benutze keine Namen mit
führenden Unterstrichen, diese sind für die Bibliothek und den
Compiler reserviert.  Schreib also:
1
#ifndef STRINGS_H
2
#define STRINGS_H
3
4
// ...
5
#endif /* STRINGS_H */

strings.h ist übrigens kein sehr schöner Name, da die Verwechslungs-
gefahr mit dem Standard-C-Header string.h ziemlich groß ist.

von Paul (Gast)


Lesenswert?

Hi Jörg,
erstmal danke für deine Antwort!

Ich hab gelesen, dass die Unterstriche besser wären, weil der Compiler 
DEFINEs mit einem führenden E z.B. für sich beansprucht (irgendwie so).
Oder macht AVR-GCC da eine Ausnahme?

Danke für den Tipp, werde die strings.h auch nochmal umbenennen. ;)

Aber wie bekomme ich es nun hin, dass ich das #include "strings.h" in 
die main.h schreiben kann?
Ich bin, wie gesagt, sehr unsicher mit diesen ganzen includes. Vllt kann 
man das besser lösen?

von Falk B. (falk)


Lesenswert?

@ Paul (Gast)

>Aber wie bekomme ich es nun hin, dass ich das #include "strings.h" in
>die main.h schreiben kann?

???
Schreibs doch einfach rein.
1
#inlcude "my_strings.h"

>Ich bin, wie gesagt, sehr unsicher mit diesen ganzen includes. Vllt kann
>man das besser lösen?

Ja. Deine Fehler liegen

a) and er falschen Syntax: in WINAVR wird das so gemacht.

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmspeicher_.28Flash.29

b) am falschen Konztept. Was du in deiner string.h hast sind globale 
Variablen. Die werden anders gehandhabt. Stichwort EXTERN.

in my_string.h kommt dann

1
// Deklaration der globalen Variablen
2
extern char hello[] PROGMEM;

In my_string.c kommt dann

1
// Definition der globalen Variablen
2
char hello[] PROGMEM = "Hallo Welt!";

my_string.h kannst du dann überall problemlos einbinden. Solche globalen 
Variabeln bzw. Konstanten legt man üblicherweise in globals.c/h ab.

MFG
Falk

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Paul wrote:

> Ich hab gelesen, dass die Unterstriche besser wären, weil der Compiler
> DEFINEs mit einem führenden E z.B. für sich beansprucht (irgendwie so).

Makros, die mit einem E beginnen, sind in der Tat potenzielle
Erweiterungen für <errno.h>.  Allerdings haben wir davon im Moment
beim AVR-GCC fast keine in Benutzung.

Nur: du hast den Teufel mit dem Beelzebub ausgetrieben.  Während die
mit dem E für weitere Fehlernamen reserviert sind (wobei mir keiner
bekannt ist, der davon jemals auf _H enden würde), sind die Makronamen,
die mit einem Unterstrich und einem Großbuchstaben beginnen sowie
alle Bezeichner, die mit zwei Unterstrichen beginnen, immer für
die interne Benutzung von Compiler und Bibliothek reserviert.

von Paul W. (mosfetkiller)


Lesenswert?

Mensch..hab ganz vergessen, dass ich hier ja auch angemeldet bin. ;-)
Danke euch! Es klappt jetzt alles so wie ich es haben will.

Die letzte verbliebene Frage ist nur noch, in was ich diese Zeile 
umändern muss, wenn ich prog_char gänzlich vermeiden möchte:
1
void print(const prog_char *str)

Ganze Funktion:
1
void print(const prog_char *str)
2
{
3
  while (1) {
4
    char lsb = (char) pgm_read_byte(str);
5
    if (lsb == '\0')
6
    return;
7
    remote_control(0, lsb);
8
    str++;
9
  }
10
}

Gruß,
Paul

von Falk B. (falk)


Lesenswert?

@ Paul Wilhelm (mosfetkiller)

>Die letzte verbliebene Frage ist nur noch, in was ich diese Zeile
>umändern muss, wenn ich prog_char gänzlich vermeiden möchte:

>void print(const prog_char *str)

Du must einen Pointer auf Daten im Flash verweden. Hab aber im Moment 
die Doku nicht parat. Steht alles recht gut erklärt in der Doku der libc 
im WINAVR. Irgendwas mit PROGMEM_P oder so.

MFG
Falk

von Paul W. (mosfetkiller)


Lesenswert?

Na super ;-)

Auszug aus dem PROGMEM-Kapitel der libc-Doku:
1
#define PGM_P const prog_char ∗

Hat sich also erledigt. :P

Aber trotzdem danke. Damit wären alle meine Fragen bis auf weiteres 
beantwortet!

Gruß,
Paul

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.