Hallo Ich muss einen PIC16F84A so programmieren dass er die Aufgabe macht: am Eingang(PORTA)ist ein 4er Schalter angeschlossen) und PORTB als Ausgang(ein LED am RB.0 zum testen). und jenach kombination beim Schalter muss PORTB(LED) eine bestimmte Zeit an bleiben.Ich habe mit C programmiet(nicht fit..) Das Programm: #include<C:\cc5\16F84A.h> #pragma config |= 0b.1111.1111.0010 char i; // Variable "i" deklariren ist für alle unterprogramme bekant void pause(uns16 ms) // Unterprogramm zum abwarten angegebener anzahl von Milisekunden { while(ms) // Schleife verlassen wenn ms=0 ist { OPTION = 2; // Vorteiler auf 8 einstellen TMR0 = 131; // 125 * 8 = 1000 (= 1 ms) while (TMR0); // Schleife, solange bis TMR0=0 wird ms--; // "ms" mit jeder 1ms ernidrigen } } void main (void) { TRISB =0b.0000.0000; // RA0..7 als Ausgänge bit A0 @ PORTA.0; // RA0..3 als Eingänge bit A1 @ PORTA.1; bit A2 @ PORTA.2; bit A3 @ PORTA.3; while(1) { if (A3) // PORTB an nach 30sec aus { PORTB=1; pause(30000); PORTB=0; } if (A0 && A3) // PORTB an nach 60sec aus { PORTB=1; for(i=0;i<2;i++) { pause(30000); } PORTB=0; } if (A1 && A3) // PORTB an nach 3min aus { PORTB=1; for(i=0;i<6;i++) { pause(30000); } PORTB=0; } if (A0 && A1 && A3) // PORTB an nach 6min aus { PORTB=1; for(i=0;i<12;i++) { pause(30000); } PORTB=0; } if (A3 && A2) // PORTB an nach 15min aus { PORTB=1; for(i=0;i<30;i++) { pause(30000); } PORTB=0; } if (A0 && A2 && A3) // PORTB an nach 30min aus { PORTB=1; for(i=0;i<60;i++) { pause(30000); } PORTB=0; } if (A1 && A2 && A3) // PORTB an nach 90min aus { PORTB=1; for(i=0;i<180;i++); { pause(30000); } PORTB=0; } if (A1 && A2 && A3 && A0) // PORTB an nach 180min aus { PORTB=1; for(i=0;i<360;i++) { pause(30000); } PORTB=0; } } } Das Problem: wenn der Schalter aus ist, dann leuchtet die LED ganz Zeit sonst bleibt aus? hoffe dass mir jemand helfen kann. mfg
Debugge Dein Programm und schau, ob dein Timer 0 überhaupt läuft. Mir scheint, daß der Timer nicht gestartet wird. Gerhard
Die LED ist am Programmanfang aus. Drückst Du einen oder mehrerer Schalter, daraufhin geht die LED an. Du lässt alle Schalter los, jetzt sollte die LED nach 30 Sekunden ausgehen. Macht sie aber nicht. Richtig? while (TMR0); Das ist solange eine klassische Endlosschleife, wie TMR0 sonstwo nicht auf exakt 0 gesetzt wird. Wer oder was macht das in Deinem Programm? Wenn es ein Timer ist, dann muss der C-Compiler wissen, dass sich die Variable TMR0 irgendwo ändert. Wenn er das nicht weiss, sieht er die Zuordnung TMR0 = 131; unmittelbar davor und beim optimieren wird angenommen, dass sich TMR0 nie never ever ändert... Also irgendwo müsste TMR0 als "volatile irgendwas TMR0;" deklariert sein. Wahrscheinlich in C:\cc5\16F84A.h Eine Erklärung der PIC Timer gibt es bei http://www.sprut.de/electronic/pic/grund/timer/timer.htm In den Assemblerquellen hierzu wird der Timerinterrupt noch extra eingeschaltet. bsf INTCON, T0IE ; Timer0 interrupt erlauben bsf INTCON, GIE ; Interrupt erlauben Dieser Part fehlt bei Dir. Dadurch zählt der Timer 0 einfach nicht hoch.
Ich weiss aber nicht mit welchen Befehlen man den TMO hochzählen lässt.und für den beiden Befehlen weiss ich nicht wo? Ich habe dass Programm auch als Assemblercode: ; CC5X Version 3.2F, Copyright (c) B Knudsen Data ; C compiler for the PICmicro family ; ************ 15. Jun 2005 12:07 ************* processor 16F84A radix DEC TMR0 EQU 0x01 PORTB EQU 0x06 TRISB EQU 0x86 Carry EQU 0 Zero_ EQU 2 RP0 EQU 5 OPTION_REG EQU 0x81 i EQU 0x0E ms EQU 0x0C A0 EQU 0 A1 EQU 1 A2 EQU 2 A3 EQU 3 GOTO main ; FILE Test2.c ; ; ;#include<C:\cc5\16F84A.h> ;#pragma config |= 0b.1111.1111.0010 ; ; ;char i; // Variable "i" deklariren ist für alle unterprogramme bekant ; ;void pause(uns16 ms) // Unterprogramm zum abwarten angegebener anzahl von Milisekunden ;{ pause ; while(ms) m001 MOVF ms,W IORWF ms+1,W BTFSC 0x03,Zero_ GOTO m004 ; // Schleife verlassen wenn ms=0 ist ; ; { ; OPTION = 2; // Vorteiler auf 8 einstellen MOVLW .2 BSF 0x03,RP0 MOVWF OPTION_REG ; TMR0 = 131; // 125 * 8 = 1000 (= 1 ms) MOVLW .131 BCF 0x03,RP0 MOVWF TMR0 ; while (TMR0); // Schleife, solange bis TMR0=0 wird m002 BCF 0x03,RP0 MOVF TMR0,W BTFSC 0x03,Zero_ GOTO m003 GOTO m002 ; ; ms--; // "ms" mit jeder 1ms ernidrigen m003 DECF ms,1 INCF ms,W BTFSC 0x03,Zero_ DECF ms+1,1 ; } GOTO m001 ;} m004 RETURN ; ; ;void main (void) ; ;{ main ; ; TRISB =0b.0000.0000; // RA0..7 als Ausgänge BSF 0x03,RP0 CLRF TRISB ; bit A0 @ PORTA.0; // RA0..3 als Eingänge ; bit A1 @ PORTA.1; ; bit A2 @ PORTA.2; ; bit A3 @ PORTA.3; ; ;while(1) ;{ ; if (A3) // PORTB an nach 30sec aus m005 BCF 0x03,RP0 BTFSS 0x05,A3 GOTO m006 ; { ; PORTB=0; CLRF PORTB ; pause(30000); MOVLW .48 MOVWF ms MOVLW .117 MOVWF ms+1 CALL pause ; PORTB=1; MOVLW .1 BCF 0x03,RP0 MOVWF PORTB ; } ; ; if (A0 && A3) // PORTB an nach 60sec aus m006 BCF 0x03,RP0 BTFSS 0x05,A0 GOTO m009 BTFSS 0x05,A3 GOTO m009 ; { ; PORTB=0; CLRF PORTB ; for(i=0;i<2;i++) CLRF i m007 MOVLW .2 SUBWF i,W BTFSC 0x03,Carry GOTO m008 ; { ; pause(30000); MOVLW .48 MOVWF ms MOVLW .117 MOVWF ms+1 CALL pause ; } INCF i,1 GOTO m007 ; PORTB=1; m008 MOVLW .1 BCF 0x03,RP0 MOVWF PORTB ; } ; ; if (A1 && A3) // PORTB an nach 3min aus m009 BCF 0x03,RP0 BTFSS 0x05,A1 GOTO m012 BTFSS 0x05,A3 GOTO m012 ; { ; PORTB=0; CLRF PORTB ; for(i=0;i<6;i++) CLRF i m010 MOVLW .6 SUBWF i,W BTFSC 0x03,Carry GOTO m011 ; { ; pause(30000); MOVLW .48 MOVWF ms MOVLW .117 MOVWF ms+1 CALL pause ; } INCF i,1 GOTO m010 ; PORTB=1; m011 MOVLW .1 BCF 0x03,RP0 MOVWF PORTB ; } ; ; if (A0 && A1 && A3) // PORTB an nach 6min aus m012 BCF 0x03,RP0 BTFSS 0x05,A0 GOTO m015 BTFSS 0x05,A1 GOTO m015 BTFSS 0x05,A3 GOTO m015 ; { ; PORTB=0; CLRF PORTB ; for(i=0;i<12;i++) CLRF i m013 MOVLW .12 SUBWF i,W BTFSC 0x03,Carry GOTO m014 ; { ; pause(30000); MOVLW .48 MOVWF ms MOVLW .117 MOVWF ms+1 CALL pause ; } INCF i,1 GOTO m013 ; PORTB=1; m014 MOVLW .1 BCF 0x03,RP0 MOVWF PORTB ; } ; ; if (A3 && A2) // PORTB an nach 15min aus m015 BCF 0x03,RP0 BTFSS 0x05,A3 GOTO m018 BTFSS 0x05,A2 GOTO m018 ; { ; PORTB=0; CLRF PORTB ; for(i=0;i<30;i++) CLRF i m016 MOVLW .30 SUBWF i,W BTFSC 0x03,Carry GOTO m017 ; { ; pause(30000); MOVLW .48 MOVWF ms MOVLW .117 MOVWF ms+1 CALL pause ; } INCF i,1 GOTO m016 ; PORTB=1; m017 MOVLW .1 BCF 0x03,RP0 MOVWF PORTB ; } ; ; if (A0 && A2 && A3) // PORTB an nach 30min aus m018 BCF 0x03,RP0 BTFSS 0x05,A0 GOTO m021 BTFSS 0x05,A2 GOTO m021 BTFSS 0x05,A3 GOTO m021 ; { ; PORTB=0; CLRF PORTB ; for(i=0;i<60;i++) CLRF i m019 MOVLW .60 SUBWF i,W BTFSC 0x03,Carry GOTO m020 ; { ; pause(30000); MOVLW .48 MOVWF ms MOVLW .117 MOVWF ms+1 CALL pause ; } INCF i,1 GOTO m019 ; PORTB=1; m020 MOVLW .1 BCF 0x03,RP0 MOVWF PORTB ; } ; ; if (A1 && A2 && A3) // PORTB an nach 90min aus m021 BCF 0x03,RP0 BTFSS 0x05,A1 GOTO m024 BTFSS 0x05,A2 GOTO m024 BTFSS 0x05,A3 GOTO m024 ; { ; PORTB=0; CLRF PORTB ; for(i=0;i<180;i++); CLRF i m022 MOVLW .180 SUBWF i,W BTFSC 0x03,Carry GOTO m023 INCF i,1 GOTO m022 ; { ; pause(30000); m023 MOVLW .48 MOVWF ms MOVLW .117 MOVWF ms+1 CALL pause ; } ; PORTB=1; MOVLW .1 BCF 0x03,RP0 MOVWF PORTB ; } ; ; if (A1 && A2 && A3 && A0) // PORTB an nach 180min aus m024 BCF 0x03,RP0 BTFSS 0x05,A1 GOTO m027 BTFSS 0x05,A2 GOTO m027 BTFSS 0x05,A3 GOTO m027 BTFSS 0x05,A0 GOTO m027 ; { ; PORTB=0; CLRF PORTB ; for(i=0;i<360;i++) CLRF i ; { ; pause(30000); m025 MOVLW .48 MOVWF ms MOVLW .117 MOVWF ms+1 CALL pause ; } INCF i,1 GOTO m025 ; PORTB=1; m026 MOVLW .1 BCF 0x03,RP0 MOVWF PORTB ; } ; } m027 GOTO m005 ORG 00 ;DATA 0FF2H END ; *** KEY INFO *** ; 0x0001 21 word(s) 2 % : pause ; 0x0016 168 word(s) 16 % : main ; RAM usage: 3 bytes (2 local), 65 bytes free ; Maximum call level: 1 ; Total of 190 code words (18 %)
Sorry Yassine, aber dein Posting is ne Zumutung. Schonmal gelesen, was bei eröffnung eines neuen Threads immer am Anfang steht? Nein? Macht nichts, hier kommts nochmal: * Keine Fragen zu Cracks, Raubkopien etc. * Vor dem Schreiben Google und Forum-Suche benutzen und ggf. Datenblatt lesen * Beitrag im richtigen Unterforum schreiben * Sourcecode immer in den Anhang * Beiträge die dagegen verstoßen werden ohne Vorwarnung gelöscht * Erst denken, dann schreiben! Fällt dir was auf?
Sorry. Mein erster Tip bezog sich auf Interrupts. Man kann den Timer aus ohne Interrupts in einer Zählschleife abfragen, so wie Du es machst. Quellen/Erläuterungen zu Deinem Problem findest Du bei http://www.cc5x.de/ Besonders Teil 1 und 3 finde ich interessant. Zum debuggen die 30000ms auf 1000ms runtersetzen und ein paar Piepser wie bei Teil 3 beschrieben einbauen... Dein böser Quelltext sieht fast richtig aus ;-) Mit TRISB konfigurierst Du alle Pins von PORTB als Ausgänge. Dein Kommentar hierzu passt nicht. Das ist aber Kleinkram. Problematisch ist IMHO die Typdeklaration von i als char Variable. In einigen Fällen (Zählschleifen bis 180 und 360) bekommst Du einen Überlauf. Deklariere i besser als >=16Bit int Typ oder noch besser als unsigned int. Im Moment passiert z.B. bei A1 && A2 && A3 folgendes: Es wird von i=0 bis i=127 (d.h. 128 mal) 30s gewartet. Dann wird i von 127 erhöht. Weil i ein signed char ist geht es statt auf 128 auf -1... und die for Schleife wird nie verlassen ;-( Kritisch ist weiter, dass Du alle if Abfragen hintereinander steckst statt die passenden else zu benutzen. Oder statt die Schalterstellung in eine Variable zu schreiben und ein switch zu benutzen. Ich habe mir nur grob angesehen, was passieren kann, wenn bei bestimmten Schalterkombinationen zwei oder mehr if-Fälle anspringen. Im Moment wenn Z.B. alle Schalter an sind (A1 && A2 && A3 && A0), dann werden ALLE if Fälle wahr, d.h. ALLE Wartezeiten werden durchlaufen.
Ähm... kann es sein, dass du PORT A nicht als eingang definiert hast oder habe ich das übersehen?
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.