Forum: Mikrocontroller und Digitale Elektronik ATmega644PA empfängt auf USART1 nur 0-Bytes nach 2 Min


von Bernhard (Gast)


Lesenswert?

Hallo!

Nach langer Fehlersuche habe ich mich entschieden die Frage ans Forum zu 
stellen.

Ich habe ein Crumb644 mit einem ATmega644PA und 14.7456 MHz Quarz.
Auf der Platine ist USART0 mit dem USB-Seriell-Wandler verbunden und 
USART1 an einem RS485 Konverterchip.

Der USART1 empfängt froh Daten vom RS485 die auch richtig ankommen. 
Konfiguration: 9600 8N2 (ja, 8N zwei)

Mein Problem ist, dass nachvollziehbar immer nach ca. 2 Minuten auf 
USART1 in der RX ISR nur noch Bytes mit "0" in UDR1 ankommen - obwohl 
auf dem Scope am Pin des Controllers eindeutig die richtigen Daten 
anliegen.

Erratas scheint es für den 644PA nicht zu geben, Datenblatt habe ich 
schon durchforstet, Code aufs notwendigste ausgedünnt, alles kein 
Erfolg.

Im Fehlerfall steht in UCSR1A der Wert 0x30 (UDRE1 und FE1 gesetzt) und 
in UCSR1B der Wert 0x98
FE1 kommt daher weil auf dem Bus einige Geräte anstelle 2 Stop-Bits nur 
eines senden. IMHO kann das ignoriert werden.

Habt Ihr mal ähnliche Erfahrungen gemacht, ist das vielleicht irgendein 
Bug in Hardware oder muss ich den Fehler in der Software suchen?

Bin gerade etwas ratlos.

Grüße,
Bernhard

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Bernhard schrieb:
> in der RX ISR nur noch Bytes mit "0" in UDR1 ankommen
Wie hast du das kontrolliert?
Die ISR wird aber noch zuverlässig pro Zeichen 1 mal aufgerufen?

> ist das vielleicht irgendein Bug in Hardware
Die RX-ISR wird ja nur dann angesprungen, wenn die Hardware ein Byte 
tatsächlich (merh oder weniger) empfangen hat. Prüfst du auch die 
Fehlerflags des UART?

> oder muss ich den Fehler in der Software suchen?
Wenn auf der Hardware die Signale tatsächlich am Pin ankommen, dann 
würde ich sagen: Ja, such den Fehler in der Software.

: Bearbeitet durch Moderator
von S. Landolt (Gast)


Lesenswert?

> FE1 kommt daher weil auf dem Bus einige Geräte anstelle
> 2 Stop-Bits nur eines senden.
Das glaube ich nicht, aus dem Datenblatt zu FEn:
"This bit is set if the next character in the receive buffer had a Frame 
Error when received. I.e., when the first stop bit of the next character 
in the receive buffer is zero."

> IMHO kann das ignoriert werden.
M.E. ist das FE1 ein wichtiger Fingerzeig.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Für den Empfang von Daten ist es nicht erforderlich, zwei Stopbits zu 
konfigurieren. Ändere das mal auf ein Stopbit und beobachte weiterhin 
das "framing error"-Bit.

Mit den Stopbits kann es dann nichts mehr zu tun haben.

von Georg G. (df2au)


Lesenswert?

Das UART wertet nur das erste Stopbit aus. Die 2 Stopbits sind nur beim 
Senden relevant und sollen der Gegenseite mehr Zeit für die Reaktion 
geben bzw bei vielen unmittelbar aufeinander folgenden Bytes eine 
schnellere Synchronisation ermöglichen.

von Bernhard (Gast)


Lesenswert?

Zunächst Danke für Eure Antworten!

@Lothar:

So wird das kontrolliert:
1
uint8_t data, stat;
2
3
stat = UCSR1A;
4
data = UDR1;
5
6
UDR0 = data;
7
8
// hier werte ich die Fehlerflags aus
9
// aktuell nur DOR1


USART0 läuft mit 115200bps, USART1 mit 9600
Von daher ist "UDR0 = data" so machbar ohne groß zu warten.
Am PC lasse ich mir die empfangenen Daten als Hex ausgeben.

@S. Landoldt:

Beim letzten Test habe ich vor dem Fehlerfall auf dem RS485 1247 
Telegramme (alle mit korrekter Prüfsumme usw.) erhalten. Darunter auch 
viele einzelne Bytes mit nur einem Stop-Bit.

Bisher hatte ich auf allen meinen Geräten den RS485 auf USART0 und nie 
ein ähnliches Problem gehabt. Den Code habe ich portiert und mehrfach im 
Editor und per grep auf der Konsole sichergestellt dass überall die 
richtigen Register verwendet werden.

von Oliver S. (oliverso)


Lesenswert?

Bernhard schrieb:
> USART0 läuft mit 115200bps, USART1 mit 9600
> Von daher ist "UDR0 = data" so machbar ohne groß zu warten.

Du könntest ja trotzdem mal UDRE0 vorher abfragen, nicht, daß da doch 
was klemmt.

Oliver

von S. Landolt (Gast)


Lesenswert?

FEn heißt, dass der Empfänger auf dem ersten (!) Stopbit eine Null 
sieht.

Lothar Miller schrieb:
> Wenn auf der Hardware die Signale tatsächlich am Pin ankommen
Die Betonung liegt auf 'am Pin'.

von Karl M. (Gast)


Lesenswert?

Guten Morgen,

auch ist zu überprüfen, ob man senden über Uart0 darf.

UCSR0A – USART Control and Status Register A
Bits:
RXC0 TXC0 UDRE0 FE0 DOR0 UPE0 U2X0 MPCM0

while ( (UCSR0A & (1<<UDRE0)) == 0  ) { }

Das zeigt dieses Codestück nicht.
1
uint8_t data, stat;
2
stat = UCSR1A;
3
data = UDR1;
4
UDR0 = data;

Man könnte nun entgegen, dass die beiden Uart mit unterschiedlicher 
Baudrate arbeiten, aber man weis halt nicht wirklich, ob der 
Senderegister von Uart0 bereit ist neue Daten aufzunehmen !

Erst dachte ich es werden sauber Sende- und Empfangspuffer (Fifo) für 
beide Uart genutzt, aber nein, das UartN-Handling ist unsauber in meinen 
Augen.

von Bernhard (Gast)


Lesenswert?

@Oliver:

UDRE0 könnte man abfragen, ja. Trotzdem kommt die ISR von USART1 knapp 
jede mS und dann hat USART0 schon längst alles im Hintergrund 
verschickt.
Es kommen ja auch alle 1247 Telegramme korrekt am PC an, nur dann nur 
noch Nuller.

@S. Landoldt:

FEn auf erstem Stopbit, richtig (gerade nachgelesen).
Die Ursache ist ein Gerät auf dem Bus was keine 2 Stopbits kann und das 
dann per 9-Bit Übertragung emuliert. Firmware ist nicht von mir und den 
Fehler kenne ich.
Gerät vom Bus abgeklemmt und siehe da - kein FE1 mehr.
Fehlerbild ist immernoch das gleiche. Gerade nach 700 Telegrammen.

> Die Betonung liegt auf 'am Pin'.

Nun, ich gehe davon aus dass die Lötstellen von der vorgefertigten 
Platine in Ordnung sind und eine Messung ausreicht um sicherzustellen 
dass die Bits aus Tatsächlich am Pin ankommen.
Nehmen wir den unwahrscheinlichen Fall dass die Verbindung nicht in 
Ordnung ist, dann kommen entweder zufällige Daten an oder gar nichts.

Im Rhythmus der der Telegramme wird die ISR von USART1 aufgerufen und 0 
aus UDR1 ausgelesen. Ohne dass überhaupt ein Takt am RXD1 anliegt würde 
das doch nicht passieren, oder?

Nachtrag:

Auf mehrfachen Wunsch und trotz meines besseren Wissens habe ich nun den 
Code wie folgt "sauber" abgeändert:
1
uint8_t data, stat;
2
stat = UCSR1A;
3
data = UDR1;
4
loop_until_bit_is_set(UCSR0A, UDRE0);
5
UDR0 = data;

Ergebnis: Bringt nix, gleiches Ergebnis - immernoch Nullen

von Karl M. (Gast)


Lesenswert?

Hallo Bernhard,

für mich, bzw. die Fehlersuche, machst Du noch zu viele Annahmen.
Ich habe gelernt noch nichts als gegeben aus zu gehen und selbst alle 
Verbindungen zu überprüfen und auch selbst für einen korrekten Code zu 
sorgen.

Kannst Du bitte eine abgespecktes Programm, das einen mögl. Fehler immer 
noch zeigt, bitte komplett einstellen ?

Mit komplett ist gemeint, dass unserer AVR Gcc diesen Quelltest auch 
übersetzt.

von Bernhard (Gast)


Lesenswert?

@Karl:

Danke für Deine Unterstützung.
In einer ISR mache ich ungern while Loops. Davor hatte ich ausgiebige 
Tests mit ner FIFO-Loop für USART0.
Um das Thema nicht allzu aufzublähen habe ich das weggelassen. 
Vielleicht war das ein Fehler, ist aber jetzt nicht wichtig.

Beispielcode: Ja, das ist das Ulitimo-Ratio - bisher will ich mir den 
Aufwand sparen.

Hat denn irgendjemand schonmal ein ähnliches Problem gehabt? Das wäre 
spannend zu wissen. Wenn nicht dann muss ich einfach weiter in der 
Software nach einer möglichen Ursache suchen.

von Karl M. (Gast)


Lesenswert?

Hallo Bernhard ,

ich will nicht überheblich klingen, Probleme sollte man immer im Code 
suchen.

Bei mir läuft Uart0 etc. immer problemlos.
Ich verwende immer für den Hardware-Uart eine RX-/TX-Fifo gestützte 
Implementierung.
Diese muss man nur einmalig richtig programmieren und kann sie dann als 
kleine Lib immer über ein Makefile und einer Inlcudedatei mit einbinden.

Und so könnte das für Uart0 aussehen:

Beitrag "AVR-GCC: UART mit FIFO"

von ianet (Gast)


Lesenswert?

Karl M. schrieb:
> ich will nicht überheblich klingen, Probleme sollte man immer im Code
> suchen.

Klingt aber falsch. Was ist, wenn der Fehler in der HW steckt. Nicht 
notwendigerweise im µC aber im sonstigen Azfbau?

von Peter D. (peda)


Lesenswert?

Null-Byte + Frame-Error deutet auf eine viel zu hohe Baudrate hin 
(Startbit wird als Byte abgetatet). Du solltest dann auch viel mehr 
Bytes empfangen (jede 1-0 Flanke).
Irgendeine Task schaltet nach 2min die Baudrate um. Debugge mal das 
Baudratenregister.

von Bernhard (Gast)


Lesenswert?

@Peter:

Vielen Dank für den Tipp!
Das ist nämlich genau die Ursache für die Null-Bytes!
Das UBRR1L Register wird auf 0 gesetzt und damit wird das Start-Bit als 
Byte abgetastet!

Der Fehler lag natürlich auch in der Software - ein Copy-Paste Fehler in 
einem Array von verschiedenen Bus-Geschwindigkeiten war
1
{ .high = BAUD1_UBRR1H, .low = BAUD1_UBRR1H}
... sollte eigentlich heißen:
1
{ .high = BAUD1_UBRR1H, .low = BAUD1_UBRR1L}

Danke an alle für Eure Hilfe!

von S. Landolt (Gast)


Lesenswert?

Das ist mir nicht klar, da sollte doch ein Frame-Error kommen. Wie passt 
das zu:

Bernhard schrieb:
> ... Firmware ist nicht von mir und den Fehler kenne ich.
> Gerät vom Bus abgeklemmt und siehe da - kein FE1 mehr.

von Pandur S. (jetztnicht)


Lesenswert?

Was fuer einen Oszillator verwendest du, den internen RC, der mit der 
Temperatur weglaeuft ? Ja, ich hab vom Quarz gelesen, aber wurde der 
auch konfiguriert ?
Ich wuerd einfach periodisch ein paar Bytes raussenden, und diesen dann 
mit einem Oszilloskop vermessen, und/oder mit dem PC empfangen.

von Bernhard (Gast)


Lesenswert?

@ S. Landoldt:

FE1 bei normaler Funktion - hatte ich möglichereweise missverständlich 
formuliert.

@ Oder Doch:

Zuerst 20MHz Quarz, während Fehlersuche gegen 14.7456MHz getauscht.
Daran lags sicher nicht :)


Wie gesagt - Problem ist jetzt gelöst - danke nochmal!

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.