Forum: Mikrocontroller und Digitale Elektronik Problem mit Interrupt an PIC


von SebiTNT (Gast)


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

von Andreas R. (blackpuma)


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.

von Jens P. (Gast)


Lesenswert?

Keine Calls innerhalb der Interruptroutine. Das geht nicht!

von SebiTNT (Gast)


Lesenswert?

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

von Andreas R. (blackpuma)


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.

von Jens Plappert (Gast)


Lesenswert?

genau!

von tastendrücker (Gast)


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)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.