mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Mikrocontroller empfängt Daten nicht UART ATmega644


Autor: Jack (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der uC soll auf ein Zeichen warten, was ich am Terminal senden möchte, 
er macht es nicht. Hier ist der Code (denke es liegt an der 
Initialisierung):
void init_uart(void){
  UBRR0H = (unsigned char)(UBRR_VAL>>8);   // UBRR = UART Baud Rate Register
  UBRR0L = (unsigned char)(UBRR_VAL);     // UBRR Register zum berechnen/setzen der Baudrate
  UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);      // Asynchron 8N1
  UCSR0B = (1<<TXEN0) | (1<<RXEN0);        // tx & rx enable
                         // Wenn TXEN und RXEN gesetzt ist, arbeitet die UART,
                        // sonst sind die PINS normale I/O-Pins
}

void uart_putc(unsigned char c){
  while (!(UCSR0A & (1<<UDRE0))){
    /* warten bis Senden moeglich */
  }
  UDR0 = c;                // UDR0 = UART Data Register
}                         // Hier werden Daten zwischen UART und CPU übertragen

void uart_puts (const char *s){
  do{
    uart_putc (*s);
  }while(*s++);
}

uint8_t uart_getc(void){
  while (!(UCSR0A & (1<<RXC0)))
    ;    //warten bis Zeichen verfuegbar
  return UDR0;
}




#define BAUD 115200UL          // Baudrate //921600

#ifndef F_CPU
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 14745600UL"
#define F_CPU 14745600UL    // Systemtakt in Hz
// Definition als unsigned long beachten
// Ohne UL ergibt Fehler in der Berechnung
#endif
 
// Berechnungen
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)      
// Fehler in Promille, 1000 = kein Fehler
 
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
#warning "Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!" 
#endif








main:

  char xxx;

  xxx = uart_getc(); //Hier wartet er nicht einmal

      uart_putc(xxx);

Autor: Jack (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uint8_t xxx; //geändert << geht auch nicht

  xxx = uart_getc(); //Hier wartet er nicht einmal

      uart_putc(xxx);

Autor: Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jack schrieb:
> #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden

Finde ich nicht besonders clever. Wenn man das nachrechnet, kommt da 
totaler Müll bei raus.


Jack schrieb:
> F_CPU+BAUD*8
Was soll das?

So wird das ausgerechnet:
UBRRn = (fOSC /16BAUD) -1

mfg.

Autor: Jack (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
gut danke schön. Das habe ich geändert, es läuft aber immer noch nicht 
Korrekt.

Hab jetzt folgendes gemacht:

unsigned char xxx;

xxx = uart_getc();
uart_puts(&xxx);

xxx = uart_getc();
uart_puts(&xxx);

xxx = uart_getc();
uart_puts(&xxx);

xxx = uart_getc();
uart_puts(&xxx);

xxx = uart_getc();
uart_puts(&xxx);

Habs einfach paar mal öfters eingetippt, die ersten 3 mal kommt nur 
irgendwas, ohne das ich etwas eingebe. Dann kann ich etwas eingeben und 
er gibt mir sogar den richtigen Wert wieder, jedoch mit zwei 
Folgezeichen die aussehen wie eine eckige 0 :) (in binär 11111111 
00010000)


Kann es sein, dass am Anfang noch etwas müll im Register steht und ich 
erstmal löschen muss??? Nur wie am besten??

Mit freundlichen Grüßen
Jack

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas Eckmann schrieb:
> Jack schrieb:
>> #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
>
> Finde ich nicht besonders clever. Wenn man das nachrechnet, kommt da
> totaler Müll bei raus.

Dann rechne besser nochmal nach. Die Formel ist nämlich korrekt und 
besser als deine Einfach-Formel, eben weil eine eventuelle Aufrundung 
enthalten ist.

Autor: Jack (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mag ja sein, aber das Problem bleibt bei beiden Formeln.

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das hier:

Jack schrieb:
> xxx = uart_getc();
> uart_puts(&xxx);

sendet natürlich nach jedem gültigen Zeichen noch eine zufällige Anzahl 
von Müllzeichen nach.  Denn uart_puts erwartet einen Null-terminierten 
String. Oder besser, es sollte.  Denn das hier:

> void uart_puts (const char *s){
>   do{
>    uart_putc (*s);
>  }while(*s++);
> }

erwartet zwar einen Null-terminierten Sting, sendet aber die Null mit.

Deine Schrottzeichen sind also genau das, was das das Programm macht.

Autor: Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> Dann rechne besser nochmal nach. Die Formel ist nämlich korrekt und
>
> besser als deine Einfach-Formel, eben weil eine eventuelle Aufrundung
>
> enthalten ist.

Das ist nicht meine Formel, sondern die aus dem Datenblatt.

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas Eckmann schrieb:
> Das ist nicht meine Formel, sondern die aus dem Datenblatt.

Das ist nicht die aus dem Datenblatt.  Dort sieht man eine mathematische 
Formel.  Wenn man die sehr schlicht umsetzt, d.h. alle Variablen darin 
als Integer annimmt, kommt Deine (entschuldige: die von Dir 
geschriebene) Formel raus.

Geht man das Thema aber ohne die Integer-Vereinfachung an und rechnet 
sauber mathematisch, kommt - danach auf Integer umgerechnet - die Formel 
des OP raus, die allgemein gebräuchlich ist.

Autor: Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hc Zimmerer schrieb:
> Thomas Eckmann schrieb:
>
>> Das ist nicht meine Formel, sondern die aus dem Datenblatt.
>
>
>
> Das ist nicht die aus dem Datenblatt.  Dort sieht man eine mathematische
>
> Formel.  Wenn man die sehr schlicht umsetzt, d.h. alle Variablen darin
>
> als Integer annimmt, kommt Deine (entschuldige: die von Dir
>
> geschriebene) Formel raus.
>
>
>
> Geht man das Thema aber ohne die Integer-Vereinfachung an und rechnet
>
> sauber mathematisch, kommt - danach auf Integer umgerechnet - die Formel
>
> des OP raus, die allgemein gebräuchlich ist.

Anstatt hier dumm rumzusülzen solltest du vielleicht mal ins Datenblatt 
reingucken.

mfg.

Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas Eckmann schrieb:
>> Geht man das Thema aber ohne die Integer-Vereinfachung an und rechnet
>>
>> sauber mathematisch, kommt - danach auf Integer umgerechnet - die Formel
>>
>> des OP raus, die allgemein gebräuchlich ist.
>
> Anstatt hier dumm rumzusülzen solltest du vielleicht mal ins Datenblatt
> reingucken.
>
> mfg.

is nu Mal so: wenn man die Formel aus dem Datenblatt korrekt umsetzt, 
dann muss man runden. Das machst Du nicht und das ist nicht korrekt.
Also bitte nicht gleich beleidigt sein und andere anmachen!

Autor: Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Walter schrieb:
> is nu Mal so: wenn man die Formel aus dem Datenblatt korrekt umsetzt,
>
> dann muss man runden. Das machst Du nicht und das ist nicht korrekt.
>
> Also bitte nicht gleich beleidigt sein und andere anmachen!

Erstens bin ich nicht beleidigt und zweitens, wer mich anmacht, den 
mache ich auch an.

Und jetzt mal sachlich:
Bei dem 14,74600 MHz Quarz handelt es sich um einen Baudratenquarz. 
Solche Quarze setzt man da ein, wo man exakte Baudraten haben möchte. Da 
wird überhaupt nicht gerundet. Sondern das geht in Integer immer glatt 
auf.
Und deswegen runde ich da nicht und das ist sehr korrekt.
Deswegen nimmt man nämlich einen Baudratenquarz.

Mit so einer komischen Formel, allgemeingültig(?), versaut man sich 
leider die ganze Rechnerei. Mag sein, daß das für 20 MHz ja Sinn macht. 
Aber nicht für 14,74600 MHz.

mfg.

Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas Eckmann schrieb:
> Mit so einer komischen Formel, allgemeingültig(?), versaut man sich
> leider die ganze Rechnerei. Mag sein, daß das für 20 MHz ja Sinn macht.
> Aber nicht für 14,74600 MHz.

das ist keine komische Formel, man versaut sich nichts, sie ist 
allgemeingültig.
Deine mag ja für 14,74600 MHz stimmen, für nicht Baudratenquarze und die 
gibts ja auch stimmt sie nicht.
Dann müsstest du korerekterweise vor dem Berechnen abfragen ob es ein 
Baudratenquarz ist und wenn nicht die Berechnung mit der komischen 
Formel machen.
Das fände ich aber wirklich komisch

Autor: Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Walter schrieb:
> das ist keine komische Formel, man versaut sich nichts, sie ist
>
> allgemeingültig.
>
> Deine mag ja für 14,74600 MHz stimmen, für nicht Baudratenquarze und die
>
> gibts ja auch stimmt sie nicht.
>
> Dann müsstest du korerekterweise vor dem Berechnen abfragen ob es ein
>
> Baudratenquarz ist und wenn nicht die Berechnung mit der komischen
>
> Formel machen.
>
> Das fände ich aber wirklich komisch

Stimmt. Das ist keine komische Formel.
Eine mathematische Formel, die auch nur ein einziges Mal falsch rechnet, 
ist wirklich nicht komisch, sondern Müll.

mfg.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas Eckmann schrieb:

> Stimmt. Das ist keine komische Formel.
> Eine mathematische Formel, die auch nur ein einziges Mal falsch rechnet,
> ist wirklich nicht komisch, sondern Müll.

Ich weiss nicht, wie du zu der Aussage kommst, dass die Formel Müll 
berechnet.

Auch im Fall eines Baudratenquarzes kommt da selbstverständlich das 
richtige raus. Wahrscheinlich hast du dich beim Taschenrechner vertippt. 
In beiden Fällen kommt eine Integer 7 raus.


Bei 14.476 Mhz und 9600 Baud errechnet sich nach Datenblatt-Formel ein 
einzustellender Wert von 8.6

Deine Datenblattformel würde daher bei einer Einstellung von 8 liegen, 
während der gerundete Wert einen Wert von 9 ergibt. 8.6 liegt näher an 9 
als an 8, daher ist der Fehler dort kleiner. Und genau das macht die 
Formel mit der Rundungskorrektur. Und um nichts anderes als um eine 
Rundungskorrektur handelt es sich bei dem zusätzlichen Term. Damit bei 
einem rein rechnerischen Ergebnis von 12.9 dann auch tatsächlich 13 
rauskommt und nicht 12.

Und das hier
> Sondern das geht in Integer immer glatt auf.
ist ein Irrtum, wovon man sich leicht überzeugen kann, wenn man mal mit 
deinem 'Baudratenquarz' 14.476Mhz und einer Baudrate von 9600 
nachrechnet. Baudratenquarze haben die Eigenschaft, dass man viele 
Baudraten mit ihnen glatt erzeugen kann. Aber viele ist nicht 
gleichbedeutend mit allen/immer.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.