Forum: Mikrocontroller und Digitale Elektronik UART Problem


von Sepp H. (vali1991)


Lesenswert?

Hallo, ich verwende einen ATmega8 und möchte gerne ein Zeichen über die 
Serielleschnittstelle an einen Terminal(PC) senden.

Doch es tut sich nichts.

#include <avr/io.h>

#define F_CPU 3686400L
#define BAUD 9600L
#define UBRR_VAL = ((3686400/(9600*16))-1)

void uart_init(void) {
    UBRRH = 0x00;
  UBRRL = 0x17;


    UCSRB |= (1<<TXEN);  // UART TX einschalten
    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1
}

int main(void) {
  while(1){
  while (!(UCSRA & (1<<UDRE)))  // warten bis Senden moeglich
    {
    UDR = 'x';
  }
    UDR = 'x';
  }
}


Wäre super, wenn mir jemand helfen könnte, danke.
von STK500-Besitzer (Gast)


Lesenswert?

1
  while (!(UCSRA & (1<<UDRE)))  // warten bis Senden moeglich

da fehlt ein Semikolon
von Sepp H. (vali1991)


Lesenswert?

die geschwungene Klammer befindet sich eine Zeile darunter, müsste doch 
passen oder?
von STK500-Besitzer (Gast)


Lesenswert?

Nein
von holger (Gast)


Lesenswert?

void uart_init(void) {

wird in der main() nie aufgerufen.
von J.-u. G. (juwe)


Lesenswert?

Sepp Horst schrieb:
> die geschwungene Klammer befindet sich eine Zeile darunter, müsste doch
> passen oder?

Nein. Du schreibst doch selbst im Kommentar "warten bis Senden möglich".

Es ist also sinnlos, während das Wartens ständig etwas ins UDR zu 
schreiben.
von Sepp H. (vali1991)


Lesenswert?

Ok, danke. Bekomme jedoch noch falsche Zeichen im Terminal. Das müsste 
doch an einer falschen Baudrate liegen? Habe im Terminal und im Programm 
auf 9600 baud, 1 Stopp - Bit gestellt, was könnte ich noch falsch 
gemacht haben?
von Sepp H. (vali1991)


Lesenswert?

Verwende einen Quarz mit 3,6864 MHz!
von Tom (Gast)


Lesenswert?

Sepp Horst schrieb:
> #define F_CPU 3686400L
> #define BAUD 9600L
> #define UBRR_VAL = ((3686400/(9600*16))-1)

Warum definierst du eine L-Konstante, wenn du die zwei Zeilen später gar 
nicht verwendest. Und wozu wird UBRR_VAL berechnet?

Wenn du deinem Code nicht traust, kannst du besser den Ablauf im 
Simulator verfolgen (z.B. die UART Initialisierung), anstatt 
irgendwelche magischen Zahlen im Quellcode zu verteilen.

Sepp Horst schrieb:
> die geschwungene Klammer befindet sich eine Zeile darunter, müsste doch
> passen oder?
Überleg mal, was in der While-Schleife passieren soll?
von holger (Gast)


Lesenswert?

>Ok, danke. Bekomme jedoch noch falsche Zeichen im Terminal. Das müsste
>doch an einer falschen Baudrate liegen? Habe im Terminal und im Programm
>auf 9600 baud, 1 Stopp - Bit gestellt, was könnte ich noch falsch
>gemacht haben?

Dein uC läuft mit falschem Takt. Vermutlich 1MHz intern RC.
Du musst die Fuses auf Crystal Osc umstellen.
UND BLOSS NICHT AUF EXTERN CLOCK!
von Sepp H. (vali1991)


Lesenswert?

Habe bei Fuses auf: Ext. Crystal/Resonator High Freq.; Start-up time: 
16K CK + 64 ms gestellt. Ist das Richtig?
von holger (Gast)


Lesenswert?

Wie sieht dein Programm jetzt aus?
von Sepp H. (vali1991)


Lesenswert?

#include <avr/io.h>

#define F_CPU 3686400
#define BAUD 9600
//#define UBRR_VAL = ((3686400/(9600*16))-1)

void uart_init(void) {
    UBRRH = 0x00;
  UBRRL = 0x17;


    UCSRB |= (1<<TXEN);  // UART TX einschalten
    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1
}

int main(void) {
  uart_init();
  while(1){
  while (!(UCSRA & (1<<UDRE))) {  // warten bis Senden moeglich
  }
        UDR = 'x';
    }
}
von Karl H. (kbuchegg)


Lesenswert?

Sepp Horst schrieb:
> Habe bei Fuses auf: Ext. Crystal/Resonator High Freq.; Start-up time:
> 16K CK + 64 ms gestellt. Ist das Richtig?

Und hat es geklappt?

(Du hast doch einen Quarz drauf? Hoffe ich zumindest)

Ich kann nur wieder auf die Checkliste verweisen.
Dort ist auch enthalten, wie man überprüfen kann, ob der µC jetzt 
tatsächlich mit der am Quarz aufgedruckten Frequenz arbeitet.
http://www.mikrocontroller.net/articles/AVR_Checkliste#UART.2FUSART
von Sepp H. (vali1991)


Lesenswert?

Habe den Quarz laut SDK - 500 Handbuch gejumpert und die Fuses 
eingestellt. Es hat sich nichts verbessert, es werden noch immer fast 
kreisrunde Zeichen  statt x ausgegeben.
von Karl H. (kbuchegg)


Lesenswert?

Sepp Horst schrieb:
> Habe den Quarz laut SDK - 500 Handbuch gejumpert und die Fuses
> eingestellt. Es hat sich nichts verbessert, es werden noch immer fast
> kreisrunde Zeichen  statt x ausgegeben.

Zum 35.ten mal:

Hast du KONROLLIERT, ob dein µC mit der am Quarz aufgedruckten Frequenz 
läüft oder hast du das nicht?

Es ist uninteressant was du wo reingesteckt hast und welche Fuse du wo 
umgestellt hast. Du musst KONTROLLIEREN ob dein µc mit der gewünschten 
Taktrate läuft. Vertrauen ist gut, Kontrolle ist besser.

Zu mehr als 98% sind deine Symptome auf eine falsche Taktrate 
zurückzuführen. Möglich, dass du zu den verbleibenden 2% gehörst. Aber 
solange du nicht definitiv die 98% ausschliessen kannst (und zwar 
aufgrund von Messungen), ist das erst mal die Arbeitshypothese Nummero 
Uno.
von Sepp H. (vali1991)


Lesenswert?

Hab den Quarz mit Hilfe des Testprogrammes und einer LED getestet, er 
funktioniert.
von Karl H. (kbuchegg)


Lesenswert?

Sepp Horst schrieb:
> Hab den Quarz mit Hilfe des Testprogrammes und einer LED getestet, er
> funktioniert.

F_CPU war auf 3696400 gestellt?
Blinken alleine ist zu wenig. Stimmt das Timing auch? Am besten mit 
einer Stoppuhr 20 mal aufblinken der LED abstoppen. Die gemessene Zeit 
sollte ziemlich genau 40 Sekunden betragen - im Rahmen der Genauigkeit 
einer Handstoppung.

(Es gibt nur die beiden Möglichkeiten
  entweder die Taktfrequenz im µC stimmt nicht
  oder das Terminalprogramm ist auf eine andere Baudrate eingestellt.

Wenn die beiden Dinge korrekt sind und die RS232 über das Jumperfeld 
richtig angestöpselt wurde (da kannst du kaum einen Fehler machen), dann 
MUSS die RS232 soweit funktioneren.

Terminal am PC zuerst hochfahren und laufen lassen. Dann erst den µC 
einschalten, wobei die Kabelverbindung schon bestehen muss. Stimmt das 
Timing, dann muss das auf Anhieb klappen.
von Sepp H. (vali1991)


Lesenswert?

Hab da Timing gestoppt, ein Zustand am LED dauert jeweils eine Sekunde.
Hab nun versucht das Terminalprogramm zu starten, anschließend wurde die 
Verbindung mit den richtigen Einstellungen hergestellt und 
schlussendlich habe ich den µC eingeschaltet.
Resultat --> es funktioniert (also lag es an der Reihenfolge von 
Connection starten und µC einschalten)

Vielen Dank!
von Karl H. (kbuchegg)


Lesenswert?

Gut.

Was du dir merken musst: Du kannst dich nicht mit dem Empfänger in eine 
laufende ununterbrochene Übertragung einschalten. Der Empfänger ist 
darauf angewiesen, dass der Sender immer wieder mal eine kleine Pause in 
der Übertragung einlegt, damit er sich zu 100% sicher auf den Anfang 
eines Zeichens synchronisieren kann. Ansonsten bekommt der Empfänger Bit 
um Bit vorgesetzt und kann nicht feststellen, bei welchem Bit ein 
Zeichen anfängt.

int main(void) {
  uart_init();
  while(1){
    while (!(UCSRA & (1<<UDRE))) {  // warten bis Senden moeglich
    }
    UDR = 'x';
    _delay_ms( 10 );    // <--------
  }
}

hätte den gleichen Zweck erfüllt.
von Sepp H. (vali1991)


Lesenswert?

Ok, nochmal vielen Dank!
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.