Forum: Mikrocontroller und Digitale Elektronik UART sende richtig, empfängt aber falsch


von MandA K. (Firma: MAMIMO STudios) (bastlomat)


Lesenswert?

Guten Abend,

ich habe hier einen AT644, der bei 20 MHz über UART mit dem PC verbunden 
ist. Baud 250000 2 Stop bits. Was funktioniert ist, das ich Zeichen vom 
Controller zum PC senden kann. Wenn ich allerdings die empfangenen 
Zeichen wieder zurück schicke kommen immer 2 unterschiedliche Zeichen 
bei raus aber nie das, was ich gesendet habe.
1
  
2
UBRR0 = UBRR_VAL;
3
UCSR0C = (1 << USBS0) | (3 << UCSZ00); 
4
UCSR0B = (1 << TXEN0) | (1 << RXEN0) | (1 << RXCIE0) ; 
5
6
ISR(USART0_RX_vect)
7
{
8
  data =UDR0;
9
  UDR0=data;
10
}

Hat jemand eine Idee?

Grüße

von Bert 0. (maschinist)


Lesenswert?

Hallo,

ich mag jetzt nicht das Datenblatt studieren, aber ist 20MHz denn 
wirklich eine Baudratenfrequenz?

Oder ist 250000 BpS eine gültige PC-Bitrate?

Irgendwo hier hapert es, schau Dir mal genau das serielle Timing an!



Gruß...Bert

von cskulkw (Gast)


Lesenswert?

Prinzipiell kann man eine beliebige Baudrate einstellen, solange sich 
Empfaenger und Sender über ein gemeinsames Timing einig sind.

Das Programm sieht nach First Steps on AVR aus.

Wenn Du keinen Debugger hast, um im UDR0 nachschauen zu können, ob das 
empfangene Zeichen dem gesendeten entspricht, dann solltest Du 
vielleicht erst einmal mit einer langsameren Baudrate anfangen.

void SetCommBaudRate(unsigned int param_BaudRateToSet,
       unsigned long param_ProcessorClockRate)
{
  float varl_BaudRateRegister = (param_ProcessorClockRate / (16.0 * 
(float) param_BaudRateToSet));

  unsigned int varl_IntBRR = (unsigned int) varl_BaudRateRegister;
  float varl_Remainder = varl_BaudRateRegister - (float) varl_IntBRR;

    /* laut Formel einen abz,iehen und das im Integer. */
    if(varl_Remainder < 0.5)
    {
      varl_IntBRR --;
    }

    UBRR0L = (unsigned int)  (varl_IntBRR & 0x00FF);
    UBRR0H = (unsigned int) ((varl_IntBRR & 0xFF00) >> 8);
}

Versuche mal, ob Dir diese Routine bei der Baudrate hilft.

Du kannst dabei z.b. den Aufruf so schreiben:

SetCommBaudRate(20000000,115000);

Viel Erfolg...

von Udo S. (urschmitt)


Lesenswert?

Interessant wäre vieleicht auch welches Zeichen erwartet und welche 
Zeichen erhalten wurden. Dann könnte man evt. sehen was für ein Bit 
gekippt ist.
Verwendeter Zeichensatz?
Ansonsten werden meine Vorredner wohl recht haben.

von MandA K. (Firma: MAMIMO STudios) (bastlomat)


Lesenswert?

Ne ne also die Tackfrequenz des Controllers ist 20MHz. Die Baudrate ist 
250000.
Im Datenblatt ist auch angegeben, welchen Wert für UBRR nehmen soll( in 
diesem Fall "4").

Wenn ich mit dem Terminal Programm ein einfaches "a" sende und das 
direkt wieder zurück schicke, Kommt bei 5 sendewiderholungen  3 mal 177 
und 2 mal 166 am Terminal an?!

Die baudrate ist eingentlich im Datenblatt mit 0% Fehler angegeben. 
Niedrigere Baudraten haben dann 0,2% oder sogar 4%. Das liegt ja in der 
Teilbarkeit des Controllertacktes so irgendwas war da.

Ich frag mich nur, wieso er wunderbar senden kann, aber nicht empfangen.

von Udo S. (urschmitt)


Lesenswert?

MandA K. schrieb:
> Ne ne also die Tackfrequenz des Controllers ist 20MHz. Die Baudrate ist
> 250000.

MandA K. schrieb:
> Die baudrate ist eingentlich im Datenblatt mit 0% Fehler angegeben.
> Niedrigere Baudraten haben dann 0,2% oder sogar 4%. Das liegt ja in der
> Teilbarkeit des Controllertacktes so irgendwas war da.

Ja klar, der Takt (schreibt sich übrigens nicht mit 'ck') berechnet sich 
aus dem Prozessortakt und dem Teilungsfaktor aller Vorteiler.

Du magst mit 250.000 Baud auf dem µC zwar einen Fehler von 0% haben, die 
Frage ist aber was macht denn dein PC? Denn der hat einen Taktoszillator 
der ein vielfaches von 1200 ist.
Ich habe noch nie gehört daß eine PC Schnittstelle mit 250.000 Baud 
funktioniert.
Wikipedia nennt übliche Baudraten von 115.200, 230.400 und 460.800.
So wie ich PC Software kenne ist es gut möglich, daß du dein PC Programm 
zwar mit 250.000 intialisiert aber nicht den Returnwert prüfst oder der 
Funktionsaufruf einfach ohne Fehler den nächstliegendsten Wert nimmt.
Welcher das ist könntest du herausfinden indem du nach dem Setzen der 
Baudrate diese nochmal ausliest.
Fang halt mal mit 9600 oder 19200 Baud an.

von Thomas E. (thomase)


Lesenswert?

MandA K. schrieb:
> Ne ne also

Ja ja.

Du hast also alles richtig gemacht? Dann funktioniert es ja.

Tut es das aber nicht, hast du nicht alles richtig gemacht. So einfach 
ist das. Da sind weder Windows noch Atmel noch der GNU-Compiler dran 
schuld.

Und in der Zeit von gestern abend 22:19 bis jetzt, hättest du schon 
lange verschiedene  Baudraten, wie vorgeschlagen, testen können. Das ist 
ohnehin das erste, was man macht.

Woher weisst du denn, daß dein USB-to-serial-Converter das überhaupt 
kann? Weil auf der Verpackung stand bis 936.000? Und dann muß er 
zusammen mit dem PC eine exotische Baudrate wie 250.000 Bd auch können?

mfg.

von MandA K. (Firma: MAMIMO STudios) (bastlomat)


Lesenswert?

Ja es war die Baudrate was für eine Überraschung. Ich habe mich von der 
Fehlerangabe des Datenblattes blenden lassen!!

Dankeschön! Jetzt kann es erst richtig los gehen mit dem Quadrocopter 
:-)!

von Michael U. (amiga)


Lesenswert?

Hallo,

ein FTDI kann z.B. schon 250000. Dummerweise nicht aus jedem 
Terminalprogramm. Wenn man aus eigener Software mit 250000 
initialisiert, geht es problemlos.

Gruß aus Berlin
Michael

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.