www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Nur ein Interrupt beim PIC12F629?


Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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)

Autor: Analog (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich bin nicht sicher, aber ich glaube du hast nur einen handler. In 
diesem musst Du per If-Abfrage alles managen.

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke!

Will einen Interrupt von Timer 0 Overflow auslösen lassen, geht einfach 
nicht:

Hab folgendes initialisiert:
//Timer 0 Init
T0SE = 0;  //Rising Edge
T0CS = 0;  //Clk Source
PSA = 0;  //Prescaler assigned to T0
PS0 = 1;  //Prescaler = 256
PS1 = 1;
PS2 = 1;
TMR0 = 128;  //Timer value
T0IF = 0;  //Clearing Interrupt
T0IE = 1;  //Interrupt Mask
GIE  = 1;  //Global Interrupt Enable


Dies ist meine Interrupt Routine:
  void interrupt t0_int(void){
    GPIO2 ^= 1;
    T0IF=0;
    TMR0=0;    //Laden
  }


Autor: Analog (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mehr details

kommt ne fehlermeldung ? Was passiert ?

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, ich kanns kompilieren.

Die Interruptroutine wird aber nie aufgerufen.

Hab ich da noch ein Flag vergessen zu initialisieren?

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder muss ich noch was einbinden um Interrupts zu benutzen?

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Die Interruptroutine wird aber nie aufgerufen.

Wenn GPIO2 nicht toggelt:
TRIS richtig gesetzt ?
CMCON auf 0x07 gesetzt ?

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja hab ich

TRIS2 = 0; //Output
CMCON = 0x07;

Autor: Analog (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void interrupt timer0_isr(void)
{



  T0IF = 0;
}

Autor: Analog (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
probier mal anstatt interrupt timer0_int doch lieber interrupt 
timer0_isr

Autor: Analog (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber wie du ja gesagt hast ist der Name nach "interrupt" egal...

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Läuft der PIC überhaupt ?
Wie sieht dein Configurationword aus ?

Autor: Analog (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
achso lad mal TMR0 wieder mit 128 in der ISR so läuft der nicht wieder 
weiter

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Analog (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Analog (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Probier mal diese Einstellung

  T0CS = 0;      // select internal clock
  T0IE = 0;      // enable timer interrupt
  GIE = 1;      // enable global interrupts

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab ich gemacht, der wird nie 1!

Autor: Analog (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
T0IE = 0;      // enable timer interrupt

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Muss T0IE nicht 1 sein? Ist doch das Enable bit für den Timer0 
Interrupt.

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hatte bei den Konfigurationsbit den Watchdog Timer auf Off 
geschaltet. Mit On gehts!! Wusst nicht das der direkt mit dem Timer0 
zusammenhängt?

Autor: Analog (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das stimmt hab ich verbaselt. Aber ich sehe gerade das Du den PIE1 gar 
nicht gesetzt hast

Autor: Analog (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Datasheet Seite 31

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PIE1 ist doch nur für Timer 1

Autor: Analog (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was jetzt ? Timer0 dann muss T0IE gecleared werden, steht im Datenblatt.

Autor: Analog (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bit clear = 0

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ 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 ?

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nö kein Sleep (noch nicht)

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann mir jemand sagen was ihr bei der Configuration konkret einstellt?

Und muss das T0IE jetzt 1 oder 0 sein?

Autor: Analog (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
0. probieres doch einfach aus.

Autor: Sven Stefan (stepp64) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
#include <htc.h>

main()
{
//Init
//static bit input,inputneu;


//Port Init
TRIS2 = 0; //Output
CMCON = 0x07;
GPPU = 0;
GPIO2 = 0;

//Timer 0 Init
T0SE = 0;  //Rising Edge
T0CS = 0;  //Clk Source
PSA = 0;  //Prescaler assigned to T0
PS0 = 1;  //Prescaler = 256
PS1 = 1;
PS2 = 1;
T0IF = 0;  //Clearing Interrupt
T0IE = 1;  //Interrupt Mask
GIE  = 1;  //Global Interrupt Enable
TMR0 = 128;  //Timer value

}

   void interrupt timer0_isr(void) {
    GPIO2 ^= 1;
    T0IF=0;
    TMR0=128;    //Laden
  }

Autor: Sven Stefan (stepp64) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Sven Stefan (stepp64) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Sven Stefan (stepp64) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ja, deine Routine hat keine Hauptschleife. Eventuell liegt es ja 
auch daran ?!?

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab's auch mit dem KO angeschaut. Benutze den PIC12F629.

Autor: Hugo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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!!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.