Forum: Compiler & IDEs Lauflicht in C


von ** *. (newman8051)


Lesenswert?

Hallo!

Ich versuche seit paar tagen auf mein 8051 ein lauflicht zu 
programmieren, leider ohne erfolg.
Da ich mir die programmier sprache C selber beigebracht habe, fehlen mir 
auch einige grundlagen. Ich hoffe Ihr könnt mir helfen.

#include <sfr51.h>


void warte(void);


main()
{


    {
        P0=0x01;        // Anfangswert.
       while(1)
       {
        warte ();       // Aufruf der Funktion warte.

        P0=P0<<1;       // Bit um eins nach Links verschieben.
        warte ();       // Aufruf der Funktion warte.
        }

        if (P0 == 0x80) // Prüfe ob P0 = 0x08 ist, wenn ja, setze 
Ausgang.
            {
                P0=0x01;// Wieder auf Anfangswert.
                warte ();// Aufruf der Funktion warte.

            }


     }

}

void warte(void)
{
    int i;
    for(i=0; i=50; i++)    // Timer 50 mal wiederholen, da einer 
durchlauf 20ms hat.
                           //50 x 20ms = 1sek.
    {
         TMOD = 0x01;
         TF0 = 0;
         TR0 = 0;
         TL0 = 0x7D;
         TH0 = 0xCA;
         TR0 = 1;
         while (TF0 == 0);


    }

}

von Peter D. (peda)


Lesenswert?

Dimithrius M. schrieb:
1
       while(1)
2
       {
3
        warte ();       // Aufruf der Funktion warte.
4
5
        P0=P0<<1;       // Bit um eins nach Links verschieben.
6
        warte ();       // Aufruf der Funktion warte.
7
        }

Alles danach ist toter Code.

Du weißt aber schon, daß P0 open-Drain Ausgänge hat?


Peter

von Loonix (Gast)


Lesenswert?

** ** schrieb:
1
> {
2
>         P0=0x01;        // Anfangswert.
Hier machst du eine Endlosschleife auf:
1
>        while(1)
2
>        {
3
>         warte ();       // Aufruf der Funktion warte.
4
> 
5
>         P0=P0<<1;       // Bit um eins nach Links verschieben.
6
>         warte ();       // Aufruf der Funktion warte.
7
>         }
Der folgende Code wird nie erreicht:
1
>         if (P0 == 0x80) // Prüfe ob P0 = 0x08 ist, wenn ja, setze
2
> Ausgang.
3
>             {
4
>                 P0=0x01;// Wieder auf Anfangswert.
5
>                 warte ();// Aufruf der Funktion warte.
6
> 
7
>             }
8
>

Das hier endende Klammernpaar ist überflüssig:
1
>      }

Ausserdem wird P0 nirgends initialisiert, woher soll dein uC denn wissen 
was Eingang und was Ausgang ist?

von Loonix (Gast)


Lesenswert?

Nachtrag: Sch... 7 Minuten gebraucht um das zamzuschreiben

von Mike R. (thesealion)


Lesenswert?

** ** schrieb:
1
void warte(void)
2
   {
3
   int i;
4
   for(i=0; i=50; i++)    // Timer 50 mal wiederholen, da ein Durchlauf 20ms hat.
5
                          //50 x 20ms = 1sek.
6
      {
7
      TMOD = 0x01;
8
      TF0 = 0;
9
      TR0 = 0;
10
      TL0 = 0x7D;
11
      TH0 = 0xCA;
12
      TR0 = 1;
13
      while (TF0 == 0); 
14
     } 
15
   }

Deine Warte-Funktion hat auch noch einen Fehler. Zu mindestens wenn sie 
so funktionieren soll wie angegeben.

Da für die Bedingung für die Schleife bei dir "i=50" lautet, wird die 
Schleife sofort abgebrochen. Wenn du 50 Durchläufe haben willst, muss 
die Bedingung so lange wahr sein, bis der fünfzigste Durchlauf erreicht 
ist. Also so lange i kleiner als 50 ist, soll die Bedingung wahr sein.

von Sven W. (Firma: basement industries) (dj8nw)


Lesenswert?

sollte es nicht heißen:
...
for (i=0 ; i<=50 ; i++) //anstatt i=50?

Gruß, Sven

von ** *. (newman8051)


Lesenswert?

Danke für die Unterstützung. Ich habe d Code geändert, aber es 
funktioniert noch nicht richtig. Ein LED leuchtet auf und ds wars dann 
auch.


main()

{

    P2 = 0x01;              //Anfangswert

    while(1)                //Dauerschleife

    {

        warte();            //Aufruf Funktion "Warte"

        P2 = P2 <<1;        //Bit um ein Feld nach links schieben

        warte();            //Aufruf Funktion "Warte"



        if(P2 == 0x80)      //Prüfe ob die "8hex" anliegt, wenn ja, 
setzte Ausgang wieder zurück

        {

            P2 = 0x01;      //Ausgang wieder zurück setzen

            warte();        //Aufruf Funktion "Warte"

        }

    }

}



// Unterprogramm----------------------------------------



void warte (void)

{

    int i;

    for (i=0;i<=50;i++)     //Timer 50 mal wiederholen lassen da ein 
Durchlauf 20ms hat (eingestellt)

    {

        TMOD = 0x01;        //Starten des Timers 0

        TF0 = 0;

        TR0 = 0;            //Timer stop

        TL0 = 0xE5;

        TH0 = 0xBE;

        TR0 = 1;            //Timer start

        while (TF0 == 0);   //Wiederhole solange kein Überlauf

    }

}

von ET-Tutorials (Gast)


Lesenswert?

Deine Verwendung des Timers ist etwas gewöhnungsbedürftig.
Normalerweise schreibt man eine Interrupt Service Routine, die dann das 
Shiften übernimmt.

Versuch doch zunächst einmal ohne den Timer das Lauflicht zu 
programmieren, indem Du in der warte-Funktion zunächst enmnal eine 
Variable (long int) hochzählt. Dann bist Du zumindest unabhängig von der 
Timer-Programmierung.

Ich werde überigens im Juli meinen 8051-Kurs weitermachen.
Der Timer kommt ziemlich am Anfang.
Vielleicht hast Du ja Interesse.
http://et-tutorials.de/mikrocontroller/

von Peter D. (peda)


Lesenswert?

ET-Tutorials schrieb:
> Deine Verwendung des Timers ist etwas gewöhnungsbedürftig.
> Normalerweise schreibt man eine Interrupt Service Routine, die dann das
> Shiften übernimmt.

Nein.
Man kann auch auf jede Interruptquelle (z.B. Timerüberlauf) pollen und 
dann das Flag händisch löschen.

Wenn man nur Däumchen drehen will, ist ein Interrupt nur unnötig 
aufwendig.
Einen Interrupt braucht man nur, wenn man in der Zwischenzeit noch was 
anderes machen will.


Peter

von ** *. (newman8051)


Lesenswert?

Hallo!

Hab gerade erst mit dem Programmieren in C für den Mikrokontroller 
angefangen. Daher kann ich nicht ganz verstehen, warum meine 
Timerfunktion ungewöhnlich ist.

Okay. Werden dann mal die Timerfunktion deaktivieren und Sie mit einem 
long int hochzählen.
Würde gern trotzdem verstehen, warum es nicht funktioniert.

Bezüglich Deines Angebots für 8051 würd ich gern darauf zurück kommen.

von Peter D. (peda)


Lesenswert?

ET-Tutorials schrieb:
> Versuch doch zunächst einmal ohne den Timer das Lauflicht zu
> programmieren, indem Du in der warte-Funktion zunächst enmnal eine
> Variable (long int) hochzählt. Dann bist Du zumindest unabhängig von der
> Timer-Programmierung.

Das ist die schlechteste Lösung, da Trial & Error.
Man hat keinerlei Kontrolle darüber, wie lang das Delay ist. Änderungen 
von Compilerversion und Compileroptionen können das Ergebnis 
beeinflussen.
Sowas sollte man daher nur im aller äußersten Notfall machen (z.B. alle 
Timer belegt).

Mit dem Timer kann man die Zeit aber exakt ausrechnen, hinschreiben, 
compilieren, flashen und es stimmt auf Anhieb.

Manche Compiler haben eine Delay-Lib, der man die Zeit (µs, ms, s) 
übergeben kann. Dann stimmt das Delay auch, solange es nicht durch 
andere Interrupts zu stark verzögert wird.
Ohne Delay-Lib ist aber immer der Timer die beste Wahl.


Peter

von ** *. (newman8051)


Lesenswert?

> Einen Interrupt braucht man nur, wenn man in der Zwischenzeit noch was
anderes machen will.

Hallo Peter,

Danke für dein Kommentar. Wie du schon gemerkt hast, bin ich ein 
Grünschnabel in Sachen C Programmierung. Es wäre super wenn du mir sagen 
könntest, was ich falsch gemacht habe.
Eine Interrupt Funktion wollte ich noch nicht einfügen, da mir hier noch 
die nötige Einarbeitung fehlt.

von Peter D. (peda)


Lesenswert?

1
P2 = P2 <<1;
Wenn Du die LEDs direkt an P2 gelegt hast, könnte es sein, daß der MC 
immer 0x00 einliest und schiebt.

Leg Dir ne Hilfsvariable an und gib diese auf P2 aus.


Peter

von ET-Tutorials (Gast)


Lesenswert?

Hallo Peter,
natürlich ist Zählen keine schöne Lösung, da gebe ich Dir recht.

Meine Erfahrung aus dem Unterricht ist aber, dass sich Schüler im ersten 
Schritt mit dem Zählen einfacher tun.

Also erst die Baustelle Bitshiften und dann die Baustelle Timer.
Bei 2 Baustellen verlieren Einsteiger meiner Erfahrung nach schneller 
die Übersicht.

Und natürlich kann man auch das Interrupt Pendig-Flag pollen.
Aber wie gesagt, mein (Lehrer-)Ansatz wäre da schrittweise ranzugehen.
Just my 2 Cents.

von ... (Gast)


Lesenswert?

Mike S. schrieb:
> Da für die Bedingung für die Schleife bei dir "i=50" lautet, wird die
> Schleife sofort abgebrochen.

Falsch! Das ist eine Zuweisung, die als boolcher Ausdruck interpretiert 
immer wahr ist. Das ist also eine Endlosschleife.

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.