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


von Jack (Gast)


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):
1
void init_uart(void){
2
  UBRR0H = (unsigned char)(UBRR_VAL>>8);   // UBRR = UART Baud Rate Register
3
  UBRR0L = (unsigned char)(UBRR_VAL);     // UBRR Register zum berechnen/setzen der Baudrate
4
  UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);      // Asynchron 8N1
5
  UCSR0B = (1<<TXEN0) | (1<<RXEN0);        // tx & rx enable
6
                         // Wenn TXEN und RXEN gesetzt ist, arbeitet die UART,
7
                        // sonst sind die PINS normale I/O-Pins
8
}
9
10
void uart_putc(unsigned char c){
11
  while (!(UCSR0A & (1<<UDRE0))){
12
    /* warten bis Senden moeglich */
13
  }
14
  UDR0 = c;                // UDR0 = UART Data Register
15
}                         // Hier werden Daten zwischen UART und CPU übertragen
16
17
void uart_puts (const char *s){
18
  do{
19
    uart_putc (*s);
20
  }while(*s++);
21
}
22
23
uint8_t uart_getc(void){
24
  while (!(UCSR0A & (1<<RXC0)))
25
    ;    //warten bis Zeichen verfuegbar
26
  return UDR0;
27
}
28
29
30
31
32
#define BAUD 115200UL          // Baudrate //921600
33
34
#ifndef F_CPU
35
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 14745600UL"
36
#define F_CPU 14745600UL    // Systemtakt in Hz
37
// Definition als unsigned long beachten
38
// Ohne UL ergibt Fehler in der Berechnung
39
#endif
40
 
41
// Berechnungen
42
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
43
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
44
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)      
45
// Fehler in Promille, 1000 = kein Fehler
46
 
47
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
48
#warning "Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!" 
49
#endif








main:

  char xxx;

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

      uart_putc(xxx);

von Jack (Gast)


Lesenswert?

uint8_t xxx; //geändert << geht auch nicht

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

      uart_putc(xxx);

von Thomas E. (thomase)


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.

von Jack (Gast)


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

von Stefan E. (sternst)


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.

von Jack (Gast)


Lesenswert?

Das mag ja sein, aber das Problem bleibt bei beiden Formeln.

von Hc Z. (mizch)


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.

von Thomas E. (thomase)


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.

von Hc Z. (mizch)


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.

von Thomas E. (thomase)


Angehängte Dateien:

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.

von Walter (Gast)


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!

von Thomas E. (thomase)


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.

von Walter (Gast)


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

von Thomas E. (thomase)


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.

von Karl H. (kbuchegg)


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.

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.