Forum: Compiler & IDEs Baud rate berechnen


von Pascal (Gast)


Lesenswert?

Hallo leute, ich versuche ja die baud rate mit dem formel zu rechnen 
aber das ergebnis in oscilloskop ist nicht richtig. Die Formel die ich 
benutze ist
UBRRH = (uint8_t)( UART_UBRR_CALC( UART_BAUD_RATE, F_CPU ) >> 8 );
UBRRL = (uint8_t)UART_UBRR_CALC( UART_BAUD_RATE, F_CPU );

aber wenn ich die werte zu den Registern zuweise habe ich im bildschirm 
die Baud Rate das ich erwarte.

ich arbeite mit dem Atmega16 mit einem fosc von 1Mhz und ich will gerne 
mit einer Baud Rate von 9600hz arbeiten

bitte helfen sie mir
Danke in voraus

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> aber wenn ich die werte zu den Registern zuweise habe ich
> im bildschirm die Baud Rate das ich erwarte.

Ich nehme an, daß hier ein linguistisches Problem vorliegt. Vermutlich 
fehlt das Wort "nicht".

Obendrein lässt sich aus 1 MHz nicht ohne Fehler eine Baudrate von 9600 
Baud erzeugen - das Thema "Baudratenquarz" wurde hier bereits ad nauseam 
durchgehechelt.

Dann wäre noch zu klären, ob der Takt auch wirklich stimmt - die 
berühmten "Fuses" kommen da ins Spiel.

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


Lesenswert?

Rufus t. Firefly wrote:

> Obendrein lässt sich aus 1 MHz nicht ohne Fehler eine Baudrate von 9600
> Baud erzeugen

Brauchbar genau, wenn man das U2X-Bit setzt (und dann natürlich nur
durch 8 statt durch 16 teilt).

> Dann wäre noch zu klären, ob der Takt auch wirklich stimmt - die
> berühmten "Fuses" kommen da ins Spiel.

Wobei 1 MHz die Werkseinstellung ist, zumindest falls der ATmega16
mit 5 V betrieben wird.

von Johannes M. (johnny-m)


Lesenswert?

Ist F_CPU denn überhaupt korrekt definiert? Wenn das schon nicht stimmt, 
dann kann die Baudrate noch nicht mal annähernd korrekt sein. Hinzu 
kommt noch die Frage, ob Du einen externen Quarz oder den internen 
RC-Oszillator nutzt. Im zweiten Fall ist funktionierende asynchrone 
Datenübertragung eher Glückssache.

von Pascal (Gast)


Lesenswert?

es ist ja klar das ich kein Deutscher Bin. aber was ich sagen will ist 
das, wenn ich die werte Dierkt zu den register eigebe (die Registern 
initialisieren) habe ich fast die Baud rate das ich erwarte (9,26khz). 
Aber wenn ich die werte von den Registern mit der Formel berechnen 
bekomme ich im bildschirm eine Baud rate von etwas 1,2khz. deswegen 
frage ich mich ob ich die Richtige Formel benutzt habe

von Johannes M. (johnny-m)


Lesenswert?

Das sieht dann eher danach aus, als ob F_CPU nicht korrekt ist 
(möglicherweise ist es auf 8 MHz eingestellt, das würde mit den 
angegebenen Werten einigermaßen übereinstimmen). Check mal Deine 
Einstellungen im Makefile bzw. in der IDE (je nachdem, womit Du 
arbeitest).

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Wie ist UART_UBRR_CALC(a,b), UART_BAUD_RATE, F_CPU definiert?

von Pascal (Gast)


Lesenswert?

so sieht mein Programm aus:


#include <avr/io.h> 
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#ifndef F_CPU
#define F_CPU 1000000              /* Oszillator-Frequenz in Hz */
#endif

// Hilfsmakro zur UBRR-Berechnung ("Formel" laut Datenblatt)

#define UART_UBRR_CALC(BAUD_,FREQ_) ((FREQ_)/((BAUD_)*16L)-1)

#define UART_BAUD_RATE 9600




 void USART_Transmit( unsigned char x)
{
while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich 
*/
    {

    }

    UDR = x;                    /* schreibt das Zeichen x auf die 
Schnittstelle */
}




int main(void)
{
    //UCSRA |= (1<<U2X);
  UCSRB |= (1<<TXEN);      // UART TX einschalten
        UCSRC |= (1<<URSEL)|(3<<UCSZ0);  // Asynchron 8N1


  UBRRH = (uint8_t)( UART_UBRR_CALC( UART_BAUD_RATE, F_CPU ) >> 8 );
        UBRRL = (uint8_t)UART_UBRR_CALC( UART_BAUD_RATE, F_CPU );

   //UBRRH = 0;   //High Byte ist 0
   //UBRRL = 6; //Low Byte ist 6 (dezimal)


 unsigned char x = 0xAA;
 USART_Transmit(x);
}

von Peter D. (peda)


Lesenswert?

Pascal wrote:

> Aber wenn ich die werte von den Registern mit der Formel berechnen
> bekomme ich im bildschirm eine Baud rate von etwas 1,2khz. deswegen
> frage ich mich ob ich die Richtige Formel benutzt habe

Welche Formel, ich sehe nirgends eine.

Vielleicht steckt ja eine hinter dem Macro "UART_UBRR_CALC".

Aber das ist nirgends definiert.

Und die anderen Macros auch nicht.


Peter

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Gut, jetzt wird es klarer.

Du berechnest Werte von Hand, die stimmen, aber die per Code berechneten 
sind inkorrekt.

Das liegt an dieser Zeile:

   #define F_CPU 1000000

Das muss eine long-Konstante sein, als int-Konstante lässt sich ein so 
großer Wert nicht ausdrücken (int ist auf dem AVR nur 16 Bit groß).

Durch Anhängen eines "L" wird aus der Konstanten eine long-Konstante:

   #define F_CPU 1000000L

und die Berechnung sollte jetzt stimmen.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Bei F_CPU 1000000 und BAUD 9600 wäre laut Formel ein Wert von 5,51 in 
das Baudratenregister einzutragen.

Die Formel trägt nur ganzzahlige Werte ein, d.h. 5 (abgerundet). Damit 
kommst du auf eine Baudrate von 10416,7, d.h. +8,5% gegenüber den 
gewollten 9600.

Von Hand trägst du 6 ein (aufgerundet). Damit kommst du auf eine 
Baudrate von 8928,6 , d.h. -7,0%. Ein etwas geringerer Fehler und 
möglicherweise ausschlaggebend für eine doch gerade noch mögliche 
Übertragung.

Beides zeigt, dass mit der F_CPU diese BAUD nur mit grossem Fehler 
realisierbar sind. Ich würde eine andere BAUD probieren bzw. einen 
andere F_CPU (Baudratenquarz)

Ich würde ausserdem mein Oszilloskop-Auslesung bzw. meine 
Frequenzmessung kontrollieren, ob vielleicht eine 10er Stelle vom 
Ergebnis verschoben ist.

von Pascal (Gast)


Lesenswert?

ich habe die zeile korrigiert aber das ergebnis hat nicht geändert

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


Lesenswert?

Stefan B. wrote:

> Beides zeigt, dass mit der F_CPU diese BAUD nur mit grossem Fehler
> realisierbar sind.

Nein, man muss U2X setzen (und dann durch 8 teilen), siehe oben.
Dann ist der Fehler bei 0,2 %.

von Pascal (Gast)


Lesenswert?

Die werte von 6 habe ich von das Formel die im Datenblatt steht undzwar 
ubrr=fosc/(16*Baud) - 1 bekommen

von Johannes M. (johnny-m)


Lesenswert?

> Die werte von 6 habe ich von das Formel die im Datenblatt steht undzwar
> ubrr=fosc/(16*Baud) - 1 bekommen
Die Formel im Datenblatt (und demzufolge auch die in Deinem Programm) 
berücksichtigt aber das U2X-Bit nicht! Deshalb gehts nicht.

Die 1,2 kHz sind allerdings eher ein Zeichen dafür, dass F_CPU irgendwo 
außerhalb Deines Programms auf 8 MHz gesetzt wird. Nimm mal das "#ifndef 
F_CPU" und das "#endif" raus.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Jörg Wunsch wrote:
> Stefan B. wrote:
>
>> Beides zeigt, dass mit der F_CPU diese BAUD nur mit grossem Fehler
>> realisierbar sind.
>
> Nein, man muss U2X setzen (und dann durch 8 teilen), siehe oben.
> Dann ist der Fehler bei 0,2 %.

Sorry Jörg, du hast natürlich recht und meine pauschale Aussage ist 
Quatsch.

Bei U2X = "1" errechnet sich der genaue Wert für UBRR auf 12,02. Wenn 
man stattdessen gerundet 12 verwendet, kommt man auf eine Baudrate von 
9615,4, d.h. harmlose +0,2% Fehler (wie Jörg bereits angegeben hat).

von Pascal (Gast)


Lesenswert?

  Jörg Wunsch worte:
> Nein, man muss U2X setzen (und dann durch 8 teilen), siehe oben.
> Dann ist der Fehler bei 0,2 %.


ich habe es gemacht aber wie ich erwartete es hat nur die Baud 
verdoppelt (von 1,2khz zu 2,4khz)

von Pascal (Gast)


Lesenswert?

wie bekommt ihr diese werte von 12,02 im UBRR kann jemand von euch mir 
erklärt wie genau diesen gleichungen functionniert:
    UBRRH = (uint8_t)( USART_UBRR_CALC( USART_BAUD_RATE, F_CPU ) >> 8 );
    UBRRL = (uint8_t)USART_UBRR_CALC( USART_BAUD_RATE, F_CPU );

von Karl H. (kbuchegg)


Lesenswert?

Pascal wrote:
> wie bekommt ihr diese werte von 12,02 im UBRR kann jemand von euch mir
> erklärt wie genau diesen gleichungen functionniert:
>     UBRRH = (uint8_t)( USART_UBRR_CALC( USART_BAUD_RATE, F_CPU ) >> 8 );
>     UBRRL = (uint8_t)USART_UBRR_CALC( USART_BAUD_RATE, F_CPU );

Mach das, was der Präprozessor auch macht.
Setzte die #define ein

F_CPU ersetzt du durch 1000000UL
                              **
                              mach da mal statt L ein UL draus

USART_BAUD_RATE ersetzt du durch 9600

dann steht da

  UBRRL = (uint8_t)USART_UBRR_CALC( 9600, 1000000UL );

und jetzt ersetzt du USART_UBRR_CALC durch im #define
angegebene Ersetzung, wobei du überall in der Ersetzung
9600 für BAUD_ einsetzt und 1000000UL für FREQ_

das war nochmal die Formel
#define UART_UBRR_CALC(BAUD_,FREQ_) ((FREQ_)/((BAUD_)*16L)-1)

eingesetzt ergibt sich
  UBRRL = (uint8_t)((1000000UL)/((9600)*16L)-1);

und das tippst du jetzt in den Taschenrechner: macht 5.5104

Wenn du mit U2X arbeitest, dann muss nicht durch 16, sondern
durch 8 dividiert werden:

#define UART_UBRR_CALC(BAUD_,FREQ_) ((FREQ_)/((BAUD_)*8L)-1)

und die Ersetzung ergibt daher:
  UBRRL = (uint8_t)((1000000UL)/((9600)*8L)-1);

im Taschenrechner ausgerechnet ergibt sich: 12.0208

(aufpassen dass du dich nicht mit den Klammern verhaust.
In Mathe-Notation ist das

          1000000
        ---------- - 1
          9600 * 8





von Pascal (Gast)


Lesenswert?

Danke Karl für die erklärung.  ich hoffe es muss jetzt functionnieren. 
wenn nicht melde mich noch wieder.

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.