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?
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.
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 :-)
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
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. ;-)
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?
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
"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
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.
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. :-)
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.
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
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
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.