PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : UART bringt µC aus dem Takt



demmy
09.11.2015, 21:33
Hallo zusammen,

ich habe mal wieder ein merkwürdiges Problem.

Ich habe eine kleine Platine mit einem Atmega8-16PU erstellt. Die Platine wird mit 24V versorgt und über einen Schaltregler werden die 5V für den Atmega rutergeregelt. Am µC hängt ein 8Mhz Quarz. Weiter sind an dem µC 2 Relais über Transistoren angeschlossen als schaltbare Ausgänge sowie 2 Transistoren als Eingangsbeschaltung. Über Eingang 1 kann Relais 1 geschaltet werden und über Eingang 2 das Relais 2. Zusätzlich kann über die UART der Status der Relais und der Eingänge (Taster) ausgelesen werden.
Des Weiteren gibt es mehrere LEDs die an verschiedene µC-Pins hängen und verschiedene Stati anzeigen.

Nun zu meinem Problem:

Betreibe ich die Platine ohne UART funktioniert das Programm einwandfrei. Die Relais lassen sich über die Eingänge ein- und ausschalten und auch die LEDs zeigen an was sie sollen.

Schalte ich jetzt eine zweite Platine dazu, die über die UART zyklisch (Protokoll an Protokoll) den Status der ersten Platine abruft, dann fängt die erste Platine irgendwie das spinnen an!
Das heißt, die LEDs blinken kurzzeitig unregelmäßig mal hin und her oder die Relais schalten plötzlich kurz mal ein und wieder aus. Obwohl keine Taste gedrückt wurde. Also ein komplett Chaotisches Verhalten.

Die Baudrate ist auf beiden Seiten auf 9600 Baud eingestellt. Die UART lasse ich mit Interrupts arbeiten (Bascom Config SerialIn und SerialOut).

Die Daten die hin und her geschaufelt werden sind jedenfalls korrekt, das habe ich rausgemessen bzw. mitgeschrieben.

Vom Ablauf her werden permanent Daten über die UART hin und hergeschickt. Mir kommt es fast so vor, als würde der µC aus einem UART Interrupt an die falsche Stelle im Programm zurückspringen und dann unerlaubt irgendwelche Schaltungen auslösen. Ein schalten der Relais über die UART bzw. das Protokoll ist nicht möglich! Das heißt, der Fehler muss irgendwo im Timing des µC sein vermute ich. Ich habe irgendwie das Gefühl das die UART-Interrupts den µC aus dem tritt bringen oder so. Aber ganz kann ich es mir nicht erklären.

Habt Ihr sowas schonmal gehabt? Die Spannung am µC habe ich gemessen, es sind immer konstant 5V.

Würde es evtl. was bringen wenn ich mit dem Quarz runter gehe oder auf einen Baudratenquarz wechsle?


Ich hoffe Ihr habt ein paar gute Ideen und könnt mir helfen.

Peter(TOO)
09.11.2015, 23:20
Hallo,

Das heißt, der Fehler muss irgendwo im Timing des µC sein vermute ich. Ich habe irgendwie das Gefühl das die UART-Interrupts den µC aus dem tritt bringen oder so. Aber ganz kann ich es mir nicht erklären.

Habt Ihr sowas schonmal gehabt? Die Spannung am µC habe ich gemessen, es sind immer konstant 5V.

Würde es evtl. was bringen wenn ich mit dem Quarz runter gehe oder auf einen Baudratenquarz wechsle?

Die 5V muss man mit dem Oszilloskop messen, ein DVM kann in diesem Falle keine Aussage machen.

Die grundsätzliche Frage ist, ob der Fehler im Hardware-Aufbau liegt oder in der Software!

Hardware:
Da wäre zuerst einmal die Masse-Verbindung zwischen den Platinen und mögliche Brummschleifen.
Gibt es auch Blockkondensatoren?
Die Datenübertragung erzeugt ein Störsignal, das ist eigentlich eine Variable Frequenz. Wenn dein Aufbau nicht ganz sauber ist, kann das dann zu viel werden. Bei einem sauberen Aufbau ist das kein Problem.

Software:
Hier ist vor allem im Bereich der Interrupts zu suchen.
1. Die Interrupts benötigen zusätzlichen Platz auf dem Stack um Register und Rücksprung-Adresse zu retten und für lokale Variablen. Hier kann es zu einem Überlauf kommen, wenn der Stack zu klein ist.
2. Wenn die ISR nicht richtig beendet wird, weil z.B. Interrupts zu früh wieder freigegeben werden, können sich die ISR auf den Stack schachteln, was auch zu einem Überlauf führen kann.
3. Mit Bascom kenne ich mich nicht so aus, aber bei C ist ein typischer Fehler mit nicht initialisierten Zeigern zu arbeiten oder über Array-Grenzen hinaus zu schreiben. Dann wird irgendwie der Stack zerschossen. Besonders wenn dann eine Rücksprung-Adresse überschrieben wird, macht das Programm unerwartete Dinge!


Die Baudrate hat nur am Rande einen Einfluss und ein Ändern löst das Problem nicht wirklich. 9600 Baud sind eigentlich noch keine Herausforderung für den µC.
9'600 Baud ergibt maximal knapp 1'000 Interrupts/Sekunde. Wenn der Fehler jetzt bei jedem 1'000ten Aufruf auftritt, dauert es nur etwas länger, wenn du die Baudrate senkst, behebt aber den Fehler nicht wirklich.

MfG Peter(TOO)

peterfido
10.11.2015, 07:27
Hallo,

so ohne vollständiges Programm ist die Frage nicht vernünftig zu beantworten.

demmy
10.11.2015, 07:59
Guten Morgen zusammen,

also die Spannung werde ich heute Abend nochmal mit dem Oszilloskop genau messen und euch dann berichten. Grundsätzlich ist es so, das die Spannung von einer Platine zur anderen weitergegeben wird. Beide Platinen hängen also an der gleichen Spannungsquelle und haben die gleiche Masse. Die Masseflächen auf den Platinen sind Polygone-Flächen die Eagle berechnet hat, es sollte also keine Masseschleifen geben.
Blockkondensatoren sind auch überall vorhanden. Die Platine kann ich euch auch heute Abend mal per Foto zeigen.

Was den Stack angeht, daran habe ich auch schon gedacht und habe die Werte im Programm mal übertrieben hochgesetzt. Den HWstack, SWstack und Frame jeweils 200. Das sollte mehr als genug Platz sein.
Hab ich irgendwie eine Möglichkeit den Stack zu diagnostizieren um zu sehen was dort abgeht?


2. Wenn die ISR nicht richtig beendet wird, weil z.B. Interrupts zu früh wieder freigegeben werden, können sich die ISR auf den Stack schachteln, was auch zu einem Überlauf führen kann.

Wie kann ich das überprüfen? Kann das der Fall sein wenn Timer interrupts und UART interrupts ineinander greifen? Wenn Ja, wie kann ich das umschiffen?


3. Mit Bascom kenne ich mich nicht so aus, aber bei C ist ein typischer Fehler mit nicht initialisierten Zeigern zu arbeiten oder über Array-Grenzen hinaus zu schreiben. Dann wird irgendwie der Stack zerschossen. Besonders wenn dann eine Rücksprung-Adresse überschrieben wird, macht das Programm unerwartete Dinge!


Was meinst du mit nicht initialisierten Zeigern?

Das Programm gibt es ebenfalls heute abend. :)

Also wenn ich das richtig verstanden habe, von einem Baudratenquarz haltet Ihr nichts? Nicht das da aufgrund der für die Baudrate "ungeraden" Quarzfrequenz was durcheinander kommt!?

peterfido
10.11.2015, 09:41
Bei 9600 mit 8MHz gibt es da keine Probleme. Wenn die Ausgänge sich anders verhalten, wenn UART läuft, dann ist das ein anderes Problem.

Das überlasse ich dann anderen, bin erst wieder am WE am PC.

fredred
10.11.2015, 14:41
Hallo demmy,

bin ich richtig in der Annahme du hast kein RS232 Pegelwandler nachgeschaltet?
Wenn nicht kann die Fehlersuche schon aufwendiger werden.
Wenn ja die einzelnen Platinen mit PC-COM Terminal lesen. Nun solltest du sehen ob UART fehlerfrei funktionier.
Hinweis: Für solche Tests habe ich ein kleines RS232 Modul gebaut. Ist mittlerweile für Software Überprüfung unentbehrlich geworden.
Vermute aber(da kein Code) es liegt an Enable/Disable Interrupts.

Mit

$baud = 9600
$hwstack = 32
$swstack = 32
$framesize = 32

Bist du erst mal auf der sicheren Seite.

Mit freundlichen Grüßen
Fred

demmy
10.11.2015, 19:49
Hallo zusammen,

ich wollte euch mal eben schnell auf den aktuellen Stand bringen. Ich habe den Fehler gefunden und ich konnte es selber nicht glauben als ich es gesehen habe.
Ich habe tatsächlich bei einem UART interrupt vergessen die Register zu sichern. Kein wunder das der µC da irgendwo rumgesprungen ist sobald was über die Serielle riengekommen ist.

In Bascom gibt es die Möglichkeit bei der Deklaration der Interruptverzweigung mit anzugeben ob beim Springen in das Interrupt die Register gesichert werden sollen.

Bsp.:
On Int0 Label2 Nosave 'jump to label2 on INT0

Der Zusatz "Nosave" war das Problem. Hier die Erklärung aus der Bascom Hilfe.
When you specify NOSAVE, no registers are saved and restored in the interrupt routine. So when you use this option make sure to save and restore all used registers.

Ich habe das Nosave im Code entfernt und jetzt läuft alles einwandfrei. Das war wohl ein klassicher copy / paste Fehler von mir.

Aber vielen vielen danke an alle die sich mit dem Problem beschäftigt haben. :)

malthy
10.11.2015, 22:50
Das war wohl ein klassicher copy / paste Fehler von mir

Hättest Du direkt Deinen Code gepostet, hätten die meisten (Bascom-kundigen) das Problem sofort erkannt ... ;-)