Forum: Mikrocontroller und Digitale Elektronik Interruptiming Problem


von Tim (Gast)


Lesenswert?

Also hier ist erst mal der assembler code für den PIC16f84 , unten sag 
ich was da nicht so richtig geht :
um es besser lesen zu können am besten in einen Assembler-Tool kopieren


        list p=16f84
;**************************************************************
;*
;* Pinbelegung
;*      ----------------------------------
;*      PORTA:  0
;*              1
;*              2
;*              3
;*              4
;*      PORTB:  0 LED
;*              1
;*              2 LED
;*              3
;*              4
;*              5
;*              6
;*              7
;*
;*********** Beschreibung ********************************
;
;  2 blinkende LEDs die eine wird durch ein LED zum blinken gebracht und
;  in der Interrupbehandlungsroutine gibt es eine Verzögerung
;
;
; Taktquelle: 4MHz
;
;**************************************************************
; Includedatei für den 16F84 einbinden
;
        #include <P16f84.INC>
;
; Configuration festlegen
;
; bis 4 MHz: Power on Timer, kein Watchdog, XT-Oscillator
        __CONFIG        _PWRTE_ON & _WDT_OFF & _XT_OSC

;
;**************************************************************
; Variablennamen vergeben
loops    Equ     0x22            ; Zähler für Warteschleife
loops2   Equ     0x23            ; Zähler für Warteschleife
invert   Equ   0x24
w_copy   Equ   0x25
s_copy    Equ   0x26
invertA   Equ   0x27
MAinvert Equ     0x28


;**************************************************************
; los gehts mit dem Programm
        org    0x00
        goto   Init               ; Sprung zum Hauptprogramm
;**************************************************************
; die Interuptserviceroutine

    org    0x04
intvec
        bcf    INTCON, GIE      ; Interrups micht zulassen
        movwf  w_copy           ; w retten
        swapf  STATUS, w        ; STATUS retten
        movwf  s_copy
;-------------------------------------------------------------

    btfsc  MAinvert,0    ; schauen ob MAinvert 1 ist dann
    bsf     PORTB,2      ; LED an an RB2 an
    btfss  MAinvert,0    ; schauen ob MAinvert 0 ist dann
    bcf     PORTB,2      ; LED an an RB2 aus
    comf  MAinvert,1    ; invertieren von MAinvert

    call   Wait      ; Springen zur warte schleife

;======== Timerladen =========
;      MOVLW  D'250'           ; Timer neu laden
;       MOVWF  TMR0             ; immernoch Timer neu laden
;-------------------------------------------------------------
Int_end
;        bcf    INTCON, T0IE    ; RB0-Interupt-Flag löschen
        swapf  s_copy, w        ; STATUS zurück
        movwf  STATUS
        swapf  w_copy, f        ; w zurück mit flags
        swapf  w_copy, w

    bcf    INTCON, T0IF    ; Timeüberlauf flag löschen
        bsf    INTCON, GIE      ; Interrups zulassen
        retfie          ; aus der interrupgehandlung wieder 
zurückspringen

;===================== Hauptprogramm =========================

Init
        bsf     STATUS, RP0     ; auf Bank 1 umschalten
        movlw   B'00000000'     ; PortB alle output
        movwf   TRISB
        movlw  B'00000111'
    movwf  OPTION_REG    ; Vorteiler auf 256 setzen
        bcf     STATUS, RP0     ; auf Bank 0 zurückschalten
    clrf    PORTB      ; PORTB ausschalten
    bsf   INTCON, T0IE  ; durch Timerüberlauf Interrup zulassen
    bsf   INTCON, GIE    ; Interrups zulassen

; -------- endlos Schleife -------
Loop
        call    Wait            ; Springen zur warte schleife
        call  inver      ; spring in die LED invertierteil

;       btfsc  INTCON,T0IF
;    bsf     PORTB,3      ;aktion 1

;    btfss  INTCON,T0IF
;    bcf     PORTB,3      ;aktion  2

;       btfsc  INTCON,T0IF
;    bcf    INTCON,T0IF

        goto    Loop
;---------------------------------------------------------
inver
    btfsc  invertA,0    ; schauen ob invertA 1 ist dann
    bsf     PORTB,0      ; LED an an RB0 an
    btfss  invertA,0    ; schauen ob invertA 0 ist dann
    bcf     PORTB,0      ; LED an an RB0 aus
    comf  invertA, F    ; invertA invertieren
    retlw   0
;**********************************************************
; Warteschleife 250 ms

Wait
        movlw   D'250'          ; 250 ms Pause
        movwf   loops

Wai
        movlw   D'100'          ; Zeitkonstante für 1ms
        movwf   loops2
Wai2    nop
        nop
        nop
        nop
        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
        retlw   0              ; das Warten hat ein Ende

        end

So also das Problem ist, es wird nur die interruproutin abgearbeitet. 
Das hab ich mir so gedacht weil die LED an RB0 nicht blinkt.

Wäre nett wenn mir jemand helfen kann (ich häng schon extrem lang an dem 
Problem und als Anfänger ist das voll deprie :(

gruß Tim

von Tim (Gast)


Lesenswert?

uhhh soviel Beiträge schon ihr mag wohl PICs nicht so gg und lange 
(naja für ein Forum) Cods lesen auch nicht?
Phhh

Aber irgendwie muss euch das doch bekannt vorkommen oder ist das bei den 
AVRs so unterschiedlich oder seit ihr so Hochsprache lam0r :D? (Richtige 
Männer programmieren in asm, hab ich mir sagen lassen g)
naja vielleicht findet ja noch einer den Fehler(vielleicht sogar ein AVR 
programmieren :P)

von crazy horse (Gast)


Lesenswert?

Ich hasse PIC-Assemblercode, ich kann es einfach nicht ohne größerer 
Anstrengungen lesen - und das tue ich mir  just for fun auch nicht an - 
und damit bin ich wohl nicht ganz allein.

von thkaiser (Gast)


Lesenswert?

Sorry, hat nichts zu tun mit "PIC nicht mögen", sondern einfach: Nix Pic 
verstehn. Hättste einen Atmel, würde ich Dir gern helfen ;-)

von Peter D. (peda)


Lesenswert?

Hallo Tim,

ja, lange Listings mögen wir nicht direkt im Text.
Dazu ist der "Dateianhang" besser geeignet.
Dann siehst Du auch, wie oft sich das jemand angesehen hat.


Zum PIC gibt es hier fast nur 2 Meinungen:

Die einen (ich auch) kennen sich mit dessem Assemblersyntax nicht aus.

Und die anderen, die ihn mal kennen gelernt haben (z.B. crazy horse), 
wollen nichts mehr mit ihm zu tun haben.

Sollte das einem nicht zu denken geben ?


Ansonsten ein paar allgemeine Tips:

Immer klein anfangen, testen und dann Stück für Stück hinzufügen.
Ganz zu Anfang erstmal sehen, ob die CPU überhaupt was tut, z.B. 3 LEDs 
ran, eine auf 0, eine auf 1 setzen und die 3. immer im Wechsel.

Interrupts sind manchmal etwas schwierig, bessser dessen Funktion 
erstmal mit Polling testen.


Peter

von Ralf (Gast)


Lesenswert?

Hi Tim,

ich denke dein Fehler ist, das Du im Timerinterrupt die Warteschleife 
aufrufst. D.h. der Interrupt dauert sehr lange. Der Timer läuft in 
dieser Zeit aber weiter. Dadurch kann es sein, dass dein Hauptprogramm 
nur noch sehr langsam abläuft. Normalerweise hält man eine 
Interruptroutine möglichst kurz und beschränkt sich auf das nötigste 
(Taster abfragen, Variablen inkrementieren, usw.), sodass der der 
Interrupt möglichst wenig Zeit braucht und so den Rest des Programms 
nicht blockiert.
Was mir bei der Fehlersuche immer sehr geholfen hat, war eine Simulation 
in MPLAB. Dort sieht man genau wo der PIC gerade so rumläuft und kann 
sich Variablen anzeigen lassen und Zeiten messen.
Noch ne andere Frage: Warum benutzt Du immer dieses swapf um Register zu 
retten? Das geht doch mit movf und movwf auch, nur ohne diese doppelte 
Vertauschung. Ist vielleicht einfacher zu verstehen und somit weniger 
anfällig für Fehler (man hat leicht mal ein Swap vergessen).

Gruß,

Ralf

von Tim (Gast)


Lesenswert?

Das mit dem Swap hat den Vorteil das keine Flags im Statusregister 
verändert werden im Gegensatz zu movf den dabei kann das Zerobit gesetzt 
werden.
Ich hab mir das auch gedacht das der Timer weiter läuft und es dann zu 
diesen Problemen kommen kann, aber ich hab mal am Ende der 
Interruproutine den Timer neu gesetzt doch das Resultat war das selbe.

Also irgendwie wird immer nach verlassen der Interruproutine ein neuer 
aufgerufen aber eigentlich sollte das durch "bcf INTCON, T0IF ; 
Timerüberlauf flag löschen" verhindert werden, aber naja ich werd das 
mit der Debugger mal testen (wenn ich den Fehler irgend wann mal 
gefunden haben sollte post ich ihn :-)).

Gruß Tim

von Tim (Gast)


Lesenswert?

Mist ich hab den Fehler gefunden(dummer Fehler)! Danke@Tipp mit Debugger
Also wenn die Warteschleife vom Hauptteil aufgerufen wird dann 
unterbricht der Interrup diese. In der Interrproutine wird aber die 
selbe mit den gleichen Variablen aufgerufen das heißt loops2, loops hat 
sich verändert und wenn dann wieder zurück in die  Warteschleife des 
Hauptprogramms gesprungen wird, kann diese nicht zuende laufen da ja die 
startwerte resetet wurden und damit sie von neuem beginnt und von neuem 
durch den Interrup unterbrochen wird.

sorry für den langen komischen Satz ;P naja wir können ja mal einen AVR 
vs. PIC Thread aufmachen dann können wir mal Vergleichen.

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.