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
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.
> 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.
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.
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.
Zunächst Danke für Eure Antworten!
@Lothar:
So wird das kontrolliert:
1
uint8_tdata,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.
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
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'.
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_tdata,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.
@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:
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.
@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.
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"
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?
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.
@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
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.
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.
@ 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!