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.