www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik UART und ADC-Interrupt


Autor: Olaf Fran (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Habe folgendes Problem mit einem ATmega16:

In meinem Programm gibts einen Main-Loop, der den UART pollt. Dazu
läuft im Hintergund der ADC, der einen Interrupt auslöst, wenn er mit
der Conversion fertig ist. Die Interrupt-Routine setzt dann einen neuen
Channel und startet eine neue Conversion.

Das Problem ist, daß wenn ich diesen Interrupt aktiviert habe, ca.
jedes 6. byte vom UART nicht korrekt ausgelesen wird. Kommt dann nur
irgendwelcher Blödsinn raus, den auf der anderen Seite nie jemand
gesendet hat. Ist der Interrupt aus, läuft alles bestens. Fällt dazu
jemandem was ein? Kann doch wohl nicht so timingkritisch sein, die
UART-Geschichte, oder doch?

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Poste den Quellcode!
Olga hat gerade Urlaub!

Autor: Olaf Fran (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
I'm sorry. Hatte ich meiner Verzweiflung auf eine "Ach ja, das ist ein
typischer Anfängerfehler"-Antwort gehofft. ;-)

Hier ist ein aufs Wesentliche reduzierter Source, mit dem sich der
Fehler nachvollziehen lässt. Kommentiert man die Zeilen zwischen den
"blah" Kommentaren aus, läuft alles bestens.

BTW, der Takt ist bei mir 3.69 MHz, die Baudrate demnach 57600.

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Solche Probleme hat man immer, wenn man im Interrupt das Statusregister
nicht rettet und wiederherstellt. Glück hast Du noch, da sich der
Fehler gleich gezeigt hat :-)

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
man sollte SREG zwar immer sichern, aber in diesem Fall ist es
ausnamsweise unschuldig, da im main garnicht benutzt.

Und richtiger sollte es wohl

sbr r16, 1<<adsc

heißen.


Das Problem dürfte vielmehr sein, daß ständig gesendet wird, d.h. auch
wenn nichts empfangen wurde.
Dadurch reichen schon kleinste Programmverzögerungen aus, um Bytes
doppelt zu senden, klar daß dann dafür andere Bytes geopfert werden
müssen.


Peter

Autor: Olaf Fran (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmmm.

Wie ist das mit dem ständigen senden gemeint? Die Empfangsroutine
wartet doch, bis ein Zeichen da ist. Danach wird erst die Senderoutine
aufgerufen. Klappt ja auch, solange der Interrupt aus ist.

Ich schau mal in die Specs, was es mit dem SREG auf sich hat. Danke für
den Tip. ;-)

Autor: Olaf Fran (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi.

Hab gerade mal versucht, in int_adc das sreg zu sichern ('in r20,
sreg' am anfang und 'out sreg, r20' vor dem reti), hat aber leider
auch nicht zum Erfolg geführt. Hat vielleicht noch jemand eine Idee?

Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo Olaf,

ich würde den adc interrupt abschalten, wenn ein Zeichen empfangen
wurde und erst nachdem alle Zeichen über den Uart empfangen worden sind
wieder den ADC interrupt akitivieren....
Hatte mal das selbe Problem und hab's nicht anders lösen können, wobei
ich jetzt nicht unbedingt der Profi Programmierer bin....

vielleicht klappt's ja

Gruß

Sven

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Wie ist das mit dem ständigen senden gemeint?"

War ein Irrtum meinerseits.


Aber ganz ohne Empfangs-/Sendepuffer dürfte es normal sein, daß Zeichen
verloren gehen. Die Senderoutine frißt Dir dann die ganze Zeit auf.
Dein Quarz muß nur leicht langsamer sein als der der Gegenstelle und Du
empfängst schneller als Du senden kannst.

Jede kleine Mehrbelastung z.B. durch einen Timerinterrupt dürfte die
gleiche Wirkung haben.


Peter

Autor: Olaf Fran (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Theoretisch schon. Bei dem Source, den ich reingestellt hab, reicht es
aber auch, in einem Terminalprogramm ab und an mal eine Taste zu
drücken, um den Fehler auszulösen. Müssen keine irrsinnigen Datenströme
sein.

Die fertige Anwendung würde auch so aussehen, daß erst ein Befehl
empfangen wird, der Controller antwortet und dann kommen erst die
nächsten Daten. Wäre also in Ordnung, wenn er da eine Weile in der
Senderoutine verbringt, weil währenddessen nichts kommen kann.

Autor: Olaf Fran (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sven,

Danke für den Tip, aber dann könnte ich den ADC auch gleich pollen.
Wäre dann in meiner Anwendung die sinnvollere Alternative. Aber da
Interrupts irgendwie lässiger sind, möcht ich die lieber ans laufen
bekommen. :-)

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wie wäre es denn beides über Interrupts auszuführen?
Dann würde der Controller 95% der Zeit nix tun, aber ziemlich sicher
auf alles reagieren, was da so anliegt.
Die Idee von Peter würde ich immer realisieren, sprich einen
Empfangspuffer per Interrupt füllen und dann in der Hauptschleife
auslesen.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenns schon bei einem Byte auftritt, dann muß da was faul sein.

Stimmt denn der Interruptvektor ?
Warum nimmst Du nicht ".org Int-Name" zum Zuweisen des richtigen
Vektors ?

Auch solltest Du ruhig kommentieren und Konstanten verstehbar (Namen
benutzen) hinschreiben.


Peter

Autor: Olaf Fran (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi.

Ich bin ab gleich für ein paar Tage ausser Landes, mal über andere
Sachen nachdenken. Vielleicht kommt mir da ja zufällig die rettende
Idee (oder jemand anders hat noch zufällig eine?). Ich probier später
noch mal, das Ding mit Buffer und Interrupt-gesteuertem Empfang ans
Laufen zu bekommen.

Der Vektor für den ADC-Int in meinem Code müsste stimmen.

Übrigens bitte nicht dieses aus dem Kontext gerissene Code-Snippet als
repräsentativ für meinen Stil betrachten. Das war nur ein Spielzeug. Im
echten Code sind schon Kommentare und Konstanten drin. Wenn ich auch
nicht einer von diesen Wahnsinnigen bin, die jedem Register ein Alias
ala Variablenname verpassen. ;-)

Danke für die Hilfe bisher.

MfG,
Olaf

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!
Ich habe momentan blos das pdf vom Mega163, aber da hat ein Int-Vekt.
16 Bit! Ist das beim M16 nicht auch so?

MFG Uwe

Autor: Thorsten Witt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
nimm den Tip von Peter an und schreib vor jedem IRQ-Vektor die Adresse
mittels ".org Int-Name". Ich verwende auch den Mega16 und hatte das
gleiche Problem. Nachdem ich vor jedem verwendetem IRQ-Vektor das
entsprechende ".org" geschrieben habe, funktioniert es.

Viel Erfolg

Thorsten

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.