Hallo, Ich programmiere einen AT89C51RD2 in Bascom wollte wissen ob es die Möglichkeit gibt die Rücksprungadresse des Interrupts zu ändern, um eine definierte Adresse nach Abarbeitung der Interrupt-Routine festzulegen ? Danke schon mal im vorraus !! MFG Tim
Ja, einfach die letzen beiden Werte vom Stack löschen und die neue Adresse auf den Stack schreiben. In Assembler eine Kleinigkeit, aber in Bascom keine Ahnung...
Wurde hier schon öfters diskutiert. Das ist Teufelszeug, Finger weg !!! Du machst Dir damit das Programmieren nur unnötig kompliziert und eine Erweiterung von Programmen fast unmöglich, falls du es wirklich mal stabil zum Laufen kriegen solltest. Solche Fragen kommen auch nur ausschließlich von Anfängern, weil sie sich der Bedeutung des Wortes "Interrupt" nicht im klaren sind. Profis benutzen einen Programmablaufplan um ihr Programm besser zu strukturieren, damit solcher Unfug nicht benötigt wird. Für genauere Erklärungen lies die alten Threads. Peter
> Das ist Teufelszeug, Finger weg !!!
Wird das nicht für preemptive multithreading benötigt?
(Ok, das ist nix mit was sich ein Anfänger antun wird).
Hi Chris, preemtives Multithreading in Basic auf einem Microcontroller ;-)
es gibt schon Situationen wo man das brauchen kann... Aber: Leute die sowas brauchen fragen nicht, weil Sie wissen wie das geht! Ansonsten hat Peter recht das ist Teufelszeug. In Basic sowiso. Thomas
> preemtives Multithreading in Basic auf einem Microcontroller ;-)
Wüsste nichts, was dagegen spricht (solange Basic Funktionszeiger,
Stackveränderungen bzw. inline-assembler beherrscht [was ich nicht
weiß]). ;-)
Wär natürlich IMHO ziemlich übertrieben sowas zu versuchen; ich wollte
eben nur ein Beispiel nennen, bei dem eine Änderung der
Rücksprungadresse bei einem Interrupt doch sinnvoll ist.
@peter dannegger Danke, dass du mich als Anfänger bezeichnest... Ob man es macht hat nichts damit zu tun wie gut man programmieren kann. Wenn man genau weiß was man macht, kann man damit ordentlich Zeit sparen, vor allem wenn irgendwas extrem schnell z.B. auf einen Interrupt reagieren soll und anschließend sofort an eine bestimmte Stelle im Programm springen soll. Die warscheinlichkeit, dass es in Bascom daneben geht ist allerdings um ein Vielfaches höher als in Assembler.
>kann man damit ordentlich Zeit >sparen, vor allem wenn irgendwas extrem schnell z.B. auf einen >Interrupt reagieren soll und anschließend sofort an eine bestimmte >Stelle im Programm springen soll. Ohne Dir auf den Schlips treten zu wollen, aber sowas riecht für mich immer stark nach nem Fehler im Programm-Design. Warum soll man den Code, der an dieser "bestimmten Stelle" steht, nicht einfach im Interrupt-Handler selbst unterbringen können?
Ganze einfach: Weil im Interrup kein anderer Interrupt aufgerufen werden kann. Es geht z.B. um eine Synchronisierung. Sobald der Sync Impuls ankommt, muss der uC sofort zurück an eine bestimmte Stelle im Hauptprogramm. Das ganze ist eine Grafikkarte mit TVout, und da zählt jeder Prozessortakt. Es würde daher viel zu lange dauern, bis der uC irgendwann mal ein in der Interrrupt Routine gesetzes Bit abfragt und erst dann an die gewünschte Stelle springt. Falls jemand eine gute Alternative kennt, wie man möglichst schnell, aber ohne unterbrochen ein Bit abzufragen bei einem Interrupt an eine bestimmte Stelle Springen kann, dann bin ich gerne für Alternativen offen...
"Danke, dass du mich als Anfänger bezeichnest..." Lies bitte die alten Threads, bisher waren es 100% Anfänger, die danach gefragt hatten. Es ist mir jedenfalls so gegangen, daß man mit zunehmender Programmiererfahrung solche Trickserei einfach nicht mehr nötig hat. Irgendwann ändert sich nämlich der Programmierstil vom chaotischen Hin- und Herspringen zum Denken in Funktionen und Modulen mit je genau einem Start- und Endpunkt. Ich hatte zu Anfang meiner Programmierzeit selber mit sowas gespielt, aber schnell eingesehen, daß man so keine größeren Projekte machen kann, da der Programmfluß damit den Bach runtergeht. Interrupt können eben überall unterbrechen, auch in Unterfunktionen oder anderen Interrupts. Sie werden sich also, wenn Du sie abschießt, genau den Punkt im Programmablauf aussuchen, wo am meisten Schaden entsteht (Variablen zerstört, Stack nicht ausbalanciert, Speicher belegt, Portpins falsch gesetzt usw.). Und bei mehreren Tasks und Interrupts ist es eh unmöglich, alle möglichen Konstellationen zu berücksichtigen. Du schränkst Dich damit also nur selber in Deinen Programmiermöglichkeiten drastisch ein und verdammst Deine CPU dazu, auf Sparflamme zu arbeiten, weitab ihrer realen Leistungsfähigkeit. Peter
"Falls jemand eine gute Alternative kennt,..." Dazu müßte man das Programm sehen. Eine Generallösung gibt es nicht. Es kommt auf die richtige Balance an, was im Interrupt und was im Main gemacht wird. Auch könnte es sinnvoll sein, mehrere Interruptprioritäten zu verwenden. Peter
Interruptprioritäten ? Sowas hat der AVR nicht... Was soll ich viel zum Programm sagen: Es gibt keine calls, keine weiteren Interrupts sondern nur die eine Main Schleife die andauernd läuft. Kommt ein externes H oder VSync Signal müssen alle Adresszähler resettet werden und die Datenübertragung von neuem Beginnen. Ich muss also an eine entsprechende Stelle springen. Und sowas geht am einfachsten und schnellsten mit der Stackmanipulation. Bisher hatte ich damit auch keine Probleme, es läuft alles einwandfrei. In riesigen Programmen mit tausenden Unterprogrammen würde ich sowas nie machen, da hier die Gefahr viel zu groß ist, dass es Probleme mit einem anderen Unterprogramm oder ähnliches gibt.
Der AVR hat zwar keine Hardwareprioritäten, so etwas lässt sich aber in Software nachbilden. Das ist im Prinzip kein Problem. Siehe auch andere Beiträge hier im Forum. Ich selber nutze das auch häufig, weil es mir die Programmierung sehr erleichtert.
>>Der AVR hat zwar keine Hardwareprioritäten, so etwas lässt sich >>aber in Software nachbilden. Seit wann haben die AVR's keine Hardwarepriorität bei den Interrupts??? The lowest addresses in the Program memory space are by default defined as theReset and Interrupt Vectors. The complete list of Vectors is shown in Interrupts onpage 44. The list also determines the priority levels of the different interrupts. The lower the address the higher is the priority level. RESET has the highest priority, and next isINT0 the External Interrupt Request 0. Peter
Gemeint ist nicht die Priorität beim gelichzeitigen Eintreffen der auslösenden Ereignisse, sondern Interruptlevel - sprich verschiedene Prioritätslevel, so dass Interrupts höherer Priorität Interrupts niedrigerer Priorität unterbrechen können, aber nicht umgekehrt. So etwas haben die meisten MCs, so z.B. die 8051er, die mindestens 2 Level, aber durchaus auch 4 haben. Das erleichtert die Programmierung ungemein, falls mehrere Aufgaben parallel zu erledigen sind.
Interrupts mit niedriger Priorität bekommen gleich nach dem Einsprung SREG |= 128; Damit ist diese Routine unterbrechbar von anderen Interrupts. MW
Womit der dann allerdings von allen andere Interrupts unterbrechbar ist, nicht nur von denen höherer Priorität. Was so nebenbei den Stack unkalkulierbar macht, weil's kein prinzipielles Limit gibt. Nein, wenn man sowas brauch und es sowas nicht im Interrupt-System integriert ist, dann hilft nur, die Interrupts an der Quelle zu maskieren. Aufwendig und arg unübersichtlich.
Es ist sicherlich richtig, dass das unübersichtlich ist und auch Performance kostet - ich würde das lieber mit den 8051ern machen - allerdings gibt es unter den "bezahlbaren" MCs nur die AVRs, die einen so schönen und ausgereiften kostenlosen C-Compiler wie den GCC haben. Für Hobbyisten oder Diplomarbeiter ist das schon ein entscheidendes Argument, so dass ich letztlich auch gewechselt bin (vom 8051er mit SDCC).
@Benedikt "Interruptprioritäten ? Sowas hat der AVR nicht..." ich war immer noch der Meinung, es ginge um die Originalfrage (AT89C51RD2 in Bascom). Man schaut ja nicht ständig auf den Autor. Hatte mich schon gewundert, eine Videoausgabe in Bascom. Hatte ich also doch recht, die, die danach fragen sind 100% Anfänger. Warum Du Dich dann aber dazu gezählt hast, wundert mich. Ich denke mal, daß Du ja gar keine Probleme mit Deinem Programm hast, die man hier weiter erörtern müßte. Es gibt natürlich immer Ausnahmen von der Regel. Ich hatte gerade auch ein Programm, welche sauschnell sein mußte. Da wird alles im Polling gemacht, weil selbst die Interrupteintrittszeit zu lang gewesen wäre. Ein ATTiny26 ersetzt einen CPLD. Plötzlich mit einer neuen Charge hat dieser CPLD manchmal gesponnen, warscheinlich irgendwelche metastabilen Zustände. Da ich den CPLD nicht kannte und auch nicht das Entwicklungstool und der Hersteller sich auch nicht wieder gemeldet hat, hab ich kurzerhand den CPLD rausgeschmissen. Ich hatte erst Zweifel, mit Interrupts hätts auch nie geklappt (10 Zyklen Overhead), die Pins wurden daher nur mit (SBIS+RJMP) getestet (2/3 Zyklen Overhead). Und auch nirgends RCALL+RET, sondern immer nur RJMP. Peter
Ich zähle mich nicht zu den Anfängern, und mein Programm läuft problemlos mit den Stackmanipulationen, mich hat nur die Aussage von peter dannegger gestört: "Solche Fragen kommen auch nur ausschließlich von Anfängern, weil sie sich der Bedeutung des Wortes "Interrupt" nicht im klaren sind. Profis benutzen einen Programmablaufplan um ihr Programm besser zu strukturieren, damit solcher Unfug nicht benötigt wird." Ich würde sowas nicht als Unfug bezeichnen, sondern eher als dirty-trick.
@Benedikt "mich hat nur die Aussage von peter dannegger gestört:..." Nochmal: Du warst ja nicht der Fragesteller, also stimmt doch meine Aussage. Und so ein "dirty-trick" geht auch beim Profi nicht in Bascom oder C, d.h. da ist und bleibt es Unfug. Nach Assembler war ja garnicht gefragt. Peter
"Nach Assembler war ja garnicht gefragt." OK, damit bin ich zufrieden...
Hi Benedikt. Um einen möglichen Ausweg aufzuzeigen, vielleicht hilft folgendes: Wenn wir von PAL ausgehen, ist es doch ein leichtes, einen LM1881 mit nem Quarzoszi und nem Zähler zu verbinden. Der LM1881 separiert die Sync-Impulse, liefert sie an den Reset- Eingang des Zählers. Da der Zähler mit "Pixelclock" läuft, kannst du so auf dein Video-RAM zugreifen. Der LM1881 kann dir dann nen Interrupt liefern, der den "Strahlrücklauf" einleitet und dir dann die Möglichkeit und Zeit gibt, den Video-RAM neu zu beschreiben (sind immerhin ein paar ms) .. Wenn du es nur in s/w machen würdest, kannst du nun direkt den Zähler mit dem RAM verbinden und nach kleiner Pegelwandlung und hinzufügen der Sync-Impulse als BAS abgreifen. Für Farbe brauchste halt die Phasenwandlung und mehr RAM oder noch mehr RAM und machst halt RGB (evtl anschliessend RGB->FBAS).. Der Video-Generator läuft damit immer und gibt den RAM-Inhalt pixel für pixel aus, und wenn gerade mal nix zu tun ist, erlaubt er dem Prozessor, den RAM mit neuen Daten zu füllen. Sicherlich sind da keine extremen Transfers zu erwarten, aber für PAL reicht es allemal. Der Prozessor wird "Slave" und sendet nur daten, wenn der RAM nicht gerade vom Video-Generator unter beschlag ist. Sowas hab ich mal vor 2 Jahren aufgebaut, läuft wunderbar und entlastet die CPU-Rechenzeit enorm. Ich nutzte einen 8515 bei 8 MHz, um etwas Rechenzeit mehr zu haben gegenüber dem PAL Signal. Farbe hab ich mal im Konzept gebastelt, aber nie wirklich vertieft (wozu auch, ich brauchte nur s/w). Entschuldigt, das ich nicht auf die Interrupt-Frage eingehe, ich löse manches lieber in Hardware, wo es sich ergibt, um meine Softwaremängel auszugleichen lach Spass beiseite, meine persönliche Meinung ist, das ein Video-Generator sich an die Standards halten sollte, und die sind nunmal leichter in Hardware als in Software nachbildbar .. und vor allem auch kalibrierbarer ;) Hoffe zur allgemeinen Verwirrung beigetragen zu haben. Tim
Bin ich hier im falschen Film?? Ich wüsste nicht, dass Benedikt ein Problem mit seinem Programm hat... Der Fragesteller ist doch Tim. ...
@...HanneS... Ich habe kein Problem mit meinem Programm, aber alle versuchen mir eines unterzuschieben... @Tim O. Hast du zufällig irgendwelche Unterlagen dazu ? Mich würde vor allem der Adresszähler und die Koordination zwischen den beiden Speicherzgriffen interessieren.
Benedikt: Sicher habe ich.. Schau mal unter der folgenden Adresse, ob du was passendes findest, was du als Grundlage nutzen kannst.. http://members.lycos.nl/PI6ATV/software.htm Gruss, Tim
Grundlage ist nicht mein Problem, meistens scheitert es z.B. daran wie ich wärend dem H/VSync den Speicher freigeben kann, so dass der uC darauf zugreifen kann. Auf der Seite habe ich nicht wirklich viel brauchbares gefunden.
Schau dir mal vtgen2.gif auf vtgen-hardware.zip an, das ist nen Videotext-Generator.. zwar auf PC-Basis, aber anstelle des ISA-Busses den uC denken, fertig ;) Klar, das Design ist nur auf ein paar Zeilen aufgebaut, aber das Prinzip ist damit verdeutlicht. Tim
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.