Forum: Mikrocontroller und Digitale Elektronik PIC Programmieren


von Yassine (Gast)


Lesenswert?

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

von Gerhard Gunzelmann (Gast)


Lesenswert?

Debugge Dein Programm und schau, ob dein Timer 0 überhaupt läuft. Mir
scheint, daß der Timer nicht gestartet wird.

Gerhard

von Stefan (Gast)


Lesenswert?

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.

von Yassine (Gast)


Lesenswert?

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 %)

von Jens (Gast)


Lesenswert?

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?

von Stefan (Gast)


Lesenswert?

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.

von Schoaschi (Gast)


Lesenswert?

Ä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
Noch kein Account? Hier anmelden.