www.mikrocontroller.net

Forum: Compiler & IDEs Code auslagern mit #include und "globalem" #define


Autor: Andreas Pfau (andreaspfau)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Community,

mein erster Beitrag hier, nach langem googlen und suchen in diesem 
Forum. Ich bin am verzweifeln. Und ich weiß, dass bereits tausend 
ähnliche Fragen gestellt und beantworte wurdent, trotzdem hilft es mir 
nichts... :-(

Ich habe in AVRStudio+WinAVR ein wenig Code ausgelagert, welcher auf 
Konstanten zugreift, welche mit #define definiert wurden. Kurzer, 
zusammengefasster Abriss der Dateien:
// main.c
#include <avr/io.h>
#include <avr/interrupt.h>
#include "Uart.h"
#define UART_Baud 9600
int main(void)
{
  UartInit();
}

// Uart.h
#ifndef _Uart_h_
#define _Uart_h_
void UartInit(void);
#endif

// Uart.c
#include <avr/io.h>
#include "Uart.h" 
void UartInit(void)
{
  UBRRH = (unsigned char)(((long)F_CPU / (16l * (long)UART_Baud) - 1l)>>8);
  UBRRL = (unsigned char)(((long)F_CPU / (16l * (long)UART_Baud) - 1l));
}

Beim compilieren des Projekts kommt nunt "error: 'UART_Baud' 
undeclared". Uart.C wurde natürlich schon in die Liste "Source Files" 
mitaufgenommen, klar. F_CPU sowie der AVR-Typ werden vom Projekt 
gesetzt.

Ich hoffe ihr versteht mein Problem: ich will eine allgemein gültige 
Uart.c schreiben, die ich aber in der übergeordneten Datei main.c über 
ein #define konfigurieren kann.

Alternativ könnte ich auch einen Parameter an UartInit übergeben, laufe 
aber in Gefahr, dass das die Artihmetik dahinter (also das "((long)F_CPU 
/ (16l * (long)UART_Baud) - 1l)>>8") in Assembler übersetzt wirdt, 
anstatt es wie beim #define vom Compiler ausgewertet wird. Außerdem 
erlaubt das #define die Ausgabe von Warnungen mittels #warning bei 
ungeeigneten Werten von UART_Baud (noch nicht implementiert).

Oder, anders formuliert: wie würdet ihr vorgehen???

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Pfau wrote:

> Ich hoffe ihr versteht mein Problem: ich will eine allgemein gültige
> Uart.c schreiben, die ich aber in der übergeordneten Datei main.c über
> ein #define konfigurieren kann.

Du musst dir bei solchen Sachen immer eines klar machen: der Compiler 
übersetzt jede C-Datei für sich alleine, unabhängig von den anderen 
C-Dateien. Wenn in main.c ein #define steht, dann ist das auch nur dort 
verfügbar.

> Alternativ könnte ich auch einen Parameter an UartInit übergeben, laufe
> aber in Gefahr, dass das die Artihmetik dahinter (also das "((long)F_CPU
> / (16l * (long)UART_Baud) - 1l)>>8") in Assembler übersetzt wirdt,
> anstatt es wie beim #define vom Compiler ausgewertet wird. Außerdem
> erlaubt das #define die Ausgabe von Warnungen mittels #warning bei
> ungeeigneten Werten von UART_Baud (noch nicht implementiert).
>
> Oder, anders formuliert: wie würdet ihr vorgehen???

Du übergibst den fertig berechneten UBR-Wert per Parameter und packst 
ein Makro zum berechnen in Uart.h. In main.c steht dann sowas:
#include "Uart.h"
#define UART_Baud 9600
...
UartInit(CALC_UBR(UART_Baud));

Autor: main.h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder du erstellst eine main.h und schreibst das
#define UART_Baud 9600
dort hinein. In der uart.c schreibst du dann
#include "main.h"

Autor: Andreas Pfau (andreaspfau)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

>Du musst dir bei solchen Sachen immer eines klar machen: der Compiler
>übersetzt jede C-Datei für sich alleine, unabhängig von den anderen
>C-Dateien. Wenn in main.c ein #define steht, dann ist das auch nur dort
>verfügbar.

Ja, das war mir bewusst, aber ich hatte gehofft dass die #define-Werte 
irgendwie global mitgeschleift werden könnten...

>Du übergibst den fertig berechneten UBR-Wert per Parameter und packst
>ein Makro zum berechnen in Uart.h.

Das ist auch ne gute Idee! Ist zwar vom Aussehen her etwas holperig, 
aber so kann ich auf der Präprozessor-Ebene bleiben. Danke!

Autor: Andreas Pfau (andreaspfau)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi @main.h

das würde auch funktionieren, aber dann wäre meine Unit ja nicht mehr 
universell einsetzbar, weil sie das Vorhandensein eine bestimmten 
Dateinamnes ("main.h") voraussetzt... OK, meine ursprüngliche Idee setzt 
das Vorhandensein eines bestimmten #include voraus ^^

Autor: mork (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du könntest das #define UART_Baud 9600 auch in die uart.h schreiben, die 
ja sowieso vorhanden sein muss ...

Autor: Andreas Pfau (andreaspfau)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi @mork,

auf die Idee bin ich auch schon gekommen. Allerdings müsste man ja dann 
jedesmal die .h anpassen, das finde ich nicht allzu praktikabel...

Autor: Wolfgang Mües (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du schreibst in uart.h:

#define BAUD_9600 ((long)F_CPU / (16l * 9600) - 1l)
#define BAUD_19200 ((long)F_CPU / (16l * 19200) - 1l)

und so weiter....

in uart.c schreibst Du dann:

void UartInit(unsigned int baudrate)
{
  UBRRH = (unsigned char)(baudrate >>8);
  UBRRL = (unsigned char)(baudrate);
}

dann kannst Du in main schreiben:

UartInit(BAUD_9600);

Alles klar?

Autor: Andreas Pfau (andreaspfau)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alles klar! :-) Darauf bin ich auch noch nicht gekommen. Ist ne menge 
Fleißarbeit, aber ne sehr saubere Lösung wie ich finde!

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Wolfgang Mües (Gast)

>#define BAUD_9600 ((long)F_CPU / (16l * 9600) - 1l)
>#define BAUD_19200 ((long)F_CPU / (16l * 19200) - 1l)

Wozu? Eine allgemeine Formel reicht. Siehe

http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

MFG
Falk

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.