Forum: Compiler & IDEs Berechnungsfehler Baudrate mit Makro


von ChristianS (Gast)


Lesenswert?

Hallo zusammen,

ich bastel mit einem ATMega32 und Peter Fleury's uart lib herum. Dabei 
kommt es zu einem folgeschweren Rechenfehler bei der Berechnung der 
Baudrate. Ein UART_BAUD_RATE von 9600 wird zu dem Wert, der die 
vierfache Baudrate von 38400 (UBRR = 6 @ 4MHz) einstellt, 2400 wird zu 
9600 Baud (UBRR = 25 @ 4MHz) etc.
Eine doppelte Vergabe von Namen kann ich ausschliessen, lediglich XTAL 
und xtalCpu werden verwendet.

Nun meine Fragen:
1. Wie kann ich dem Compiler bei der Arbeit zusehen, um festzustellen, 
wie der Rechenfehler zustande kommt?
2. Hat jemand einen heissen Tip, wo ich noch suchen kann?


Den Codeausschnitt habe ich angehängt (allesamt aus der Fleury-lib):
1
#define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1)
2
3
4
#ifndef F_CPU
5
#define F_CPU 4000000UL
6
#endif
7
8
/* 9600 baud */
9
#define UART_BAUD_RATE      9600
10
11
void UsartInit(){
12
    uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );

Bin gespannt auf eure Ratschläge!

Gruß,
Christian

von Johannes M. (johnny-m)


Lesenswert?

Wenn F_CPU im Makefile anders definiert ist, dann kannst Du da oben noch 
so 4 MHz angeben, es bringt alles nix... Ich tippe mal, dass im Makefile 
16 MHz angegeben ist.

von ChristianS (Gast)


Lesenswert?

Hallo Johannes,

nein, das ist leider nicht der Fall, im Makefile wird F_CPU nicht 
vordefiniert.

Trozdem danke für den schnellen Tip ;-)

Gruß,
Christian

von Johannes M. (johnny-m)


Lesenswert?

> 1. Wie kann ich dem Compiler bei der Arbeit zusehen, um festzustellen,
> wie der Rechenfehler zustande kommt?
Fällt mir grad noch auf: Der Compiler hat damit im Prinzip überhaupt 
nichts zu tun, da der Präprozessor die Berechnungen ausführt. Und wenn 
F_CPU und UART_BAUD_RATE korrekt angegeben sind, besteht überhaupt kein 
Grund, warum das Ergebnis falsch sein sollte. Tu Dir selbst nen Gefallen 
und nimm das #ifndef und das #endif weg. Wenn dann das richtige 
rauskommt, dann ist es woanders definiert.

von yalu (Gast)


Lesenswert?

> Wie kann ich dem Compiler bei der Arbeit zusehen, um festzustellen,
> wie der Rechenfehler zustande kommt?

Die Option -E des GCC zeigt den Präprozessor-Output an.

von Rolf Magnus (Gast)


Lesenswert?

> Fällt mir grad noch auf: Der Compiler hat damit im Prinzip überhaupt
> nichts zu tun, da der Präprozessor die Berechnungen ausführt.

Nein. Der Präprozessor führt hier nur eine Makrosubstitution durch, 
sonst gar nichts. Das heißt, er macht aus:
1
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );

ein:
1
((4000000UL)/((9600)*16l)-1)

Und das geht dann so an den eigentlichen Compiler weiter.

von Rolf Magnus (Gast)


Lesenswert?

Bzw. macht er daraus ein:
1
uart_init( ((4000000UL)/((9600)*16l)-1) );

  

von pumpkin (Gast)


Lesenswert?

Ich denke auch, dass F_CPU anderswo definiert worden ist. Hast du z.B. 
die delay.h eingebunden? Nimm #ifndef mal raus, beim compilieren wird 
wahrscheinlich die Warnung 'F_CPU redefined' o.ä. ausgeworfen. Ist das 
nicht der Fall hilft vorerst nur noch die Glaskugel.

pumpkin

von ChristianS (Gast)


Lesenswert?

Hallo zusammen,

vielen Dank für die hilfreichen Tips. Verzwackte Sache, das. Es war die 
Definition von F_CPU in der delay.h - Pumpkin hat den Nagel auf den Kopf 
getroffen, aber alle haben in die richtige Richtung gesucht.
Die Redefinition von F_CPU ist leider nie aufgefallen, da in der delay.h 
auch ein #ifndef verwendet wird (hatte schon probiert eine redefinition 
so zu finden - das projekt dann aber nicht in den chip gebrutzelt).
Die falsche Zeitkonstante ist nicht aufgefallen, da mein Atmel in der 
Testphase noch über den internen Oszi mit 1MHz lief (da habe ich den 
delay überprüft und für gut befunden) - in der delay.h wird die Frequenz 
mit 1MHz dewfiniert in der besagten F_CPU.
Geknallt hat's dann erst am Ende, als alles zusammen wursteln sollte

Lösung? Demnächst kommt die Prozessorgeschwindigkeit ins Makefile.

Vielen Dank für eure Hilfe!

Gruß,
Christian

von yalu (Gast)


Lesenswert?

In meiner AVR-libc (1.4.4) spuckt delay.h eine
1
  warning: #warning "F_CPU not defined for <util/delay.h>"
aus, wenn F_CPU nicht schon vor dem Includieren definiert ist.

Ich frage mich allerdings,

- warum nur eine Warnung und kein Fehler ausgegeben wird, die
  insbesondere bei redseligen Makefiles schnell mal übersehen wird,
  und

- warum delay.h überhaupt einen Defaultwert setzt, der bei den vielen
  Prozessortaktoptionen, die die AVRs bieten, fast immer falsch sein
  wird.

In meinen Augen würde ein lauter und deutlicher Error den
Programmierer schneller zur Ursache des Problems führen.

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.