mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Problem mit Interrupt an PIC


Autor: SebiTNT (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Mein Problem ist, dass nach einmaligem Durchlauf des Interrupts dieser 
mit RETFIE irgendwie immer an die falsche Stelle im Programm 
zurückspringt. Eigendlich sollte doch wieder die endlosschleife 
gestartet werden. Bin irgendwie am verzweifeln. Sitze schon fast 3 
Stunden dabei. Ich hoffe ihr könnt mir einen Tipp geben! Vielen Dank 
schonmal im Voraus!
greetz,

Sebi


Hier mein Programm:
list p=16f627

; Taktquelle: 4 MHz
;
;**************************************************************
; Includedatei für den 16F627 einbinden
 #include <P16f627.INC>

; Configuration festlegen
; bis 4 MHz: Power on Timer, kein Watchdog, XT-Oscillator

        __CONFIG _PWRTE_ON & _WDT_OFF & _XT_OSC

;**************************************************************
; Variablennamen vergeben

w_copy  Equ    0x30               ; Backup für Akkuregister
s_copy  Equ    0x31               ; Backup für Statusregister
loops   Equ     0x22            ; Zähler für Warteschleife
loops2  Equ     0x23            ; Zähler für Warteschleife
kontrolle   Equ     0x24            ; Kontrollbit

;**************************************************************
; los gehts mit dem Programm

        org    0
        goto   Init               ; Sprung zum Hauptprogramm

;**************************************************************
; die Interruptserviceroutine

        org  4
intvec
    movwf   w_copy
    swapf   STATUS,w
    bcf     STATUS, RP0       ; status_temp in Bank 0
    movwf   s_copy

  call pruefung


Int_end
  bcf    INTCON, INTF       ; RB0-Interrupt-Flag löschen
    swapf   s_copy,w
    movwf   STATUS
    swapf   w_copy,f
    swapf   w_copy,w
    RETFIE

;**************************************************************



pruefung
    BTFSC  kontrolle, 0    ;Prüfen, ob das Gerät läuft
    call  ausschalten    ;wenn es läuft, dann ausschalten
        call  anschalten





anschalten
    BSF    PORTA, 0           ; Gerät schalten
    call  Wait250
    BCF    PORTA, 0
    BSF    kontrolle, 0        ;Kontrollbit setzen
    goto  Int_end


ausschalten
    BSF    PORTA, 0           ; Gerät schalten
    call  Wait250
    BCF    PORTA, 0
    BCF    kontrolle, 0        ;Kontrollbit entfernen
    goto  loop


; Warteschleife 250 ms
Wait250
        movlw   D'1'          ; 250 ms Pause
        movwf   loops
Wai
        movlw   .110           ; Zeitkonstante für 1ms
        movwf   loops2
Wai2    nop
        nop
        nop
        nop
        nop
        nop
        decfsz  loops2, F      ; 1 ms vorbei?
        goto    Wai2           ; nein, noch nicht
                               ;
        decfsz  loops, F       ; 250 ms vorbei?
        goto    Wai            ; nein, noch nicht
        Return

; das Hauptprogramm

Init
; Port RA0 auf Ausgabe stellen
        clrf   PORTA              ; LED aus
        bsf    STATUS, RP0        ; auf Bank 1 umschalten
        movlw  B'11111110'        ; PortA RA0 output
        movwf  TRISA
        bcf    STATUS, RP0        ; auf Bank 0 zurückschalten

; RB0-Interrupt einstellen
        bsf    STATUS, RP0        ; auf Bank 1 umschalten
        bsf    OPTION_REG, INTEDG ; 0-1-Flanke an RB0
        bcf    STATUS, RP0        ; auf Bank 0 zurückschalten

        bsf    INTCON, INTE       ; RB0-interrupt erlauben
        bsf    INTCON, GIE        ; Interrupt generell erlauben

loop    goto   loop               ; eine Endlosschleife
;**********************************************************

        end

Autor: Andreas Riegebauer (blackpuma)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weiß nicht ob das stimmt was ich jetzt schreibe aber ich glaube du 
musst den Program Counter sichern zu begin der Routine und bevor du 
wieder zurückspringst musst du den wieder setzten. Kann mich aber auch 
irren.

Autor: Jens Plappert (Firma: Bei mir und dir.) (gravewarrior)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Keine Calls innerhalb der Interruptroutine. Das geht nicht!

Autor: SebiTNT (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
VIELEN DANK!!!!
Hab's jetzt mit mehreren GOTO's innerhalb der Interruptroutine gemacht, 
geht einwandfrei!
THX!!!!

Autor: Andreas Riegebauer (blackpuma)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genau so war das. Das Call überschreibt den gesicherten Program Counter 
oder? Er weiß dann zwar wo er beim return von dem Call hin muss aber 
nicht mehr wohin er muss bei dem Return From Interrupt.

Autor: Jens Plappert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
genau!

Autor: tastendrücker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Keine Calls innerhalb der Interruptroutine. Das geht nicht!

Unfug! Natürlich geht das.

Nur (wie immer): Zu jedem CALL gehört ein RETURN. Man darf eben 
nicht mit CALL eine Routine aufrufen und aus dieser mit GOTO wieder 
herrausspringen. Bei jedem CALL wird die Rücksprungadresse auf dem 
Call-Stack abgelegt, und diese wird mit dem nächsten RETURN wieder 
abgeholt. Einzig auf die Größe des Call-Stacks ist zu achten (ich glaube 
der liegt bei 8 Adressen)

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.