Hab im C-Compiler für den PIC folgendes gelesen:
As there is a maximum of one interrupt vector in the midrange PIC
series, only one interrupt
function may be defined. The interrupt vector will automatically be set
to point to this function.
Heisst das ich kann nur eine C-Funktion per Interrupt aufrufen? Weiss
jemand wo ich die jeweiligen Interrupt-Nummern finde (diejenige für die
C-Funktion)
Zitat :
Die PIC16 verfügen nur über einen einzigen Interrupt-Vektor (Adresse
0x04). Jeder aktivierte und ausgelöste Interrupt führt dazu, daß der PIC
an diese Adresse springt. Beim Hi-Tech sorgt das Keyword interrupt
dafür, daß die Funktion zu einer Interrupt-Funktion wird (steht an der
richtigen Adresse und sichert alle relevanten Register).
Da es nur einen Interrupt-Vektor gibt, kann es prinzipiell auch nur eine
Interrupt-Funktion geben. Wenn Du mehrere Interrupts benötigst, mußt Du
in dieser Funktion die entsprechenden Interrupt-Flags und eventuell auch
die Enable-Bits abfragen:
Code:
void interrupt name_ist_egal (void)
{
if (TMR1IE && TMR1IF)
{
... // Code für TMR1-Interrupt
}
if (TMR2IE && TMR1IF)
{
... // Code für TMR2-Interrupt
}
}
Die Abfrage des Enable-Bits ist nur dann nötig, wenn der entsprechende
Interrupt zeitweise im Programm deaktiviert wird. Der Grund für die
Abfrage ist, daß das Interrupt-Flag auch bei deaktiviertem Interrupt
gesetzt wird und der Interrupt-Code des deaktivierten Interrrups beim
Auftreten eines anderen Interrupts fälschlicherweise ausgeführt wird.
Ja, grundsätzlich läuft der. Ich kann ein Schalter einlesen und an
diesem Port wieder ausgeben.
Wenn ich mir die Timervariable TMR0 anschaue, bleibt die immer auf dem
geladenen Wert. Das Programm wird auch nicht durch einen Breakpoint in
der ISR unterbrochen.
Toggle mal den GPIO nicht, sondern setze in nur auf High und miß mal mit
dem Oszi oder dem Multimeter. Dann weißt Du ob er wirklich nicht
reingesprungen ist.
@ Jürgen
Hör nicht auf Analog.
Das einzige was TMR0 anhalten könnte ist ein Sleep
Befehl. Der WDT startet den Timer dann wieder.
Steht irgendwo ein Sleep in deinem Code ?
Ich check das nicht ganz... Ich will ja nur den Timer 0 benutzen, den
Watchdog nicht. Jetzt kommt natürlich ständig
CORE-W0003: Watchdog Timer event occurred. Break in execution requested
Ich brauch den Watchdog doch gar nicht grr
Braucht er auch nicht für den Timer0. Der wird im INTCON-Register
gesetzt und abgefragt. Es muss also nur GIE und T0IE eingeschaltet
werden, dann sollte er eigentlich in den Interrupt springen.
Für mich klingt das eher danach, als ob der Timer0 nicht auf internen
Takt geschaltet ist. Dazu muss T0CS=0 sein. Steht das Bit auf 1 wartet
der Timer0 auf einen Takt am externen PIN RA4.
Der WDT und der Timer0 benutzen beide den Prescaler! Wenn du beides
einschaltest, werden die Ergebnisse unvorhersehbar sein, da der Timer0
immer mal einen Interrupt auslöst und der WDT ein Reset (siehe Bild).
Ciao
Sven
Das hab ich auch alles so gemacht. Das Bild hab ich auch schon
tausendmal angeschaut... langsam krieg ich ne Kriese.
Hier nochmal meine Konfiguration:
Oscillator: Internal RC No Clock
Watchdog Timer: Off
Power Up Timer: Off
Master Clear Enable: Internal
Brown Out Detect: On
Code Protection: Off
Data EE Read Protect: Off
Hier mein gesamter Code:
Zum Auslösen des Timer0-Interrupts muss T0IE und GIE auf 1 gesetzt sein.
Wenn der Interrupt ausgelöst wird, setzt der PIC T0IF auf 1. Das ist für
dein Programm die Stelle wo du schaust, welcher Interrupt ausgelöst hat.
Da es nur einen Interruptvektor gibt musst du in der ISR die gesetzten
Interruptbits auswerten (natürlich nur von den Interrupts, welche du
eingeschaltet hast) um entscheiden zu können, in welche Routine du
springst. In der ISR muss das entsprechende Interruptbit (also das
xxxIF-Bit) wieder zurückgesetzt werden bevor du aus der ISR springst.
Sonst wird gleich wieder ein Interrupt ausgelöst. Das ist aber alles nur
auf Assembler bezogen, da ich C nicht kann. Mag sein, dass einiges davon
der C-Compiler selbst macht.
Also TOIE und GIE auf 1. Wenn Interrupt auftritt, T0IF ggf. auswerten
und zurücksetzen.
Sven
Dann fällt mir eigentlich nur noch ein, dass du bedenken musst, dass das
Timer0-Register nur alle 256 Takte (also 256 Assemblerbefehle) um eins
weiterzählt. Falls du also zum Testen des Proggs eine Simulation benutzt
und das Prog in Einzelschritten durch gehst, wirst du erst nach 256
Befehlen eine Veränderung des Timer0 Registers bemerken. Das
Prescalerregister kann man nicht sehen. Oder mal einen anderen PIC
probieren. Welchen benutzt du eigentlich?
Sven
Wie wärs denn am Ende Deiner Main mit einem
while (1)
{
}
was passiert denn da eigentlich ? Nach der Initialisierung beendet der
Controller seine Arbeit
Ach du SCHEISSE!
Tatsächlich, ein while(1) eingefügt und es geht.
Sorry leute, hab ich überhaupt nicht dran gedacht dass das nötig ist!
Vielen Dank an alle!!