Hallo zusammen,
ich hab hier einen PIC18F4520 und benutze den C18-Compiler.
Für die serielle Kommunikation mit dem PC möchte ich nun Interrupts
verwenden. Das funktioniert, wenn ich IPEN auf 0 setze und dann einen
einen Vektor mit Adresse 0x08 verwende.
Ich möchte aber jetzt unterschiedliche Prioritäten ermöglichen und setze
IPEN auf 1; sowie auch GIEL und GIEH.
Dazu Fragen...
Wo im Datenblatt finde ich eine Angabe dazu ob meine Interrupt-Quelle
low- oder high-priority hat?! oder muss ich das für alle selbst
zuweisen? wenn ja, dann weiß ich ebenfalls nicht wo :/
wenn ich mein programm teste stelle ich fest, dass ich wohl für den
USART die high-ISR benötige...
Außerdem verwirrt mich, dass es auch ohne die folgende mittlere Zeile
tut. Wird diese nicht benötigt?
1
#pragma code high_vector = 0x08
2
//#pragma interruptlow ISR_high // NICHT BENÖTIGT?
3
voidhigh_interrupt(void){..}
Ist es die gängige Art bei diesem Controller dass man innerhalb der ISR
erst prüft von wem der Interrupt ausgelöst wurde? Gibt es also wirklich
insgesamt nur 2 Interrupt-Routinen?
Hoffentlich könnt ihr mir ein bisschen auf die Sprünge helfen :)
Viele Grüße, Mirco
Wenn ein Interrupt auftritt, dann springt die Programmausführung an eine
bestimmte Stelle im Programmspeicher. Diese Stellen sind festgelegt und
können nicht geändert werden:
Danke, aber das ist alles in Assembler, hat nichts mit C18 zu tun und
ist außerdem der falsche Controller?!
Ist beispielsweise für den UART standardmäßig eine high-priority
implementiert? Kann ich das irgendwo nachlesen?
Grüße
Mirco H. schrieb:
> Ist es die gängige Art bei diesem Controller dass man innerhalb der ISR> erst prüft von wem der Interrupt ausgelöst wurde? Gibt es also wirklich> insgesamt nur 2 Interrupt-Routinen?
Ja, das ist (nur) beim PIC so.
Das ist ein ziemlicher Pferdefuß der PICs.
Andere MCs haben die Interruptvektoren nach Quelle verschieden, da kann
man gleich loslegen, ohne was testen zu müssen.
Auch muß der Compiler dann nur die benötigten Register sichern.
Peter
Die Priorität der einzelnen Interrupts kanns Du mit jeweils einem Bit in
den IPR-, INTCON2- oder INTCON3-Registern einstellen. Nur nicht für den
INT0, der ist immer high-priority.
Und ja, es gibt nur einen Vektor für high- und einen für low-interrupts.
Dort muß man dann per Software auseinanderdröseln, wer den Interrupt
ausgelöst hat.
Es gibt für jeden Interrupt 3 Register:
PIR - hier sind die Interrupt-Flags drin, wenn der Interrupt ausgelöst
hat
IPR - hier legst du die Priority fest (0 = high und 1 = low, oder
umgekehrt, weiß ich nicht aus dem Kopf)
PIE - damit kannst du die die gewünschten Interrupts
aktivieren/deaktivieren
Low-Priority-Interrupts können von High-Priority-Interrupts unterbrochen
werden.
High-Priority-Interrupts können NICHT unterbrochen werden.
Verwendung von Prioritäten musst du aber erst mit RCON.IPEN = 1
festlegen.
Der Einsprungsvektor für High-Interrupts ist 0x0008h und der für
Low-Interrupts ist 0x0018h
Peter Dannegger schrieb:
> Mirco H. schrieb:>> Ist es die gängige Art bei diesem Controller dass man innerhalb der ISR>> erst prüft von wem der Interrupt ausgelöst wurde? Gibt es also wirklich>> insgesamt nur 2 Interrupt-Routinen?>> Ja, das ist (nur) beim PIC so.
Ich habe wieder was gelernt.
Was es nicht alles gibt?
Ahh, danke. Das klappt jetzt alles mit high und low :)
Und auch wenn es wohl eine Umstellung bedeutet kann man sich sicher an
die nur zwei ISR gewöhnen..
Könnt ihr mir auch noch sagen wieso die Zeile:
1
#pragma interruptlow ISR_low
scheinbar völlig unnötig ist? Funktioniert auch wenn sie an der gleichen
stelle ein 'interrupt' statt 'interruptlow' hat oder sogar auch wenn sie
auskommentiert ist..
Im C18-compiler-Handbuch und in allen Bsp. im Internet ist die Zeile
immer vorhanden... Wird sie wo anders noch benötigt?
Grüße
Diese Zeile bewirkt ein automatisches Context-Saving. Also da kümmert
sich dann der Compiler drum.
bei "#pragma interrupt" kommen die Inhalte aus WREG, BSR und STATUS in
sogennante Shadow-Register.
"pragma interruptlow" hingegen, legt die Inhalte auf den Softwarestack.
Ist dann eins von beiden möglicherweise als Standard festgelegt, so dass
ich die Zeile nicht unbedingt schreiben muss? Funktionieren tut es bei
mir nämlich auch ohne. Danke für die verständliche Formulierung!
Grüße
Peter Dannegger schrieb:
> Ja, das ist (nur) beim PIC so.> Das ist ein ziemlicher Pferdefuß der PICs.> Andere MCs haben die Interruptvektoren nach Quelle verschieden, da kann> man gleich loslegen, ohne was testen zu müssen.
Kleine Korrektur: Das ist bei allen 8-Bit PIC so. Die anderen Familien
sind da moderner ausgerüstet.
Ein wirklich schlimmer Pferdefuss ist es meiner Meinung nach nicht, weil
auch mit vielen separaten Interruptvektoren die ISR nicht gleichzeitig
abgearbeitet werden können. Die Latenz beim Eintritt in eine spezifische
ISR ist da natürlich etwas geringer, ob man von diesem Vorteil was hat
ist aber sehr von der konkreten Anwendung abhängig.
Grüße,
Edson
Mirco H. schrieb:
> Ist dann eins von beiden möglicherweise als Standard festgelegt, so dass> ich die Zeile nicht unbedingt schreiben muss? Funktionieren tut es bei> mir nämlich auch ohne. Danke für die verständliche Formulierung!>> Grüße
Ist mir nicht bekannt. Vergleich doch mal den assemblierten Code der
beiden Varianten.
Sicher kann es auch ohne Context-Saving funktionieren. Aber irgendwann
kommt der Punkt, wo du einen Fehler suchst, und dir nicht erklären
kannst, wo der her kommt. Zum Beispiel Vorzeichen-/Rechenfehler.
Interrupt nach der Berechnung:
0. Register 1 und 2 rücksetzen
1. Berechnung mit Register 1 und 2, Schritt 1
2. Berechnung mit Register 1 und 3, Schritt 2
3. Interrupt verändert Register 1
das geht so.
aber bei Interrupt während der Berechnung:
0. Register 1 und 2 rücksetzen
1. Berechnung mit Register 1 und 2, Schritt 1
3. Interrupt verändert Register 1
2. Berechnung mit Register 1 und 3, Schritt 2
kommt Mist raus, weil das Register 1 vom Interrupt verändert wird.
Tritt der Interrupt WÄHREND einer Berechnung auf, kann der dir den
aktuellen Registerinhalt zerschießen.
Der Micha schrieb:
> bei "#pragma interrupt" kommen die Inhalte aus WREG, BSR und STATUS in> sogennante Shadow-Register.> "pragma interruptlow" hingegen, legt die Inhalte auf den Softwarestack.
Das heißt im Klartext, "pragma interruptlow" ist für Interrupts, die
selber unterbrechbar sein müssen, also "low priority".
Stack ist sicherer, aber wohl langsamer als Register.
Peter