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
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)
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.
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 ;-)
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
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.