Forum: Mikrocontroller und Digitale Elektronik USART Takt stimmt nicht mit Atmega8


von Sheldon C. (sheldon) Benutzerseite


Lesenswert?

Hallo,

ich weiß, die USART Takt-Fragen gibt es wie Sand am Meer, aber ich komme 
nicht weiter, obwohl ich eigentlich weiß wie man UBRR berechnet.

Folgendes Problem: Ich habe funktionierenden Code für den Atmega168. Ich 
habe diesen nun einfach nur für einen Atmega8 angepasst, da dort die 
Register etwas anders heißen. Sonst ändert sich nix.
Laut Datenblatt sollte an der Taktberechung ja nix anders sein, oder 
habe ich da was verpasst?

Randbedingungen: 8MHz Takt, Baudrate soll 9600 sein -> also ein UBRR von 
51.

Code:
/* UART Configuration */
#define BAUD 9600UL
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)

#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
#error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
#endif

/* Initialize UART */
void InitUART()
{
    /* Set DDR TX to output */
    DDRD |= _BV( PD1 );
    /* Set DDR RX to input */
    DDRD &= ~_BV( PD0 );

#ifdef _AVR_ATmega8_
    //UBRRH = ( unsigned char )( UBRR_VAL >> 8 );
    //UBRRL = ( unsigned char )UBRR_VAL;
    UBRRH = 0;
    UBRRL = 51; // diesmal aus Datenblatt vorsichtshalber
    UCSRA &= ~(1<<U2X); /* disable double speed, nur ein test */
    /* Enable UART receiver and transmitter */
    UCSRB = _BV( RXEN ) | _BV( TXEN );
    /* Frame Format: synchronous 8N1 */
    UCSRC = /*_BV( UMSEL ) |*/ _BV( UCSZ1 ) | _BV( UCSZ0 );
    /* enable RX interrupt */
    UCSRB |= _BV( RXCIE );
#else /* jetzt funktionierender Code für Atmega48/168/328 */
    UBRR0H = ( unsigned char )( UBRR_VAL >> 8 );
    UBRR0L = ( unsigned char )UBRR_VAL;
    /* Enable UART receiver and transmitter */
    UCSR0B = _BV( RXEN0 ) | _BV( TXEN0 );
    /* Frame Format: synchronous 8N1 */
    UCSR0C = /*_BV( UMSEL00 ) |*/ _BV( UCSZ01 ) | _BV( UCSZ00 );
    /* enable RX interrupt */
    UCSR0B |= _BV( RXCIE0 );
#endif
}

Die Fuse-Bits habe ich auf 8MHz externen Quarz gestellt. Der Quarz 
schwingt und der Takt stimmt, kann im Sekunden-Takt mittels 
__delay_ms(1000) eine LED blinken lassen.
Habs auch schon mit internem 8MHz RC Osz. versucht, selbes Ergebnis.

Mit dem Oszi sehe ich, dass der UART für 8 Bit (Testzeichen 0x55 'U') 
25ms braucht -> 320 Baud. Sollte aber 0.833ms sein für 9600 Baud.
Das ist zeimlich genau ein Faktor 30 daneben, was ich mir nicht erklären 
kann.

Gibt's da noch irgendeinen Teiler von dem ich nix weiß?
Ich hoffe jemand kann mir da weiterhelfen.

von g457 (Gast)


Lesenswert?

dasda

> UCSRC = /*_BV( UMSEL ) |*/ _BV( UCSZ1 ) | _BV( UCSZ0 );
          ^^              ^^
..versaut dir UBRRH.

HTH

von g457 (Gast)


Lesenswert?

arrgs. Streiche UMSEL setze URSEL.

Immer diese Kürzel.

von Stefan E. (sternst)


Lesenswert?

1
    UCSRC = /*_BV( UMSEL ) |*/ _BV( UCSZ1 ) | _BV( UCSZ0 );
Du schreibst also 6 nach UBRRH. Kein Wunder, dass
> Mit dem Oszi sehe ich, dass der UART für 8 Bit (Testzeichen 0x55 'U')
> 25ms braucht -> 320 Baud.

Sheldon Cooper schrieb:
> Folgendes Problem: Ich habe funktionierenden Code für den Atmega168. Ich
> habe diesen nun einfach nur für einen Atmega8 angepasst, da dort die
> Register etwas anders heißen. Sonst ändert sich nix.

Tja, so einfach ist es halt doch nicht.

von Sheldon C. (sheldon) Benutzerseite


Lesenswert?

g457 schrieb:
> arrgs. Streiche UMSEL setze URSEL.
>
> Immer diese Kürzel.

Gut gesehen. Das wars. Danke vielmals.

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.