Code auslagern mit #include und "globalem" #define

OP #993264
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:
1
// main.c
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include "Uart.h"
5
#define UART_Baud 9600
6
int main(void)
7
{
8
  UartInit();
9
}
10

11
// Uart.h
12
#ifndef _Uart_h_
13
#define _Uart_h_
14
void UartInit(void);
15
#endif
16

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

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???
#993288
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:
1
#include "Uart.h"
2
#define UART_Baud 9600
3
...
4
UartInit(CALC_UBR(UART_Baud));
OP #993329
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!
OP #993332
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 ^^
Gast #994296
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?

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 18 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.