Forum: PC-Programmierung Mikrocontroller for-Schleife beenden?


von Stefanski (Gast)


Lesenswert?

Hallo Jungs und Mädels.
Ich fange gerade mit Mikrocontrollern an und habe einen Atmel-Ice mit 
der entsprechenden Software. Zum Einstieg habe ich mir noch ein Buch 
gekauft, aber irgendwie begreife ich es dennoch nicht. Mein Programm ist 
ein LED-Lauflicht mit 4 LEDs was in einer Schleife läuft. Wie beende ich 
denn diese Schleife nach z.B. 3 Durchläufen? Wenn das Programm sowieso 
merkwürdig oder sinnlos ist, dürft ihr mir gerne eine überarbeitete 
Version zeigen :)
Auf jeden Fall möchte ich keine Dauerschleife!


#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  DDRD = 0xFF;
  while(1)
  {
    PORTD = (1<<PD0);
    _delay_ms (400);
    for(uint8_t i = 0;i<=2;i++)
    {
      PORTD = (PORTD << 1);
      _delay_ms(400);
    }
  }
}


MfG

von Kolja L. (kolja82)


Lesenswert?

Das Lauflicht muss in eine Bedingung und einen Zähler hoch zählen

von Stefanski (Gast)


Lesenswert?

Das ist gut zu wissen, aber das heißt jetzt was?

von Nop (Gast)


Lesenswert?

Stefanski schrieb:
> Das ist gut zu wissen, aber das heißt jetzt was?

Daß Du aus der obersten while-Schleife eine for-Schleife mit einem 
Schleifenzähler machen könntest.

von Nop (Gast)


Lesenswert?

Ach ja.. das hat dann aber das Problem, daß Deine main() endet. Unter 
Windows würde sich in dem Fall das Programm beenden, aber bei einem 
Mikrocontroller gibt es halt nichts, was "danach" passieren soll.

Typischerweise hast Du dann entweder einen Absturz, oder nach dem Aufruf 
von main() ist im Startup-Teil eine Endlosschleife, so daß danach nichts 
mehr passiert.

von Stefanski (Gast)


Lesenswert?

Also wäre dann 1 Controller hopps, nur für ein Lauflicht, welches nach 
ein paar Durchläufen endet?

von go for gold (Gast)


Lesenswert?

Stefanski schrieb:
> while(1)
>   {
>     PORTD = (1<<PD0);
>     _delay_ms (400);
>     for(uint8_t i = 0;i<=2;i++)
>     {
>       PORTD = (PORTD << 1);
>       _delay_ms(400);
>     }
>   }
1
  
2
while (1) {
3
  PORTD = 0x01;
4
  _delay_ms (400);
5
  for (uint8_t i = 0; i < 3; i++;) {
6
    PORTD <<= 1;
7
    _delay_ms (400);
8
  }
9
}

von Nop (Gast)


Lesenswert?

Stefanski schrieb:
> Also wäre dann 1 Controller hopps

Nein, Du müßtest ihn resetten, dann startet das nochmal. Da Controller 
aber normalerweise ohne Nutzereingriff Dinge lange tun sollen, macht man 
das in einer großen Endlosschleife.

Für Deine Anwendung wäre es natürlich möglich, das Lauflicht dreimal 
laufen zu lassen, sozusagen als Start-Anzeige, und danach andere Dinge 
aus der main() heraus zu starten.

von Stefanski (Gast)


Lesenswert?

Okay. Könntest du mir das als Programm schreiben? Dann kann ich es 
besser nachvollziehen. Als Neuling ist es sonst ziemlich kompliziert, 
ohne Beispiel :)

von Sheeva P. (sheevaplug)


Lesenswert?

Stefanski schrieb:
> Ich fange gerade mit Mikrocontrollern an und habe einen Atmel-Ice mit
> der entsprechenden Software. Zum Einstieg habe ich mir noch ein Buch
> gekauft, aber irgendwie begreife ich es dennoch nicht. Mein Programm ist
> ein LED-Lauflicht mit 4 LEDs was in einer Schleife läuft. Wie beende ich
> denn diese Schleife nach z.B. 3 Durchläufen? Wenn das Programm sowieso
> merkwürdig oder sinnlos ist, dürft ihr mir gerne eine überarbeitete
> Version zeigen :)

Eine For-Schleife besteht aus drei Teilen: einer Initialisierung, einer 
Bedingung, einem "Nachgedanken" und dem Schleifenkörper.

Die Initialisierung findet statt, bevor der Schleifenkörper zum ersten 
Mal abgearbeitet wird. Dann wird die Bedingung geprüft, und wenn diese 
"wahr" ergibt, wird der Schleifenkörper und dann der "Nachgedanke" 
abgearbeitet. Danach springt die Ausführung wieder zu Prüfung der 
Bedingung zurück; wenn diese immer noch "wahr" ist, werden der 
Schleifenkörper und danach der "Nachgedanke" ausgeführt, bis die 
Bedingung "falsch" ergibt.

Deine For-Schleife sieht -- etwas anders geschrieben und kommentiert -- 
so aus:
1
for(
2
    uint8_t i = 0; /* Initialisierung */
3
    i <= 2;        /* Bedingung */
4
    i++            /* "Nachgedanke */
5
    ) {
6
                   /* Schleifenkörper */
7
}

Also wird die Variable i zunächst auf 0 initialisiert. Dann wird die 
Bedingung geprüft, und da i kleiner als 2 und die Bedingung damit 
erfüllt ist, wird erst der Schleifenkörper durchlaufen und danach der 
"Nachgedanke" ausgeführt, in dem i um 1 erhöht wird, am Ende also 1 ist. 
Dann folgt wieder die Prüfung der Bedingung, und da der Wert von i (1) 
natürlich kleiner als 2 ist: Schleifenkörper, "Nachgedanke", am Ende hat 
i den Wert 2 und die Bedingung wird erneut geprüft: i ist nicht kleiner, 
aber gleich 2, die Bedingung ist also erfüllt, Schleifenkörper, 
"Nachgedanke", am Ende ist i dann gleich 3 und die Bedingung wird wieder 
überprüft. Aber, huch: jetzt ist i = 3, also nicht mehr <= 2. Die 
Bedingung ist also falsch, deswegen wird die Schleife abgebrochen und 
mit dem Code nach der Schleife (nach der }) weitergemacht.

Ich hab' das mal so geschrieben, daß es auf einem PC läuft:
1
#include <stdio.h>
2
3
int main(void) {
4
5
    int i;
6
    for(i = 0; i <= 2; i++) {
7
        printf("in loop: i = %d\n", i);
8
    }
9
    printf("after loop: i = %d\n", i);
10
    return 0;
11
}

Ausgabe:
1
in loop: i = 0
2
in loop: i = 1
3
in loop: i = 2
4
after loop: i = 3

Kurz gesagt: wenn Du es richtig machst, beendet sich Deine for-Schleife 
von selbst, weil die Bedingung falsch wird.

Außerdem gibt es noch zwei Schlüsselworte: "break" springt sofort aus 
der Schleife heraus zum nachfolgenden Code, "continue" beendet das 
Abarbeiten des Schleifenkörpers und springt wieder zum Anfang der 
Schleife. Beide Schlüsselworte funktionieren auch mit anderen Schleifen 
und werden meist zusammen mit weiteren Bedingungen (if) benutzt.
1
#include <stdio.h>
2
3
int main(void) {
4
5
    int i;
6
    
7
    for(i = 0; i <= 2; i++) {
8
        printf("before if: i = %d\n", i);
9
        if( i == 1 ) {
10
            continue;
11
        }
12
        printf("after if: i = %d\n", i);
13
    }
14
    printf("after loop: i = %d\n", i);
15
    return 0;
16
}

Ausgabe:
1
before if: i = 0
2
after if: i = 0
3
before if: i = 1
4
before if: i = 2
5
after if: i = 2
6
after loop: i = 3

Du siehst: "i = 1" wird nur einmal ausgegeben, weil das "continue" in 
diesem Fall wieder zur Bedingungsprüfung springt. Wenn Du statt 
"continue" dort "break" schreiben würdest, sähe die Ausgabe so aus:
1
before if: i = 0
2
after if: i = 0
3
before if: i = 1
4
after loop: i = 1

von watz (Gast)


Lesenswert?

Vorausgesetzt deine for-schleife selbst hat bislang getan, was sie soll:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
int main(void)
5
{
6
  DDRD = 0xFF;
7
  PORTD = (1<<PD0);
8
  _delay_ms (400);
9
  for(uint8_t i = 0;i<=2;i++)
10
  {
11
    PORTD = (PORTD << 1);
12
    _delay_ms(400);
13
  }
14
  while(1)
15
  {
16
  }
17
}
Damit sollte das Programm einmal zum Start genau das machen, was du oben 
beschrieben hast und danach befindet sich der Controller in einer 
Endlosschleife, in der er einfach nichts macht.

Mikrocontroller sind keine Computer. Wenn man keine Sleepmodes 
verwendet, müssen die immer was "tun". Die leere while(1) Schleife ist 
ein bisschen vergleichbar mit dem Leerlaufprozess unter Windows.

von Stefanski (Gast)


Lesenswert?

Danke euch!  Das werde ich morgen alles mal ausprobieren und schauen. 
Jetzt aber erstmal schlafen, um halb 6 gehts wieder raus. Wünsche euch 
eine gute Nacht.

von Nop (Gast)


Lesenswert?

Stefanski schrieb:
> Okay. Könntest du mir das als Programm schreiben?

Resetten heißt z.B. Spannungsquelle abziehen und neu anstecken, dann 
startet er neu. Oder auf den Resetknopf drücken.

Positiv gesehen bist Du soweit, daß Deine Toolchain läuft, Du das 
Programm runterladen kannst und daß es auf dem Controller läuft. Das 
sind die vorbereitenden Arbeiten, und jetzt geht die Entwicklung von dem 
los, was Du denn mit dem Controller tun möchtest.

von Stefanski (Gast)


Lesenswert?

Also eigentlich möchte ich eine IR-Fernbedienung basteln, um u.A. Platz 
zu sparen (im Inneren meines Objektes). Mein Ziel ist es, LEDs und einen 
Laser mit 2 Schaltern über IR zu schalten, anstatt mit Kabel, da das nur 
bedingt möglich ist.
Das wollte ich mit einem Mikrocontroller lösen und deshalb fange ich 
ganz am Anfang an, das Programmieren zu lernen. Finde es allerdings 
ziemlich kompliziert, selbst dieses doofe Lauflicht. Vielleicht sollte 
ich mir mal eine Liste erstellen/suchen, auf der die wichtigsten Befehle 
erklärt sind.
Mein Buch finde ich anstrengend, da es ständig heißt "dazu erfahren Sie 
später mehr"... aber ich will ja genau dann wissen, was ich tun muss, 
wenn ich es ins Programm schreibe. Naja...mal sehen wann oder ob ich das 
Alles verstehe.

von Manfred (Gast)


Lesenswert?

Stefanski schrieb:
> Naja...mal sehen wann oder ob ich das Alles verstehe.

Ausdauer und selbst Fehler suchen ist angesagt und baut Wissen auf.

Kinderprogramme ins Internet zu posten ist vertane Zeit.

Ich weiß nicht mehr, wie viele Tage ich gebraucht habe, an meinem ersten 
6504-Board einen Schalter abzufragen und die zugehörige LED 
anzuschalten. Mangels Internet musste ich es mir selbst erarbeiten, 
geschadet hat es mir nicht.

von dupdidu (Gast)


Lesenswert?

>Mangels Internet musste ich es mir selbst erarbeiten,
>geschadet hat es mir nicht.

Puh, wenn ich an die Zeiten denke, Turbo Pascal aufm 286er und noch kein 
Internet. Frag dich mal, wo du jetzt sein würdest mit Internet damals ;)

Gruß J

von Dirk B. (dirkb2)


Lesenswert?

dupdidu schrieb:
> Puh, wenn ich an die Zeiten denke, Turbo Pascal aufm 286er und noch kein
> Internet.

Damals, im letzten Jahrtausend, wurden auch noch gedruckte Bücher (auch 
eine Erfindung aus dem letzten Jahrtausend) mitgeliefert.

von Pandur S. (jetztnicht)


Lesenswert?

> Vielleicht sollte ich mir mal eine Liste erstellen/suchen, auf der die 
wichtigsten Befehle erklärt sind.

Der Mega-Knaller. Genau. Die Idee. Mach das. Ohne Ueberblick wird's 
nichts. Ich wuerd aber eine Uebersicht ueber alle Befehle haben wollen.

: Bearbeitet durch User
von Stefanski (Gast)


Lesenswert?

Warum hält man nicht einfach die Klappe, anstatt Quark zu schreiben?

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.