Forum: Mikrocontroller und Digitale Elektronik Uart Baudrate


von Marc (Gast)


Lesenswert?

Hallo,
ich habe einen ATtiny, wo ich einen Qaurz mit 8Mhz drann habe. 
Desweiteren habe ich einen Prescaler von 64.
Da dieser Quarz nicht optimal für UART ist, ist mir bewusst, allerdings 
brauche ich auch 8Mhz, damit ich genau Timer-INterrupts erstellen kann.

Meine Frage bezieht sich auf den Prescaler. Wird der bei der Berechnung 
von UBBR mit einbezogen? Die Gleichung ist ja
UBRR = (fOSC / (16*BAUD) ) - 1

ist fosc jetzt 8000000 oder 125000?

Habe für den Uart eine Baud-Rate von 9600 genommen (fosc = 8Mhz), 
allerdings wird nichts richtiges empfangen.
Marc

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Wenn Du eine Prescaler von 64 für die Taktrate einstellst, dann läuft 
innerhalb des Kerns alles mit 125kHz, so auch der Eingangstakt der 
Peripherie.

von c-hater (Gast)


Lesenswert?

Marc schrieb:

> ich habe einen ATtiny, wo ich einen Qaurz mit 8Mhz drann habe.
> Desweiteren habe ich einen Prescaler von 64.
> Da dieser Quarz nicht optimal für UART ist, ist mir bewusst, allerdings
> brauche ich auch 8Mhz, damit ich genau Timer-INterrupts erstellen kann.

Was für ein Prescaler ist das? Systemtakt oder Timer? Wenn's der 
Timer-Prescaler ist, wird der Takt der UART davon nicht beeinflußt. 
Wenn's hingegen der Systemtakt ist, dann natürlich schon. Allerdings 
ergäbe das keinen Sinn, da dann auch für den Timer nur 125kHz verfügbar 
wären, womit deine Begründung für den 8MHz Quarz obsolet wäre...

von Jakob (Gast)


Lesenswert?

für den Systemtakt gibt es beim ATTiny nur die CKDIV8-Fuse.
8 MHz intern/extern/Quarz ergeben 1 MHz, oder 8 MHz
Systemtakt, je nach Fuse-Setting.
Die CKDIV8-Fuse muss in deinem Fall AUSGESCHALTET werden.

Bei den klassischen ATTinys gibt es nur den 2313 mit UART.
- Ist wohl zuviel verlangt, dass du den µC-Typ mal nennst...

Der Prescaler 64 ist also ein Rätsel für alle, die helfen
sollen.

Erste Frage:
(CKDIV8) Hast du 1 MHz, oder 8 MHz Systemtakt?

Ansonsten hängt UBRR H/L direkt am Systemtakt,

bei 1 MHz:
UBRR = (fOSC / (16*BAUD) ) - 1 =
UBRR = 1 MHz / (16 * 9600) - 1 =
UBRR = 1.000.000 / 153.600 = 6,5
UBRR = geht nicht, 6 zu klein, 7 zu groß!

bei 8 MHz:
UBRR = (fOSC / (16*BAUD) ) - 1 =
UBRR = 8 MHz / (16 * 9600) - 1 =
UBRR = 8.000.000 / 153.600 - 1 = 52,0833 - 1
UBRR = 51 -> 9615 Bd - kein Problem! OK!

von Jakob (Gast)


Lesenswert?

Und wenn du zu blöd bist die CKDIV8-Fuse abzuschalten,
kannst du bei 1 MHz noch den Double-Speed-Mode wählen,
dazu ist das U2X-Bit im UCSRA-Register zu setzen.
(Schaffst du das????)

Dann gilt:

bei 1 MHz:
UBRR = (fOSC / (8*BAUD) ) - 1 =
UBRR = 1 MHz / (8 * 9600) - 1 =
UBRR = 1.000.000 / 76.800 - 1 = 13,0208333 - 1
UBRR = 12 -> 9615 Bd - kein Problem! OK!

von DraconiX (Gast)


Lesenswert?

Jakob schrieb:
> Die CKDIV8-Fuse muss in deinem Fall AUSGESCHALTET werden.

Naja, theoretisch muss sie "eingeschaltet" werden, im weitesten Sinne 
:-D Denn viele, war damals (tm) bei mir genauso:

0 = Bit nicht gesetzt = programmed / eingeschaltet
1 = Bit gesetzt = unprogrammed / ausgeschaltet

Das sorgt schon ab und wann für Verunreinigungen. ;-)

von Karl B. (gustav)


Lesenswert?

Marc schrieb:
> Habe für den Uart eine Baud-Rate von 9600 genommen (fosc = 8Mhz),
> allerdings wird nichts richtiges empfangen.
> Marc

Hi,
da gibt es unter Umständen andere Probs noch, wenn nichts 
empfangen/gesendet wird:
"... Die Originaldokumentation für den Attiny 2313 (2543L-AVR-08/10) 
macht auf Seiten 129 bis 133 UART Controlregisterdefinitionen, die nicht 
stimmen, so dass die Assemblierung im Studio4 fehlschlägt. "UCSRC not 
defined on this target "

Im Attiny 4313 gibt es in der "def.inc" den klärenden Hinweis auf 
Kompatibilität.

ser in out init:
ldi temp, bdrt    ;Baudrate setzen
out UBRR, temp    ; .equ UBRR=UBRRL;for compatibility
ldi temp, 0x18    ;(1<<RXEN)+(1<<TXEN)
out UCR, temp    ; .equ UCR=UCSRB;for compatibility
ret
;
tx:        ;RS232-Ausgaberoutine
sbis UCSRA, UDRE  ; .equ USR=UCSRA;for compatibility
rjmp senden
out UDR, temp
ret


ciao
gustav

P.S.: verwende bei 4 MHZ als Baudratenteilerkonstante 25 bei 9k6

von Marc (Gast)


Lesenswert?

Jakob schrieb:
> - Ist wohl zuviel verlangt, dass du den µC-Typ mal nennst...

Nein, zu viel ist es nicht verlangt, aber es ging ja nicht primär um 
Uart, sondern darum, mit welchem Takt der Controller läuft.

Jakob schrieb:
> Und wenn du zu blöd bist

danke
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#define FOSC 8000000
5
#define BAUD_UART 9600
6
#define UBBR_UART (FOSC/ (16*BAUD_UART))-1
7
8
void setup(void);
9
10
volatile unsigned int senduart = 0;
11
12
int main(void)
13
{
14
    setup();
15
     
16
    sei(); /* enable Interrupt */
17
    while (1) 
18
    {
19
        if(1 == senduart)
20
        {
21
            senduart = 0;
22
            USART_Transmit("A");
23
        }
24
    }
25
}
26
27
void setup(void)
28
{
29
    /* Pin Setup */
30
    DDRB  |= (1 << PB0); /* PB0 -> Output */
31
    PORTB &= ~(1 << PB0); /* PB0 -> Low */
32
33
    /* Timer Setup */
34
    TCCR0A |= (1 << WGM01); /*Modus: CTC; Top: ORC0A */
35
    TCCR0B |= (1 << CS00) | (1 << CS01); /* Prescaler 64 */
36
    OCR0A = 125-1; /* ((8000000/64)/1000) = 125 */
37
38
    /* Usart Setup */
39
    UBRRH = (UBBR_UART >> 8);  // Set Baud-Rate */
40
    UBRRL = UBBR_UART; /* Set Baud Rate */
41
    UCSRB = (1 << RXEN) | (1 << TXEN); /* Enable receiver and transmitter */
42
    UCSRC = (1 << USBS) | (1 << UCSZ0) | (1 << UCSZ1); /* Set frame format: 8data, 2stop bit */
43
44
    /* Interrupt Setup */
45
    TIMSK |= (1<<OCIE0A); /* enable Compare Interrupt */
46
}
47
48
void USART_Transmit( unsigned char data )
49
{
50
    while ( !( UCSRA & (1<<UDRE)) );/* Wait for empty transmit buffer */
51
    UDR = data; /* Put data into buffer, sends the data */
52
}
53
54
ISR (TIMER0_COMPA_vect)
55
{
56
    static uint16_t milliseconds = 0;
57
    milliseconds++;
58
    if(milliseconds >= 1000)
59
    {
60
        milliseconds = 0;
61
        senduart = 1;
62
        PORTB ^= ( 1 << PB0 ); /* Toggle PB0 */
63
    }
64
}

In der Timer ISR lasse ich eine LED Toggeln. Dies läuft auch jede 
Sekunde. Allerdings funktioniert das mit dem UART noch nicht.
Benutze dazu das Programm HTerm, Es kommt zwar was an, aber bei jedem 
Senden 0x00 und 0xC0.
Die Fuses sind: Extended: oxFF; High: 0x9F; Low: 0xEC

DraconiX schrieb:
> 0 = Bit nicht gesetzt = programmed / eingeschaltet
> 1 = Bit gesetzt = unprogrammed / ausgeschaltet

CKDIV8 habe ich nicht gesetzt (nach deiner Aussage dann ja 
eingeschaltet), jedoch stimmt dann ja meine Berechnung für den Timer 
nicht, bzw. dann ist da noch ein anderer Fehler drinn, da die ISR wie 
berechnet jede millisekunde ausgeführt wird

von Georg G. (df2au)


Lesenswert?

mach mal dein senduart volatile, das ist vermutlich nicht die 
Fehlerursache, ist aber notwendig, damit es nicht irgendwann doch hängt.

Und dann häng doch einfach ein Scope an den TxD Pin und sieh dir die 
Breite der Bits an. Damit kannst du sofort die Baudrate errechnen und 
bekommst einen Hinweis, wo es nicht passt.

von Georg G. (df2au)


Lesenswert?

Marc schrieb:
> #define UBBR_UART (FOSC/ (16*BAUD_UART))-1

Da der Compiler per Definition mit 16 Bit Integer rechnet, kommst hier 
nicht das gewünschte Ergebnis.

Ein Blick in das .lss File zeigt dir, was passiert ist.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

> kommst hier nicht das gewünschte Ergebnis.

Benutze die Datei setbaud.h zum Berechnen der Registerwerte.

http://www.nongnu.org/avr-libc/user-manual/group__util__setbaud.html

von Jakob (Gast)


Lesenswert?

Die Frage nach dem µC könnte z.B. helfen, um für Ratschläge
das Handbuch-Kapitel zu nennen.
- Naja, manche müssen aus dem µC-Typ ein grooooßes Geheimnis
  machen. Oder lesen nicht gern?

CKDIV8 ist bei Auslieferung GESETZT, d.h. AKTIV.
Ob NULL, oder EINS das aktivierende Logik-Potential ist, KÖNNTE
man auch im Handbuch nachlesen.
Ändert man nichts am Auslieferungszustand, arbeitet der µC halt
mit 1/8 der wirksamen Frequenz...

Symbolische Rechnung ist schön, kann aber auch zu unbrauchbaren
Ergebnissen führen:

bei 1 MHz:
UBRR = (fOSC / (16*BAUD) ) - 1 =
UBRR = 1 MHz / (16 * 9600) - 1 =
UBRR = 1.000.000 / 153.600 - 1 = 5 (Ganzzahl)

Test:
BAUD = (fOSC / (UBRR + 1)) / 16 = 10.417 = 8,5% daneben!
Funktioniert nicht.

von Pandur S. (jetztnicht)


Lesenswert?

Das Standardvorgehen ist das UART mit einer Konstante, zB 0x55, senden 
zu lassen und mit einem Oszilloskop die Baudrate zu messen. Dann muss 
man viel weniger raten.

von spess53 (Gast)


Lesenswert?

Hi

>Das Standardvorgehen ist das UART mit einer Konstante, zB 0x55, senden
>zu lassen und mit einem Oszilloskop die Baudrate zu messen.

Wieso ist das 'Standard'? Ich brauche dafür lediglich IO-Frequenz und 
Baudrate.

MfG Spess

von Pandur S. (jetztnicht)


Lesenswert?

> Wieso ist das 'Standard'?

Weil man nahezu gar nichts ueberlegen muss.

von spess53 (Gast)


Lesenswert?

Hi

>Weil man nahezu gar nichts ueberlegen muss.

Aber man muss mit dem Oszi umgehen können. Sonst kommt noch größerer 
Mist als beim Rechnen heraus. Abgesehen davon besitzt nicht jeder einen 
Oszi.

MfG spess

von Jim M. (turboj)


Lesenswert?

spess53 schrieb:
> Wieso ist das 'Standard'? Ich brauche dafür lediglich IO-Frequenz und
> Baudrate.

Weil die IO-Frequenz nicht konstant ist.

AVR wird mit einem für UART Betrieb etwas zu ungenauen internem 
Oszillator ausgeliefert, den man erst per Fuse auf Quarz (so vorhanden) 
umstellen muss.

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.