- LiTime Speicher und Akkus         
Ergebnis 1 bis 10 von 10

Thema: PIC12F675 TMR0 Overflow Interrupt

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    30.06.2017
    Beiträge
    5

    PIC12F675 TMR0 Overflow Interrupt

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hallo,

    MPLab, XC8, PIC12F675, Simulator: "Real Pic Simulator"
    ohne große Umschweife, kann mir jemand auf die Sprünge helfen?
    Im Leben noch keinen PIC etc. programmiert habe ich mich nach langem Abwägen für die vorliegende Konfiguration entschieden.
    Doch schon die ersten Schritte bringen mich zur Verzweiflung.
    Es will mir nicht gelingen ein Mini-Programm zum "TMR0 Overflow Interrupt" zu schreiben.
    Einer meiner Ansätze:

    #include <xc.h>
    #define _XTAL_FREQ 4000000
    int R_count;

    void __interrupt(void)
    {
    GP5 = ~GP5; //zur Kontrolle
    INTCON &= ~(1<<T0IF); // clear timer0 overflow bit.
    R_count = 1; // ob der Rest so Ok ist wird interessant,
    GIE = 0; // sobalt der Interrupt überhaupt ausgeführt wird.
    PEIE = 1;

    } //RETFIE wird von XC8 autom. generiert, ebenso GIE=0. (heißt es)


    void main()
    {
    __CONFIG(0x3f70); //?
    TRISIO = 0; // Setzt alle GPIO als Ausgang
    ANSEL = 0; // all ports digital
    CMCON = 7; // Comparator aus
    GPIO = 0x00; // start with all outputs =1
    GIE = 1; // bit7 global interrupt enable
    PEIE = 1; //Enable Peripheral Interrupt
    OPTION_REG = 0x08; // oder auch 0x48;
    R_count = 0;

    TMR0 = 239; // preset for timer register, Counter zählt, doch kein Interrupt bei Überlauf

    while(1)
    { if (R_count == 1 ) {GP1 = 1; R_count = 0;} else GP1 = 0; //Kontrolle Interrupt
    GP0 = ~GP0;
    __delay_us(100);
    }
    }

    Die Ausgänge GPIO werden im Oszilloscope visualisiert.
    Ist GIE = 0; läuft main() wie vorgesehen, Rechtecksignal an GP0
    Ist GIE = 1; meldet "Real Pic Simulator" den Fehler: "out of code"
    der Simulator von OshonSoft zeigt brav das Rechtecksignal an GP0
    aber auch hier kein Interrupt bei TMR0 Überlauf.
    Bisher habe ich noch keinen Interrupt hinbekommen.

    Was muß ich ändern damit der Interrupt angesprochen wird?

    Vielen Dank

    Ergänzung_1
    Bin einen halben Schritt weiter.

    Ich muß anmerken, MPlab empfiehlt die Verwendung von XC8. Doch Die wenigen verfügbaren Erläuterungen / Beispiele verwenden alle Möglichen C Variationen, nur seltenst XC8.
    Das gilt auch für MPlab selbst.
    Seit mehr als zwei Wochen versuche ich mich an der Einarbeitung.

    Gerade eben bin ich auf ein PIC Beispiel gestoßen. Die Interrupt Routine lautet:
    void interrupt priority lowISR(void) // wird vom Compiler moniert
    Paßt natürlich nicht für XC8, merkt man schon wenn nicht #include <xc.h> gegeben ist.
    Dennoch, ich hatte schon einiges probiert, noch ein Versuch:
    void interrupt lowISR(void) // vom Compiler akzeptiert
    void interrupt ISR(void) // vom Compiler akzeptiert

    Diese Beiden bringen mich den Schritt weiter, der Interrupt wird aufgerufen.
    Allerdings, die Interruptroutine springt vom Ende an den Anfang.
    Der Debugger zeigt am Ende ein RETFIE, der Prog.Counter springt aber an Adr. 0x04


    Bei XC8 (finde ich gerade nicht) stand etwas von void __interrupt(void) oder so ähnlich.
    In einem Beispiel finde ich:

    For 8-bit compilers, change any occurrence of the interrupt qualifier e.g., from:
    void interrupt low_priority myLoIsr (void)
    to the following:
    void __interrupt(low_priority) myLoIsr(void)

    Es funktioniert nicht, habe aber noch nicht alle Variationen durch.
    Vielleicht hat doch jemand Erfahrung damit.


    Gruß juppkk
    Geändert von juppkk (30.06.2017 um 17:22 Uhr)

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    03.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    1.023
    Ohne diesen Controller genauer zu kennen und ohne alles durchgesehen zu haben fallen mir ein Paar Dinge in deinem Code auf:


    - im Hauptprogramm wird das T0IE bit (also INTCON<5>) nicht gesetzt? Ohne TMR0-Interrupt Enable kein TMR0-Interrupt.
    - in der ISR wird das T0IF nicht gelöscht. Ohne Löschung läuft die Timer0-ISR in Endlosschleife
    - dein Kommentar //RETFIE wird von XC8 autom. generiert, ebenso GIE=0. (heißt es) macht keinen rechten Sinn. Das Global Interrupt Enable ist aktiviert, wenn =1;

    Zitat aus dem Datenblatt

    4.4.2 Timer0 Interrupt

    A Timer0 interrupt is generated when the TMR0
    register timer/counter overflows from FFh to 00h. This
    overflow sets the T0IF bit. The interrupt can be masked
    by clearing the T0IE bit (INTCON<5>). The T0IF bit

    (INTCON<2>) must be cleared in software by the

    Timer0 module Interrupt Service Routine before re-
    enabling this interrupt.

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    30.06.2017
    Beiträge
    5

    gelöst

    Hallo,
    danke für die Antwort.

    Beim XC8/ PIC12F675 ist alles anders, das ist mein Problem schlechthin.
    XC8 kennt T0IE nicht. Dort heißt es TMR0IE.

    >>> in der ISR wird das T0IF nicht gelöscht. Ohne Löschung läuft die Timer0-ISR in Endlosschleife <<<
    ich denke gelesen zu haben, daß XC8 das selbst regelt, dennoch ich werde es probieren.
    Inzwischen probiert: Prima, das Ding heißt TMR0IF = 0; und ist des Rätsels Lösung.

    >>>dein Kommentar //RETFIE wird von XC8 autom. generiert, ebenso GIE=0. (heißt es) macht keinen rechten Sinn. Das Global Interrupt Enable ist aktiviert, wenn =1; <<<

    Da bin ich mir sicher, das gelesen zu haben. XC8 generiert den RETFIE, ist im Debugger ja auch zu sehen und GIE wird automatisch in der ISR auf 0 gesetzt. Darum muß es im Main() immer wieder neu gesetzt werden.

    Ein Blick in den Debugger: ja GIE ist auf 0 gesetzt.

    Ich möchte noch einmal hervorheben, so wie bei (fast) allen PICs die Ports mit PORTA bzw. RA0 angesprochen werden, heißt es beim PIC12F675 GPIO bzw. GP0 (RA0, GP0 = Port A Bit 0)
    Da muß man erst einmal drauf kommen. In anderen C Beispielen heißt es GPIO0 usw. oder GPIO.0
    Und so ist es mit allen Parametern.

    Noch einmal besten Dank. Das Rücksetzen des Timer Interrupt Flag TMR0IF noch in der Interrupt Routine brachte die Lösung.
    Für alle die irgendwann über diesen Thread stolpern, hier die Endgültige ISR:

    void interrupt lowISR(void) { TMR0IF = 0; GP5 = ~GP5; } //zur Kontrolle, Port A Bit5 invertieren

    Ob "void interrupt lowISR(void)" letztendlich richtig ist bleibt noch ungeklärt. Es funktioniert und auch der Compiler meckert nicht,
    obwohl die Beschreibung zum XC8 von void __interrupt . . . ausgeht.

    Vielen Dank,
    Gruß juppkk

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    03.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    1.023
    Herzlichen Glückwunsch zum Erfolg und herzlichen Dank, dass du die Lösung hier postest und so dein Wissen mit uns (mir) teilst!

    Zitat Zitat von juppkk Beitrag anzeigen
    Beim XC8/ PIC12F675 ist alles anders, das ist mein Problem schlechthin.
    XC8 kennt T0IE nicht. Dort heißt es TMR0IE.
    Das ist ja fies. Und es läuft der Microchip-Gewohnheit zuwider, Bitnamen im XC8 abweichend vom Datenblatt zu wählen. Sieht nach einer übertriebenen Vereinheitlichung mit TMR1IF ... aus. T0IF ist ja der historische Standardname beim Timer0-Interruptflag.

    Zitat Zitat von juppkk Beitrag anzeigen
    >>>dein Kommentar //RETFIE wird von XC8 autom. generiert, ebenso GIE=0. (heißt es) macht keinen rechten Sinn. Das Global Interrupt Enable ist aktiviert, wenn =1; <<<
    Da bin ich mir sicher, das gelesen zu haben. XC8 generiert den RETFIE, ist im Debugger ja auch zu sehen und GIE wird automatisch in der ISR auf 0 gesetzt.
    Ja, schon. GIE wird mit dem Einsprung in die ISR per Hardware weggenommen und beim Verlassen der ISR vom retfie-Befehl wieder gesetzt, damit kein zweiter Interrupt verschachtelt aktiviert werden kann. Dafür ist dieser Controller nicht ausgelegt, die Rücksprungadressen würden dann durcheinander kommen.

    ISR-Priorisierung gibt es hier ebenfalls nicht. da solltest du nochmal genauer hinschauen.

    Zitat Zitat von juppkk Beitrag anzeigen
    Darum muß es im Main() immer wieder neu gesetzt werden.
    Nein. Wie sollte main() das auch sinnvoll leisten? GIE sollte in der Regel nur dort manipuliert werden, wo man einem Interrupt die Unterbrechungserlaubnis geben oder entziehen will oder zur Realisierung atomarer Befehlssequenzen. Ansonsten kann im Controller hundert Jahre lang eine Timer0-ISR zyklisch aktiviert werden ohne dass jemals GIE durch einen Programmbefehl gesetzt oder gelöscht werden muss.

  5. #5
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Zitat Zitat von juppkk Beitrag anzeigen
    Ich möchte noch einmal hervorheben, so wie bei (fast) allen PICs die Ports mit PORTA bzw. RA0 angesprochen werden, heißt es beim PIC12F675 GPIO bzw. GP0 (RA0, GP0 = Port A Bit 0)
    Das ist der Tatsache geschuldet, daß die Ports im Datenblatt bei diesem Prozessor so heißen. Und der XC8 kann dafür überhaupt nichts. Ein C-Compiler kennt keine Portbits, noch nichtmal ganze Ports. Die ganze Magie steckt in pic12f675.h. Da werden alle Eigenschaften des Prozessors mit #defines beschrieben. Dieser File wird über xc.h und die Auswahl des Prozessors im Projekt eingebunden. Wenn ich mal in den jeweiligen Headerfile schauen will und zu faul bin, ihn zu suchen, nehme ich irgendeine Registerbezeichnung, die der Compiler akzeptiert, und klicke mit Ctrl-linke Maustaste drauf. Dann öffnet die IDE den File für mich.

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    30.06.2017
    Beiträge
    5
    Hallo,

    @RoboHolIC
    stimme Dir zu, mit dem GIE habe ich mich verlaufen.
    GIE wird in ISR zurückgenommen und mit RETFIE wieder gesetzt.
    Das Einzige was gehändelt werden muß ist in der ISR das TMR0IF.

    Nur so nebenbei:

    Ich habe in ISR einfach TMR0IF = 0; gesetzt.
    Warum ist das in einem Beisp. INTCON &= ~(1<<T0IF); // clear timer0 overflow bit.
    wie ein Schuß von hinten durch die Brust ins Auge?

    Interessant, TMR0IF = 1; löst umgehend einen Interrupt aus.
    Ich muß mich korrigieren, T0IF wird ebenso akzeptiert wie TMR0IF
    Kann nur vermuten, daß ich mich verschrieben hatte.

    @Klebwax
    ja, das war auf die Schnelle ein einfaches Beispiel. Jetzt wo ich es bräuchte finde ich keines, doch die letzten zwei Wochen bin ich zu Hauf über solche Besonderheiten gestolpert.
    Sei es drum, das Einzige was mich noch drückt ist die Interrupt Routine.
    Im XC8 wird von __interrupt . . . geschrieben.
    Ich bin durch Zufall und probieren bei "void interrupt lowISR(void)" gelandet.
    Es geht und stört nicht weiter, doch es scheint letztendlich nicht im Sinne des Erfinders zu sein.

    Was noch etwas bedenklich stimmt ist die beständige Meldung:
    . . . mplab_ipe\xc8\v1.00\sources\ftmul.c:60: warning: (751) arithmetic overflow in constant expression
    Es ist eine Warnung und wirkt sich nicht weiter aus.


    Gruß juppkk

  7. #7
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Zitat Zitat von juppkk Beitrag anzeigen
    Sei es drum, das Einzige was mich noch drückt ist die Interrupt Routine.
    Im XC8 wird von __interrupt . . . geschrieben.
    Ich bin durch Zufall und probieren bei "void interrupt lowISR(void)" gelandet.
    Das klingt für mich nach PIC18, wo es Interrupts mit Low und High Priority gibt. PIC12 hab ich bisher nicht mit Interrupt betrieben, bei PIC16 benutze ich void interrupt tc_int(void) , wobei tc_int ein Platzhalter ist. Es gibt ja nur einen Interruptvektor. Probier doch einfach void interrupt name(void).

    Warum ist das in einem Beisp. INTCON &= ~(1<<T0IF); // clear timer0 overflow bit. wie ein Schuß von hinten durch die Brust ins Auge?
    In den Headerfiles der (aller) PICs werden alle Control- und Statusbits als Bitfelder aufgedröselt und können daher im C-Code einzeln gesetzt werden. INTCONbits.T0IF = .... Daher hab ich mir abgewöhnt, solche Construkte wie "INTCON &= ~(1<<T0IF) " gedanklich nachzuvollziehen oder zu verwenden.

    Was noch etwas bedenklich stimmt ist die beständige Meldung:
    . . . mplab_ipe\xc8\v1.00\sources\ftmul.c:60: warning: (751) arithmetic overflow in constant expression
    Ich kann da nur vermuten, daß es an #define _XTAL_FREQ 4000000 liegt. Die Zahl ist zu groß für ein Integer, es sollte #define _XTAL_FREQ 4000000UL heißen. Die Wirkung könnte sein, daß die delay-Routinen falsche Zeiten liefern.

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

  8. #8
    Neuer Benutzer Öfters hier
    Registriert seit
    30.06.2017
    Beiträge
    5
    Hallo,
    danke,
    #define _XTAL_FREQ 4000000UL bringt keine Änderung.

    Das meine ich ja. TMR0IF =0; ist kurz u. bündig, INTCON &= ~(1<<T0IF) muß man erst einmal durchblickern.

    Gruß juppkk

  9. #9
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Zitat Zitat von juppkk Beitrag anzeigen

    Das meine ich ja. TMR0IF =0; ist kurz u. bündig, INTCON &= ~(1<<T0IF) muß man erst einmal durchblickern.
    Warum benutzt du es dann? Schreib einfach INTCONbits.T0IF =... oder INTCONbits.TMR0IF = .... Das sind Bezeichnungen von Strukturelementen, da gehört der Name der Struktur INTCONbits mit hinein. Aus PIC12F675.h

    Code:
    // Register: INTCON
    extern volatile unsigned char INTCON @ 0x00B;
    #ifndef _LIB_BUILD
    asm("INTCON equ 0Bh");
    #endif
    // bitfield definitions
    typedef union {
        struct {
            unsigned GPIF                   :1;
            unsigned INTF                   :1;
            unsigned T0IF                   :1;
            unsigned GPIE                   :1;
            unsigned INTE                   :1;
            unsigned T0IE                   :1;
            unsigned PEIE                   :1;
            unsigned GIE                    :1;
        };
        struct {
            unsigned                        :2;
            unsigned TMR0IF                 :1;
            unsigned                        :2;
            unsigned TMR0IE                 :1;
        };
    } INTCONbits_t;
    extern volatile INTCONbits_t INTCONbits @ 0x00B;
    Hier sieht man, daß aus Kompatibilitätsgründen TMR0IF und TMR0IE auch noch unterstützt werden.

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    30.06.2017
    Beiträge
    5
    Hallo,
    irgendwie ein Mißverständnis.
    Ich verwende TMR0IF =0;
    INTCON &= ~(1<<T0IF) habe ich auf der Suche nach Lösungen einem Beispiel entnommen.
    Es stellt sich die Frage, warum macht jemand so etwas?

    Gruß juppkk

Ähnliche Themen

  1. Seltsames Verhalten Timer 0 overflow interrupt
    Von Markus87 im Forum Assembler-Programmierung
    Antworten: 6
    Letzter Beitrag: 24.08.2011, 20:27
  2. Kein Overflow Interrupt für Timer0
    Von eli45 im Forum C - Programmierung (GCC u.a.)
    Antworten: 4
    Letzter Beitrag: 05.06.2007, 21:56
  3. Timer2 overflow Interrupt will nicht
    Von BomberD im Forum C - Programmierung (GCC u.a.)
    Antworten: 10
    Letzter Beitrag: 30.01.2006, 17:37
  4. Overflow Interrupt für Timer
    Von Maestro im Forum AVR Hardwarethemen
    Antworten: 8
    Letzter Beitrag: 28.09.2004, 18:02
  5. Analogverarbeitung und TMR0 Interrupt am 12F675
    Von Steffen35 im Forum PIC Controller
    Antworten: 1
    Letzter Beitrag: 09.09.2004, 22:05

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiTime Speicher und Akkus