Forum: Mikrocontroller und Digitale Elektronik Atmega8A UART sendet nur Müll


von Lars (Gast)


Lesenswert?

Hallo zusammen,

ich schaffe es einfach nicht eine vernünfitge UART Ausgabe 
hinzubekommen. Vielleicht könnte mal jemand auf den Code schauen. In 
Putty empfange ich nur Mist, wo eigentlich das Wort "Hallo" erscheinen 
sollte. Die Baudrate ist 19200 eingestellt, der Atmega8A läuft mit einem 
8 MHz Quarz (extern).
Als Kabel zwischen AVR und PC verwende ich ein "TTL-232R-5V" von FTDI. 
Dort habe ich GND, RX und TX belegt.

1
//uart.h
2
3
#ifndef UART_H_
4
#define UART_H_
5
6
#define BAUD 19200UL //Baudrate
7
8
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)  //clevers Runden
9
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))    //reale Baudrate
10
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)    //Fehler in Promille, 1000=kein Fehler
11
12
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
13
#error Systematischer Fehler der Baudrate ist groesser 1% und damit zu hoch!
14
#endif
15
16
#endif /* UART_H_ */
1
//uart.c:
2
3
#include <avr/io.h>
4
#include "uart.h"
5
6
7
8
9
void uart_init(void)
10
{
11
  UBRRH = UBRR_VAL >> 8;
12
  UBRRL = UBRR_VAL & 0xFF;
13
  
14
  // UART TX einschalten
15
  UCSRB |= (1 << TXEN);
16
  //Frame Format: Asynchron 8N1
17
  UCSRC |= (1<<URSEL) | (1<<UCSZ0)|(1<<UCSZ1);
18
}
19
20
21
int uart_putc(unsigned char c)
22
{
23
  while (!( UCSRA & (1<<UDRE)));  //warten bis Senden möglich
24
  {
25
    
26
  }
27
  
28
  UDR = c;              //sende Zeichen
29
  return 0;
30
}
31
32
33
void uart_puts (char *s)
34
{
35
  while (*s)
36
  {  /* so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)" */
37
    uart_putc(*s);
38
    s++;
39
  }
40
}

1
//main.c:
2
3
#include <avr/io.h>
4
#include "uart.h"
5
6
7
int main(void)
8
{
9
  
10
  uart_init();
11
12
13
    while (1) 
14
    {
15
    uart_puts("Hallo");
16
    
17
  }
18
}

von Karl M. (Gast)


Lesenswert?

Hallo,

was ist hier wohl falsch ?
1
while (!( UCSRA & (1<<UDRE))); //<===  //warten bis Senden möglich
2
  {
3
    
4
  }

von Karl M. (Gast)


Lesenswert?

Sonst braucht so ein AVR auch einen Takt, den mal als Define F_CPU 
wieder findet.
Wie sieht das in deinem Code aus?

Evtl. passen die Fustbit-Einstellung: Prescaler 1/8 zu deiner Annahme 
nicht.

von Lars (Gast)


Lesenswert?

...und das kommt in Putty an:

"«::"

von Karl M. (Gast)


Lesenswert?

Lars schrieb:
> ...und das kommt in Putty an:
>
> "«::"

Frage: Wenn man was tut?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Wenn du bei putty mal die Baudrate von 2400 einstellst - was passiert 
dann?

Um dem Empfänger eine Chance aufs Erkennen des Startbits zu geben (im 
Moment sendest du ja einen endlosen Bitstrom), kannst du auch mal ein 
kleines Delay in der Hauptschleife vor oder nach dem uart_puts() 
einfügen.

Karl M. schrieb:
> was ist hier wohl falsch ?
> while (!( UCSRA & (1<<UDRE))); //<===  //warten bis Senden möglich
>   {
>
>   }

Tja, da muss der TE sich wohl entscheiden. Entweder Semikolon oder 
geschweifte Klammern :-P

: Bearbeitet durch User
von Lars (Gast)


Lesenswert?

5x Ausgabe mit delay von 2 Sekunden:

▒::
                                                                                                                                                                                            ▒::
                                                                                                                                                                                               ▒::
                                                                                                                                                                                                  ▒::
                                                                                                                                                                                                     ▒::



...


Bei Puttybaudrate von 2400 kommt nichts an.
Unter Translation habe ich UTF-8 belassen.

von Karl M. (Gast)


Lesenswert?

Nun, auf Fragen gehst Du anscheinend nicht ein...

Schade.

Wie sieht die Ausgabe als HEX aus, was ist zu sehen?
Korreliert das dann doch zum Programm, wenn die Baudrate nicht stimmt?

Beitrag #5713322 wurde vom Autor gelöscht.
von Lars (Gast)


Angehängte Dateien:

Lesenswert?

Hier die Ausgabe statt Putty mit hterm in Ascii, Hex, Dec und Bin.
Gesendet wird weiterhin "Hallo".

von Falk B. (falk)


Lesenswert?

Lars schrieb:
> while (1)
>     {
>     uart_puts("Hallo");

Mach hier mal eine Pause rein, so ein Dauerfeuer verhindert eine 
Synchronisation auf einen Anfang, vor allem, wenn man Fehler finden 
will.

_delay_ms(1000);

von Lars (Gast)


Angehängte Dateien:

Lesenswert?

Und das wäre bei BAUD = 2400.

von Lars (Gast)


Lesenswert?

Ein 10 Sekunden Delay ist schon drinnen.
1
 while (1) 
2
    {
3
    _delay_ms(10000);
4
    uart_puts("Hallo");
5
    }


Auch habe ich hier das Semikolon entfernt:
1
int uart_putc(unsigned char c)
2
{
3
  while (!( UCSRA & (1<<UDRE)))  //warten bis Senden möglich
4
  {
5
    
6
  }
7
  
8
  UDR = c;      //sende Zeichen
9
  return 0;
10
}

von Felix (Gast)


Lesenswert?

Lars schrieb:
> //uart.c:
>
> #include <avr/io.h>
> #include "uart.h"
>
> void uart_init(void)
> {
>   UBRRH = UBRR_VAL >> 8;
>   UBRRL = UBRR_VAL & 0xFF;
>
>   // UART TX einschalten
>   UCSRB |= (1 << TXEN);
>   //Frame Format: Asynchron 8N1
>   UCSRC |= (1<<URSEL) | (1<<UCSZ0)|(1<<UCSZ1);
> }
>

Es könnte sein, dass du die Zuweisung an UBRRH und UBRRL noch casten 
müsstest auf uint8.

Z. B. so: UBRRH = (uint8_t)(UBRRVAL >> 8);

von Falk B. (falk)


Lesenswert?

Lars schrieb:
> Ein 10 Sekunden Delay ist schon drinnen. while (1)
>     {
>     _delay_ms(10000);
>     uart_puts("Hallo");
>     }

Das ist Unsinn, es reichen ein paar Millisekunden, ggf. 1s, damit man 
als Mensch im Terminalprogramm nicht mit Text überflutet wird.

>Auch habe ich hier das Semikolon entfernt:

Ist nebensächlich. Du hättest einfach die Klammern entfernen können, 
aber auch die haben logisch nicht geschadet. Sie waren nur überlüssig.

int uart_putc(unsigned char c)
{
  while (!( UCSRA & (1<<UDRE)));  //warten bis Senden möglich
  UDR = c;      //sende Zeichen
  return 0;
}

: Bearbeitet durch User
von Lars (Gast)


Lesenswert?

Zu den Fusebits:

Dort habe ich High = 0xD9 und Low = 0xED, F_CPU ist mit 8000000UL 
definiert.

von Lars (Gast)


Angehängte Dateien:

Lesenswert?

Habe statt "Hallo" jetzt "xxxxx" geschrieben. Anbei das Ergebnis. Die 
ersten 4 Zeichen sind gleich, das 5. allerdings nicht mehr.

von Karl B. (gustav)


Lesenswert?

Hi,
schon testweise einmal das angegebene Programm ausprobiert?

https://www.mikrocontroller.net/articles/AVR-Tutorial:_UART

Wenn es nicht klappt, liegt es vielleicht am Putty-Terminalprogramm und 
dessen Einstellungen.
Probiere einmal Teraterm aus.
Bei mir machte Hyperterminal immer "Jitter". D. h. einmal Zeichen 
richtig, dann einmal LSB falsch. Weil Flanke wackelte.
Teraterm machte das nicht. Bügelt den Fehler aus.

ciao
gustav

: Bearbeitet durch User
von Volker S. (vloki)


Lesenswert?

Karl B. schrieb:
> Bei mir machte Hyperterminal immer "Jitter". D. h. einmal Zeichen
> richtig, dann einmal LSB falsch. Weil Flanke wackelte.
> Teraterm machte das nicht. Bügelt den Fehler aus.

Kann ich mir hier irgendwie nicht vorstellen,
wie das Terminal-Programm die Hardware entsprechend beeinflussen soll.
(von der korrekten Übermittlung der Parameter für Baudrate ... 
abgesehen)

von Felix (Gast)


Lesenswert?

Ich habe dein Programm mal genommen und auf meinen ATmega8 geschmissen.

Nach Konfiguration der Konstante F_CPU über die Gnu Compiler Symbols 
(mit der Quarzfrequenz 7,3728MHz, die ich habe) kommt ein Hallo sehr 
zuverlässig raus.

Du hast womöglich F_CPU nicht (an der richtigen Stelle?) definiert oder 
die CKDIV-Fuse gesetzt. Der Takt an deiner CPU scheint nicht so zu sein, 
wie du denkst.

Probe: toggle ne LED einmal die Sekunde per delay_ms(1000). Stimmt die 
Taktfrequenz? Dann ist es was anderes bei dir.

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

Hi,
hier noch die Bildchen dazu.
Korrektur: MSB wird verfälscht bei Hyperterminal. Bei Teraterm nicht.
(Man kann testweise das Häkchen bei Echo reinsetzen, wenn nichts kommt.)

ciao
gustav

: Bearbeitet durch User
von Lars (Gast)


Lesenswert?

Danke Karl,

dann liegt es scheinbar nicht am Code.
Ich habe jetzt mal den internen 1 MHz Takt des AVR verwenwendet. Dieser 
ist unter Symbols mit "F_CPU=1000000UL" definiert. Ferner habe ich die 
Baudrate auf 2400 reduziert.

Im Terminal kommt damit leider auch nur der selbe "Mist" an.

Der Takt an sich scheint zu stimmen, durch das delay kommt alle 10 
Sekunden der Datensatz.

von Bimbo. (Gast)


Lesenswert?

Junge, nimm ein Oszilloskop und schaue ob auf der Uart TX die richtigen 
Zeichen rauskommen und ob der Takt überhaupt korrekt ist. Das ist doch 
ein Rumstochern hier. Wenn du dort 18243 statt 19200 hast, weißt du was 
los ist.

Es gibt heutzutage auch Oszilloskope, die eine UART dekodieren und dir 
in Echtzeit anzeigen, was du überträgst.

von Georg G. (df2au)


Lesenswert?

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

würde ich anders machen
  // UART TX einschalten
  UCSRB = (1 << TXEN);
  //Frame Format: Asynchron 8N1
  UCSRC = (1<<URSEL) | (1<<UCSZ0)|(1<<UCSZ1);

Bei deiner Version bleiben womöglich Bits stehen vom letzten Lauf. Oder 
gehst du immer von einem harten Reset aus? Defensiv programmieren!

von Volker S. (vloki)


Lesenswert?

Lars schrieb:
> Habe statt "Hallo" jetzt "xxxxx" geschrieben. Anbei das Ergebnis.

Schwer vorstellbar, wie aus einem 'x' 0x78 ein 0xE8 wird.

Ich nehme an du hast kein Oszilloskop zur Hand?

Ich würde dann erst mal ein einziges 'U' (0b01010101) schicken, und 
schauen, was dabei raus kommt. (wiederholt im x Sekundenabstand)

Möglich wäre auch die Zeit der Übertragung von vielen Zeichen über eine 
LED am TX zu messen und daraus die Baudrate grob zu schätzen.

von Stefan F. (Gast)


Lesenswert?

Ein Oszilloskop (gibt's unter dem Namen DSO138 ab ca. 30€) oder ein 8 
Channel Logic Analyzer (ab 10€) wäre jetzt nützlich.

von Wolfgang (Gast)


Lesenswert?

Stefanus F. schrieb:
> ... oder ein 8 Channel Logic Analyzer (ab 10€) wäre jetzt nützlich.

Sind die jetzt sooh teuer geworden? :-0
Vor ein paar Tagen waren die noch deutlich unter 6€.

von Dirk B. (Gast)


Lesenswert?

Lars schrieb:
> Anbei das Ergebnis.
das sieht sehr stark nach einem invertieren Signal aus (wirklich schwer 
vorstellbar, da das erste Datenbit dann zum Startbit wird usw.). Evtl. 
ist im FTDI-Treiber Rx auf invertiert eingestellt.
Ansonsten neben dem von Volker vorgeschlagenem 'U' auch 0xF0 und 0x0F 
ausprobieren.

von Joachim B. (jar)


Lesenswert?

Dirk B. schrieb:
> das sieht sehr stark nach einem invertieren Signal aus

war mein erster Gedanke

von Jakob (Gast)


Lesenswert?

Läuft der mega8 denn wirklich mit dem externen 8 MHz-Quarz?

Der Baudraten-Mist lässt sich leicht erklären, wenn zwar ein
Quarz dranhängt, aber der interne RC-Oszillator benutzt
wird und mit CKSEL3:0 zu F-CPU = 1, 2, 4, (oder 8) MHz
geschaltet ist.

Ohne Oszi hilft es dann nur, einen Hardware-Timer so zu
programmieren, dass er auf einem Port-Pin im Sekundentakt
eine LED aufblitzen lässt.

Der 16-Bit Timer1 mit Vorteiler 1/256 als CTC mit
MAX-Count = 31249 könnte das bewerkstelligen. Das kann man
über ein paar Minuten mit dem Sekundentakt einer Uhr
vergleichen.
Bei echten 8 MHz läuft das synchron!
Taktfehler im Prozentbereich (die RS232 außer Takt bringen)
fallen damit schnell auf.

von Ben B. (Firma: Funkenflug Industries) (stromkraft)


Lesenswert?

Evtl. falsche Kondensatoren am Quarz? Quarz defekt?
Siebkondensatoren vergessen? Sowas hat manchmal sehr komische Effekte.

von Wolfgang (Gast)


Lesenswert?

Jakob schrieb:
> Ohne Oszi hilft es dann nur, einen Hardware-Timer so zu
> programmieren, dass er auf einem Port-Pin im Sekundentakt
> eine LED aufblitzen lässt.

In Zeiten von C auf dem µC, wird man wohl einfacher ein delay() zusammen 
mit dem Blinken einer LED verwenden. Das reicht um einen grob falschen 
Quarz oder Teiler zu identifizieren.
Bei Preisen von unter 6€ für einen elementaren Logikanalysator gibt es 
heutzutage eigentlich keinen vernünftigen Grund, auch nur 1/2h damit zu 
verbringen, über Timing und Polarität von einem UART-Signal rum zu 
rätseln.

von Dirk B. (Gast)


Lesenswert?

Volker S. schrieb:
> Schwer vorstellbar, wie aus einem 'x' 0x78 ein 0xE8 wird.
Da das Messergebnis trotz Hinweis und Dokumentation als "erster Gedanke" 
weiterhin so viele Fragezeichen verursacht ein Versuch mit Zeichen zu 
beschreiben was passiert wenn 'x' bzw. 'xx' 100% taktgenau/100% 
invertiert gesendet (ex)oder empfangen wird:
1
$78:0111.1000           ; 'x'
2
r:  0001.1110            ; lsb first (praktisch rückwärts)
3
f: sooo1 111oE sooo1 111oE ^^^^; 'xx'framed:+(s)tart/(E)ndbit + idle(^)
4
i: ^^^^s ooo1o 111Es ooo1o oooe; invertiert(s=startbit Erkennung)
5
rec:   | 00010 111+| 00010 000-; 'netto' Empfang; Frame:[+|-];0...=brk
6
msb-f    111 01000($E8)-($08[FE])-($00[brk])
(auch 'Hallo' wurde 100% taktrichtig/signalfalsch gemessen)
Mögliche Ursachen:
a) Treiber/Empfänger 'verkehrt' eingestellt
b) Sender u.U. eine Platine auf der Max 2. einen Käfer verzinnt hat 
(quasi ein Rs232-Bug in dem Kontext) oder
c) etwas komplizierte Steckerverpolung (Tx an Vcc/ Gnd an Rx) was aber 
eigentlich nur mit viel Übung passieren dürfte.

Eigentlich gibt es bei solchen eindeutigen Messergebnissen keinen 
vernünftigen Grund wild von zusätzlicher Hardware zu schreiben wenn 
schon das Messergebnis des verwendeten elementaren Logikanalysators 
nicht verstanden wird.

NB.: wenn eh eine serielle Schnittstelle verwendet werden soll,dann 
lässt die sich auch sehr einfach ohne zusätzliche Verkabelungen/LED o.ä. 
durch Senden eines(!) 0x7f zur Taktmessung verwenden: kommen 2 Zeichen 
an, dann einfach auf 8MHz hochskillen ;-)

von Volker S. (vloki)


Lesenswert?

Dirk B. schrieb:
> Eigentlich gibt es bei solchen eindeutigen Messergebnissen keinen
> vernünftigen Grund wild von zusätzlicher Hardware zu schreiben wenn
> schon das Messergebnis des verwendeten elementaren Logikanalysators
> nicht verstanden wird.

Es scheint leider Messinstrument vorhanden zu sein, mit dem der 
Signalverlauf aufgezeichnet werden könnte. Sonst wäre es ja einfach ;-)

von Peter D. (peda)


Lesenswert?

Ich denke mal auch, da fehlt eine Invertierung (MAX232).
Das kann man einfach mit ner SW-UART prüfen, denn da läßt sich leicht 
die Polarität vertauschen:

Beitrag "Debug Ausgaben"

von Lars (Gast)


Angehängte Dateien:

Lesenswert?

Danke Dirk und Peter!

Eure Vermutung war richtig. Ich habe mir mal das FTDI_Tool 
runtergeladen. Im Eeprom des Chips sind tatsächlich RX und TX als 
invertiert gesetzt.
Wäre ich nie drauf gekommen, da ich das Kabel kürzlich für eine andere 
Andwendung neu gekauft hatte und dort die Kommunikation (Senden und 
Empfangen) problemlos funktionierte.

Laut Datenblatt
Seite 22 sind TX und RX werksseitig nicht invertiert, bei mir aber 
schon.

Seite 22

https://www.ftdichip.com/Support/Documents/DataSheets/Cables/DS_TTL-232R_CABLES.pdf

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.