www.mikrocontroller.net

Forum: Compiler & IDEs Berechnungsfehler Baudrate mit Makro


Autor: ChristianS (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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):
#define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1)


#ifndef F_CPU
#define F_CPU 4000000UL
#endif

/* 9600 baud */
#define UART_BAUD_RATE      9600

void UsartInit(){
    uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );

Bin gespannt auf eure Ratschläge!

Gruß,
Christian

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: ChristianS (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );

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

Und das geht dann so an den eigentlichen Compiler weiter.

Autor: Rolf Magnus (Gast)
Datum:

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

  

Autor: pumpkin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: ChristianS (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In meiner AVR-libc (1.4.4) spuckt delay.h eine
  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.

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.