UART und ADC-Interrupt

Gast #66577
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?
Gast #66579
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.
Angehängte Dateien:
Gast #66580
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 :-)
#66581
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
Gast #66582
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. ;-)
Gast #66583
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?
Gast #66584
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
#66585
"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
Gast #66586
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.
Gast #66587
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. :-)
Gast #66588
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.
#66589
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
Gast #66590
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
Gast #66592
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

Eine eigene Frage? Dieser Thread ist über 22 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.