Forum: Mikrocontroller und Digitale Elektronik Dringendes Problem mit UART+Baudrate.


von _matze (Gast)


Lesenswert?

Hallo!

Ich habe folgendes Problem:
Ich möchte mit meinem tiny2313 die UART-Schnittstelle (nur TXD) nutzen. 
Der µc läuft dabei mit 8 MHz (CKSEL=1110 SUT=01), die Fuses sind korrekt 
gesetzt.
Die Baudrate soll 9600 betragen (die kann ich ja frei wählen, richtig?). 
Aber egal, was ich versuche, es kommt nur Müll am Terminal an.

Diese defines benutze ich:
1
#ifndef F_CPU
2
  #define F_CPU 8000000
3
#endif
4
#ifndef UART_BAUD_RATE
5
  #define UART_BAUD_RATE 9600
6
#endif

Mit der folgenden Formel soll die Baudrate gesetzt werden:
1
UBRRL = (F_CPU/(16 * baud)) - 1;

Die ist doch richtig, oder?

Mit einer direkten Zuweisung, dessen Wert ich dem Datenblatt entnommen 
habe, geht es auch nicht:
1
UBRRL=51;

Was ist an der ganzen Geschichte falsch?? Ich habe alle möglichen Werte 
durchprobiert, aber immer kommt nur Buchstabensalat an, und dabei hab' 
ich gar keinen Hunger...

Im Ernst, es wäre klasse, wenn jemand einen Tipp hätte. Ich bin am 
verzweifeln...

MfG Matze

von Dussel (Gast)


Lesenswert?

Hab jetzt nicht im Kopf, was die Fuses genau bewirken, aber zuerst mal 
sollte es auf jedem Fall ein externer Oszillator sein (ist 1110 glaube 
ich auch). Verkabelung ist nehme ich an auch richtig!? Ansonsten könnte 
vielleicht UBRRH irgendeinen komischen wert haben, setzt das mal auf 0 
und überprüfe nochnmal in der Programmierung und im Terminalprogramm die 
Stoppbiteinstellungen.

von Falk (Gast)


Lesenswert?

@ _matze (Gast)

>Ich möchte mit meinem tiny2313 die UART-Schnittstelle (nur TXD) nutzen.
>Der µc läuft dabei mit 8 MHz (CKSEL=1110 SUT=01), die Fuses sind korrekt
>gesetzt.

Naja, GANZ korrekt wäre CKSEL=1111 und SUT=01, denn du hast sicherlichen 
einen 8 MHz Quarz dran und keinen Keramikresonator, oder? Sollte aber 
dennoch nicht das Problem sein.

>Die Baudrate soll 9600 betragen (die kann ich ja frei wählen, richtig?).
>Aber egal, was ich versuche, es kommt nur Müll am Terminal an.

>Diese defines benutze ich:

>#ifndef F_CPU
>  #define F_CPU 8000000
>#endif

Besser

#define F_CPU 8000000L

Das L sagt dem Compiler, dass mit 32 Bit gerechnet werden soll, sonst 
rechnet er nur mit 16 Bit und es kommt Müll raus.

>#ifndef UART_BAUD_RATE
>  #define UART_BAUD_RATE 9600
>#endif

>Mit der folgenden Formel soll die Baudrate gesetzt werden:

>UBRRL = (F_CPU/(16 * baud)) - 1;

>Die ist doch richtig, oder?

Naja, wenn du deine defines benutzen willst dann eher

UBRRL = (F_CPU/(16 * UART_BAUD_RATE)) - 1;

>Mit einer direkten Zuweisung, dessen Wert ich dem Datenblatt entnommen
>habe, geht es auch nicht:

>UBRRL=51;

Das ist OK.

>Was ist an der ganzen Geschichte falsch?? Ich habe alle möglichen Werte
>durchprobiert, aber immer kommt nur Buchstabensalat an, und dabei hab'
>ich gar keinen Hunger...

Mahlzeit! ;-)

Bist du sicher dass die Fuses richtig programmiert sind? Klemm man den 
Quarz ab, dann sollte gar nichts ankommen. Wenn doch was ankommt dann 
ist noch der interne RC-Oszillator mit 8 MHz aktiv.

MfG
Falk

von Dussel (Gast)


Lesenswert?

Sehe gerade, dass ein paar Beiträge weiter unten das gleiche Problem 
beschrieben ist (von Timo)

von _matze (Gast)


Lesenswert?

Erstmal vielen Dank für die zügige Hilfe!

Der Thread von Timo hat mich leider nicht weitergebracht (hatte ich 
schon vorher durchgelesen). Auch eure Ratschläge haben leider nicht 
geholfen.

Folgendes habe ich gemacht:

CKSEL=1111 SUT=01
         ^

#define F_CPU 8000000UL
                     ^^

#define UART_BAUD_RATE 9600UL  //obwohl ja hier nicht notwendig
                           ^^

UBRRL=51;  //fest, da ihr mir die Richtigkeit bestätigt habt
      ^^

Quarz abklemmen geht leider nicht, ich befinde mich auf einer festen 
Platine, da kann ich nicht mal eben was ändern. Ich bin aber sicher, 
dass die Fuses korrekt sind. Das AVR Studio bestätigt mir das (Fuses 
einlesen), außerdem brenne ich fast täglich andere ICs mit den gleichen 
Fuses. Da klappt's ja auch immer.

Ergänzung:
----------
(Das hätte ich wohl direkt erwähnen sollen, auch wenn ich der Ansicht 
bin, dass das keinen Unterschied machen sollte.)

Der µC befindet sich auf einer Platine in einem Scanner, nicht auf dem 
Testboard (STK500). Der Pin D0 ist nicht verbunden und somit frei für 
die USART-Nutzung. Ich habe mir von einem Arbeitskollegen ein Kabel an 
den Pin D0 löten lassen (untere Seite vom Sockel natürlich). Dieses 
Kabel steckt auf dem STK500 auf dem TXD-Pin.
An dieser Vorgehensweise ist hoffentlich nichts auszusetzen, oder? Dass 
überhaupt Daten ankommen, ist für mich das Indiz dafür, dass die 
Kommunikation grundsätzlich klappt. Oder gibt es da noch etwas zu 
beachten?
Übrigens, auf der Platine steckt ein 20 Mhz Quarz (Aufschrift AQ20.000). 
Dürfte doch aber irrelevant sein, da der tatsächliche Takt zählt, 
richtig?

Gruß Matze

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> Übrigens, auf der Platine steckt ein 20 Mhz Quarz (Aufschrift AQ20.000).
> Dürfte doch aber irrelevant sein, da der tatsächliche Takt zählt,
> richtig?

Oh weh. Was meinst Du, wer denn den "tatsächlichen Takt" woraus erzeugt?

von _matze (Gast)


Lesenswert?

Entschuldige, ich bin neu in der Firma und habe von Elektrotechnik keine 
Ahnung. Ich hab nur immer gelesen, dass die Fuses den Takt bestimmen, 
und das dann so hingenommen.

Du meinst also, der µC läuft mit 20MHz, obwohl ich per Fuses 8MHz 
einstelle??

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Du stellst mit den Fuses/F_CPU keine 8 MHz ein.

Du gibst im Programm mit F_CPU lediglich bekannt, dass deine Taktquelle 
mit 8 MHz arbeiten tut. Beispielsweise um die UART Einstellungen daraus 
abzuleiten oder um Warteschleifen abzustimmen.

Wenn die Taktquelle mit einem anderen Takt läuft (weil ein anderer Quarz 
verbaut ist), ist es Zufall, wenn das Programm richtig arbeitet.

von _matze (Gast)


Lesenswert?

Das F_CPU lediglich ein define ist und keine Auswirkungen hat, ist mir 
bekannt. Die Sache mit den Fuses verstehe ich allerdings noch nicht so 
ganz.

Bedeutet das, die Fuses sind letztlich egal, wenn ein externer Quarz zum 
Einsatz kommt? Wozu setzt man dann verschiedene Frequenzen? Schließlich 
sagt das AVR Studio, dass ich 8 MHz setze.
Oder anders gefragt: Reicht es bei externem Quarz, irgendeine Frequenz 
einzustellen, da diese letztlich sowieso vom Quarz bestimmt wird? Kann 
ich mir ehrlich gesagt kaum vorstellen, hört sich unlogisch an.

Übrigens vielen Dank für eure Geduld! Ich stelle bestimmt jede Menge 
dumme Fragen (doch, es gibt dumme Fragen!), aber irgendwie muss ich es 
ja lernen...

Wie sieht es mit dem STK500 aus? Da gibt es ja Jumper (OSCSEL, XTAL1, 
...), die die Frequenz und den verwendeten Quarz (intern/extern) 
bestimmen. Kann sich diese Einstellung auswirken, obwohl der µC gar 
nicht auf dem Board sitzt? Schließlich will ich das Board nur wegen der 
RS232-Schnittstelle missbrauchen.

Gruß Matze

von Johannes M. (johnny-m)


Lesenswert?

_matze wrote:
> Wozu setzt man dann verschiedene Frequenzen? Schließlich
> sagt das AVR Studio, dass ich 8 MHz setze.
Das AVRStudio sagt sicher nicht, dass Du genau 8 MHz hast, sondern 
dass Du einen externen Quarz mit einer Frequenz >= 8 MHz anschließt! Die 
Angaben für die Fuses sind alle von...bis und sind erforderlich, da der 
Oszillator auf den Frequenzbereich abgestimmt werden muss.

> Oder anders gefragt: Reicht es bei externem Quarz, irgendeine Frequenz
> einzustellen, da diese letztlich sowieso vom Quarz bestimmt wird? Kann
> ich mir ehrlich gesagt kaum vorstellen, hört sich unlogisch an.
Nein, wie oben schon angedeutet: Die Fuses konfigurieren den im µC 
eingebauten Oszillator. Für höhere Frequenzen muss dieser anders 
angepasst werden als für niedrige Frequenzen. Für einen 16 MHz-Quarz 
sind die Einstellungen anders als für einen 2 MHz-RC-Oszillator.

> Wie sieht es mit dem STK500 aus? Da gibt es ja Jumper (OSCSEL, XTAL1,
> ...), die die Frequenz und den verwendeten Quarz (intern/extern)
> bestimmen. Kann sich diese Einstellung auswirken, obwohl der µC gar
> nicht auf dem Board sitzt?
Wenn kein µC auf dem Board ist, wirkt sich da gar nichts aus. Und die 
Auswahl der Taktquelle geschieht eben über die Fuses. Wenn die Fuses auf 
"interner RC-Oszillator" stehen, ist es dem µC völlig egal, ob da extern 
ein Quarz dranhängt oder nicht.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> Bedeutet das, die Fuses sind letztlich egal, wenn ein externer Quarz zum
> Einsatz kommt?

Nein.

DIE eine Fuses-Einstellung für "externer Quarz" gibt es nicht. Die 
Einstellungen unterscheiden sich untereinander jenachdem ob es ein 
langsamer oder ein schneller Quarz ist. Der µC liefert den Saft, mit dem 
der Quarz zum Schwingen gebracht wird und der µC muss die Schwingungen 
als Takt entgegen nehmen. Das kannst du mit dem "Feintuning der Fuses" 
anpassen. So gesehen ist die Einstellung natürlich nicht egal.

> Wozu setzt man dann verschiedene Frequenzen?

Um den Wert für F_CPU zu generieren und damit im Programm zu wurschteln. 
Und vielleicht (!) auch, um automatisch die eine passende 
Fuses-Einstellung bei verschienden Möglichkeiten zu setzen. Weiss ich 
jetzt nicht ohne Nachschauen in AVRStudio.

> Schließlich sagt das AVR Studio, dass ich 8 MHz setze.

Sicher, oder ist das nur die Defaulteinstellung in der Auswahlbox?

von _matze (Gast)


Lesenswert?

Ok, das mit den Fuses habe ich nun (endlich!) verstanden! Danke für die 
ausführlichen Erklärungen und die unendliche Geduld, die ich allerdings 
noch weiter strapazieren muss...

Könnt ihr mir denn sagen, was dann noch falsch sein soll? Ich denke, die 
Berechnung der Baudrate ist richtig, und auch sonst sollte alles 
stimmen, oder?
1
#ifndef F_CPU
2
  #define F_CPU 20000000UL
3
#endif
4
#ifndef UART_BAUD_RATE
5
  #define UART_BAUD_RATE 9600UL
6
#endif
7
8
/***************/
9
int main(void) {
10
/***************/
11
12
  USART_init(UART_BAUD_RATE);
13
14
  for(;;) {
15
    USART_transmit('A');
16
    _delay_ms(10);
17
    _delay_ms(10);
18
    USART_transmit('B');
19
    _delay_ms(10);
20
    _delay_ms(10);
21
  }
22
}
23
24
/***************/
25
static void USART_init(unsigned int baud) {    //nochmal genau ansehen und schöner formulieren!
26
/***************/
27
  UCSRA=0x00;
28
29
  UBRRL = (F_CPU/(16 * baud)) - 1;
30
  UBRRH=0x00;
31
32
  UCSRB = (1 << RXEN) | (1 << TXEN);
33
}
34
35
/***************/
36
void USART_transmit(unsigned char cData) {  //sendet ein Zeichen ans Terminal
37
/***************/
38
  while( !(UCSRA & (1<<UDRE)) ) {
39
    ;//warten, bis der transmit buffer leer ist, so dass wieder übertragen werden kann
40
  }
41
  UDR = cData;
42
}

von _matze (Gast)


Lesenswert?

Bitte nicht auf fehlende Prototypen etc. achten, der Code war natürlich 
wesentlich größer und wurde von mir (mehr oder weniger) fachgerecht 
beschnitten! Es fehlt aber nichts, was für die Problematik relevant sein 
könnte.

von Johannes M. (johnny-m)


Lesenswert?

Hast Du im AVRStudio auch die korrekte Taktfrequenz für den µC 
eingestellt? Das
1
#define F_CPU 20000000UL
hat nur dann einen Effekt, wenn es nicht durch eine Einstellung im 
Makefile (bzw. in den Configuration Options im AVRStudio) 
"überschrieben" wird. Und wenn da ein falscher Wert angegeben ist, dann 
funktioniert es nunmal nicht.

von _matze (Gast)


Lesenswert?

In den Configuration Options ist keine Frequenz eingestellt. Dort liegt 
also auch nicht der Fehler, richtig? Hmpfh.....

von Johannes M. (johnny-m)


Lesenswert?

Wenn Du in den Configuration Options einfach mal die 20000000 Hz 
eingibst, ist das sicher nicht verkehrt...

von _matze (Gast)


Lesenswert?

DDRD ist irrelevant für UART, oder? Meines Wissens wirkt sich die 
Datenrichtung ja nur aus, wenn die Pins zu normalen I/O-Zwecken genutzt 
werden.

von Johannes M. (johnny-m)


Lesenswert?

_matze wrote:
> DDRD ist irrelevant für UART, oder? Meines Wissens wirkt sich die
> Datenrichtung ja nur aus, wenn die Pins zu normalen I/O-Zwecken genutzt
> werden.
Richtig, im Falle des UART werden die DDRD-Einstellungen ignoriert.

von _matze (Gast)


Lesenswert?

Johannes, bist du vielleicht ein Wesen aus der Zukunft? Ein Gott? Mehr 
als das? Jedenfalls HERZLICHEN DANK, dein Vorschlag war die Lösung!

Auch wenn ich es nicht verstehe. Laut deiner Aussage wird der selbst 
definierte Wert F_CPU von der Einstellung im AVR-Studio überschrieben 
(wenn vorhanden). So habe ich es zumindest verstanden.

Das scheint wohl nicht ganz richtig zu sein, denn mit einem Eintrag in 
den Options läuft es plötzlich! Ich kannte diese Einstellung nicht, 
deswegen habe ich da auch nicht nach der Lösung gesucht. Und bislang 
habe ich immer mit internem Takt gearbeitet, da trat das Problem nicht 
auf.

So kann's gehen, da sucht man Stunden vergebens nach der Lösung, und 
schließlich geht's nur um eine Kleinigkeit (mit fatalen Folgen).

Jedenfalls nochmal Dankeschön an Johannes und alle anderen Meister der 
Geduld!

Gruß Matze

von Falk (Gast)


Lesenswert?

@ _matze (Gast)

>Johannes, bist du vielleicht ein Wesen aus der Zukunft? Ein Gott? Mehr

<Blasphemie>

Neee, er hat einfach nur elementare Grundlagen drauf

</Blasphemie>

>als das? Jedenfalls HERZLICHEN DANK, dein Vorschlag war die Lösung!

>Auch wenn ich es nicht verstehe. Laut deiner Aussage wird der selbst
>definierte Wert F_CPU von der Einstellung im AVR-Studio überschrieben
>(wenn vorhanden). So habe ich es zumindest verstanden.

Mit

#define F_CPU 20000000UL

sagt du AVR Studio, dass ein 20 MHz Quarz angeschlossen ist. Denn woher 
soll die Software (AVR-Studio) wissen, wie die Hardware aufgbaut ist?

Genauso wie du mit den Fuses der Hardware mitteilen musst, wie sie 
arbeiten soll. Du kann den interen Oszillator verwenden, der hat ein 
paar feste Frequenzen (8/4/1 MHz). Oder einen exteren Quarz. Dort wird 
die Freqeunz aber durch den Quarz festgelegt, nicht durch die Fuses. Die 
sagen nur, "Nimm den Quarz".

MfG
Falk

von _matze (Gast)


Lesenswert?

Richtig, aber leider wird mein define F_CPU überschrieben, auch wenn in 
den Configuration Options GAR KEIN Wert steht. Allein mit dem define 
funktioniert es leider nicht. Hab jetzt Feierabend, muss mir morgen aber 
mal das Makefile, das AVR Studio erzeugt, ansehen. Da sollte der Wert ja 
letztlich stehen.

Gruß Matze

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.