Hallo, Falls mehrere Interruptquellen beim PIC verwendet werden, sieht das Vorgehen wie folgt aus: An Programmadresse 4 (Int-Vektor) steht folgendes: movwf w_temp swapf STATUS,w bcf STATUS, RP0 ; status_temp in Bank 0 movwf status_temp Hier wird der Inhalt Statusregisters und des Arbeitsregisters aus dem "Hauptprogramm" gesichert. Anschließend werden die verschiedenen Interruptquellen geprüft (-> wo kam der Interrupt her), indem die Flags der zugelassenen Interruptregister geprüft werden. Am Ende werden die Inhalte der Register wieder zurück gesichert. swapf status_temp,w movwf STATUS swapf w_temp,f swapf w_temp,w retfie Soweit, so gut ... Offenbar hab' ich aktuell ein Problem wenn innerhalb der Int-Routine die Inhalte des Status-Registers verändert werden (Z-Flag, etc.). Solange nur eine Interruptquelle existiert ist es noch kein Problem, wohl aber bei zwei oder mehreren. Gibt es dafür eine clevere und einfach Abhilfe oder bleibt tatsächlich nur über, für jede Interruptquelle eine ähnliche Sicherung und Rücksicherung anzufertigen, wie für das "Hauptprogramm"? Thomas
Hallo Thomas Ich verstehe nicht was Du genau fragen willst. Jeder Interrupt sollte doch in sich abgeschlossen sein und nicht den (unveränderten) Inhalt des Status-Reg beim nächsten Aufruf wieder benötigen. Oder setzt Du während ein Int bearbeitet wird wieder das GIE Flag und ein zweiter Int kann dazwischenhauen? Dann ist natürlich wieder die Sicherung von allen benutzten Registern in einem anderen Zwischenspeicher erforderlich (müsste man wohl mit einem Zählregister feststellen in welcher Interruptebene man gerade steckt). Dieter
Hallo Dieter, Also versteh' ich's richtig, dass durch Aufrufen der INT-Routine sowieso alle weiteren INTs abgeschaltet sind? Das würde das GAnze wesentlich vereinfachen und das Problem liegt wo anders. Kurze Erklärung: Falls TMR0 überläuft, erzeugt er ca. alle 0,1 s einen Interrupt und arbeitet eine relativ lange Routine ab. Wenn TMR1 überläuft, soll er lediglich alle 0,52s einen Interrupt erzeugen. Die aufgerufene Routine soll dann diese 0,52s "vervielfachen" und eine LED zum Blinken, bzw. ein Relais zum anziehen bewegen. Beides voneinander unabhängig funktioniert einwandfrei. Wird jedoch das Ereignis aus TMR0 aufgerufen, während TMR1 überläuft, gibt's Probleme, die LED geht nicht aus, bzw. das Relais fällt nicht ab. Vielleicht ist auch die "Vervielfachung" der 0,52s nicht clever genug gelöst. Mir kommt es vor, als bekäme der PIC nicht mit, wenn einer der Zähler auf 0 geht und zählt dann noch mal von 255 runter. Von der gemessenen Zeit her sieht es ganz danach aus. Siehe Anhang. Gestartet wird die Routine mit movlf Z1,24 movlf Z2,24 movlf Z3,24 movlf Z4,24 movlf Z5,24 movlf T1CON,00110001b ; Timer1 einschalten / starten Ziel der Übung ist dann folgender Rhythmus an PORTB,7: 12s an, 12 aus, 12s an, 12s an, aus Eine reine Zählschleife übrigens mit DECFSZ funktioniert übrigens deutlcih zu wacklig, dafür springt der PIC viel zu oft über TMR0 in seine lange INT-Routine. Bin für jeden Tipp dankbar, Thomas
Hallo Thomas, 1. Tritt ein Interrupt auf, sind bis zum 'retfi' alle weiteren Interrupts gesperrt. Tritt ein weitere Interrupt auf, wird nach 'retfi' sofort wieder in die ISR gesprungen. 2. Du kannst während eines Interrupts weitere zulassen (GIE-Flag). Davon ist allerdings abzuraten. 3. Bedenke immer: Vieles mit, aber nur Weniges in Interrupts machen. Es scheint mir, deine ISR's sind zu lang (zeitmäßig gesehen). In der Regel sind alle Timingaufgaben mit nur einem Timer zu lösen, der z. B. alle 100ms einen Interrupt auslöst und eine Variable "hochzählt" (mehr sollte in der Timer-ISR nicht passieren!). Hieraus können alle möglichen Zeiten generiert und Ereignisse (LED an/aus) ausgelöst werden. CB
Hallo CB, Danke für die Tipps. Also wäre Dein Ansatz das Timing Intervall des T1 kürzer zu setzen, als das kürzeste Intervall des T0 (T0 hat keine feste Zeitkonstante) und daraus die 0,5 Sekunden abzuleiten? Als zweiter Ansatz könnte dann das Auseinanderpflücken der TMR0-Routine kommen. Wird aber richtig fies - ist eine übernommene Routine. Eignet sich Deiner Meinung nach die TMR1-Routine, oder gibt's auch da noch Optimierungsmöglichkeiten? Kurz noch: Warum werden P1 ... P5 nicht nochmal in Schleifen gepackt - die Zeiten können variieren (sind nicht immer 12s) und zum Testen wollte ich es etwas übersichtlicher halten. Thomas
Hi ! Schau Dir erstmal das an: http://www.fernando-heitor.de/index.php?option=com_jd-wiki&Itemid=85&id=mikrocontroller:interrupts Bei den 18Fxxx PICs haben die Interruptquellen eine Prioritaet. Damit ist es moeglich, dass die Interruptquellen mit hoeerer Prioritaet einen Interrupt mit einer niedrigeren Prioritaet unterbrechen. Allerdings sollte man das benutzen nur, wenn es wirklich unbedingt sein muss unda man weiss genau, was man tut. Das heisst alle Interruptbehandlugsroutinen, die gleichzeitig auftreten koennen, muessen reentrant sein. In der 16F Familie gibt es diese Probleme nicht, da werden die Interrupts, auch wenn sie gleichzeitih auftreten sequentiell bearbeitet. In einem Interrupt-Aufruf koennen zwar gleichzeitig zwei Interrupt-Flags gleihzeitig gesetzt werden, aber eine Unterbrechung der Interruptbehandlungsroutine finden nicht statt. Man kann es durch Einschalten des GIE Flags "ausprovozieren" aber das mach wenig Sinn, wie andere schon erklaert haben. Gruss, Aleksandar
Aleksandar wrote: > Das heisst alle > Interruptbehandlugsroutinen, die gleichzeitig auftreten koennen, muessen > reentrant sein. Nein, das heißt es nicht. Jeder Interrupt hat entweder die hohe oder niedrige Priorität und kann sich daher nicht selbst unterbrechen. Er muß also nur die verwendeten Register sichern, wie es auch ohne Prioritäten der Fall ist. Die 8051-er haben sogar bis zu 4 Prioritäten und das funktioniert völlig problemlos und störungsfrei. Allerdings haben sie auch getrennte Interruptvektoren. Peter
Hi Peter! >> Das heisst alle >> Interruptbehandlugsroutinen, die gleichzeitig auftreten koennen, muessen >> reentrant sein. >Nein, das heißt es nicht. Du hast Recht, ich habe mich nicht ganz genau ausgedruckt - die muessen sich nur bei der gegenseitigen Unterbrechung nicht beeinflussen. "gegenseitig reentrant" waere vl. genauer ;) >Er muß also nur die verwendeten Register sichern, wie es auch ohne >Prioritäten der Fall ist. Genau, aber wenn zB zwei Interrupts gleichzeitig auftreten koennen, dann muessen zwei Sets der Variablen fuer "Ablage" definiert und benutzt werden - konkret bei PIC waeren das zwei mal mindestens W und STATUS. Ein Nachteil bei PIC 16 ist, dass es keine PUSH/POP Befehle gibt, man muss immer selbst Variablen zum Ablagern definieren. Gruss, Aleks
Aleksandar wrote: > Ein Nachteil bei PIC 16 ist, dass es keine PUSH/POP Befehle gibt, man > muss immer selbst Variablen zum Ablagern definieren. Das stimmt, daran habe ich nicht gedacht. Bei Architekturen mit PUSH/POP hat es der Assemblerprogrammierer wesentlich einfacher. Peter
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.