Forum: Mikrocontroller und Digitale Elektronik Variable einer Schleife ersetzen


von Lokus P. (derschatten)


Lesenswert?

Ich verwende folgende Schleife:
1
  while(1)
2
  {
3
    for (tpos=text1;pgm_read_byte(tpos)!='~';tpos++)
4
    {
5
        for (softx=0;softx<FONTWIDTH;softx++)
6
        {
7
        adcval = ReadChannel(6);
8
        ScrollLeft();
9
        PrintScrollColumn(pgm_read_byte(tpos),softx,0);
10
        Warte(adcval/1);
11
        }
12
    }
13
  }
14
  return 0;

Die Variable text1 ist eine Globale:
1
prog_uint8_t text1[] = "Das ist der erste Text ~";
2
prog_uint8_t text2[] = "Das ist der zweite Text ~";

Jetzt möchte ich gerne innerhalb der for-schleife eine Abfrage verwenden 
die mir tpos=text1 in tpos=text2 ändert. Sodas der 2te Text ausgegeben 
wird.

Also zb.:

if (ReadChannel(7) > 500) ...

Geht das? Wenn ja, wie?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Jetzt möchte ich gerne innerhalb der for-schleife eine Abfrage verwenden
> die mir tpos=text1 in tpos=text2 ändert. Sodas der 2te Text ausgegeben
> wird.
Du willst mitten in der Ausgabe des ersten Strings direkt an die selbe 
Postition des 2. Strings? Oder soll einfach der 2. String von vorne 
ausgegeben werden?

> if (ReadChannel(7) > 500) ...
Wo hättest du die Umschaltung gern?

BTW:
Mit C-üblichen nullterminierten Strings kannst du auch so schreiben:
1
    for (tpos=text1;pgm_read_byte(tpos);tpos++) ...

von Karl H. (kbuchegg)


Lesenswert?

Ich kann die Fragestellung auch nicht interpretieren. Hauptsächlich 
allerdings deshalb, weil ich mir aus deinem geposteten Codeabschnitt 
überhaupt keinen Reim machen kann. Was soll das Ziel sein? Dass die 
Buchstaben von links nach rechts langsam ausgegeben werden? Eine Art 
Scheibenwischereffekt?

Aber ich denke, du solltest als erstes anfangen, dir ein paar 
Hilfsfunktionen zu machen. Einzelzeichen ausgeben. String ausgeben.

von STK500-Besitzer (Gast)


Lesenswert?

>Jetzt möchte ich gerne innerhalb der for-schleife eine Abfrage verwenden
>die mir tpos=text1 in tpos=text2 ändert. Sodas der 2te Text ausgegeben
>wird.


>for (tpos=text1;pgm_read_byte(tpos)!='~';tpos++)

Bastel dir einen Pointer, der statt fest auf "text1" zeigt, variabel 
ist.
Dann kannst du dir eine Abfrage bauen, in deren "then"-Zweig dieser 
Variablen die Adresse von text1 und in "else"-Zweig die Adresse von 
text2 zugewiesen wird.
Das kann man dann quasi unendlich erweitern...
Im Prinzip kannst du auch einfach tpos die jeweilige Adresse zuweisen.

Ich bin mir nicht sicher, aber vielleicht könnte es so gehen:

[c]
if (BedingungfuerText1)
   { tpos = text1;}
else
   { tpos = text2;}
for (;pgm_read_byte(tpos)!='~';tpos++)
.
.
.
}

von Lokus P. (derschatten)


Lesenswert?

Zur Funktion:
Das ganze ist eine Scrollschriftanzeige die den Text auf einem 12x10 
LED-Board ausgibt.
Dabei wird Buchstabenweise aus der Variabel text1 / text2 ausgelesen und 
nach links verschoben.


Die Umschaltung müßte meiner Meinung nach direkt in der FOR-Schleife 
passieren, weil ich gerne auch wärend dem Scrollen auf den anderen Text 
umschalten möchte, der anschließen natürlich von vorne beginnen soll.
Also denke ich müßte man die Schleife auch mit einem break; abbrechen.

Mit nullterminierten meinst du wohl Leerzeichen, oder?
Das ist nicht so toll, da Leerzeichen sowohl auch am Schluss noch 
erwünscht sind um den Scroller Platz zu schaffen für eine Wiederholung.

Das beispiel oben könnte zwar funktionieren, erlaubt mir aber keine 
Änderung in der Schleife mehr.
Oder könnte ich die Abfrage direkt in die Schleife legen?

von Karl H. (kbuchegg)


Lesenswert?

Manfred W. schrieb:

> Mit nullterminierten meinst du wohl Leerzeichen, oder?

Nein.
Nullterminiert: eine binäre 0 am Ende.
So wie in C seit jeher Strings gebildet werden.
http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F

Danke für die Funktionsbeschreibung. Jetzt ist klarer was das Ziel ist.

Du könntest es zb so machen
1
  useText = 1;
2
3
  while(1)
4
  {
5
    if( useText == 1 )   // was soll eigentlich angezeigt werden: Text1 oder Text2?
6
      tpos = text1;
7
    else
8
      tpos = text2;
9
10
    while( pgm_read_byte( tpos ) )
11
    {
12
      //
13
      // ein Zeichen komplett ausgeben
14
      //
15
      for (softx=0;softx<FONTWIDTH;softx++)
16
      {
17
        adcval = ReadChannel(6);
18
        ScrollLeft();
19
        PrintScrollColumn(pgm_read_byte(tpos),softx,0);
20
        Warte(adcval/1);
21
      }
22
23
      tpos++;
24
25
      //
26
      // Welcher Text sol überhaupt angezeigt werden
27
      //
28
      if( ReadChannel(7) > 500 )
29
        wantText = 2;
30
      else
31
        wantText = 1;
32
33
      // Hat sich das geändert gegenüber dem was zur Zeit angezeigt
34
      // wird
35
      if( wantText != useText )
36
      {
37
        // ja, dann schalte um und brich die momentante Ausgabeschleife ab
38
        // weiter gehts dann mit while(1) und dort wird dann der neue Text
39
        // eingestellt, indem tpos den neuen Textanfang kriegt
40
        useText = wantText;
41
        break;
42
      }
43
    }
44
  }
45
  return 0;

Ich habe das jetzt absichtlich etwas ausführlich und einfach 
geschrieben, damit du es verstehst. Man kann das auch alles etwas 
kompakter lösen. Aber so gehts auch.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Mit nullterminierten meinst du wohl Leerzeichen, oder?
Ein Leerzeichen ist 0x20
Eine NULL ist 0x00

Dieser String:
>>> prog_uint8_t text1[] = "Das ist der erste Text ~";
sieht im Speicher so aus:
@text1 'D', 'a', 's', ' ', 'i', ... 'e', 'x', 't', ' ', '~', '/0'
@text1 0x44 0x61 0x73 0x20 0x69 ... 0x65 0x78 0x74 0x20 0x7E 0x00
Es ist im Speicher also 1 Byte mehr reserviert, als dein String 
tatsächlich lang ist. Und in diesem Zeichen steht die binäre Null als 
Ende-Kennung.

von Lokus P. (derschatten)


Lesenswert?

Danke euch erstmal. Das ganze funtkioniert wunderbar anhand des 
Beispieles.
Ich habe den Code jetzt etwas abgespeckt und wollte das ganze mit 
CASE-Anweisungen verwenden, weil ich ja nicht nur 2 oder 3 verschiedene 
Texte einbauen möchte, sondern mehrere ca. 10

Nur scheint es in C keine vernünftige Anwendungsweise dafür zu geben.
CASE kann nur immer einen ganzen Wert haben, also nicht ">500" zb.?
1
  tpos = text1;
2
3
  while(1)                          // Endlosschleife
4
  {
5
    while(pgm_read_byte(tpos))                // Aktuelles Zeichen lesen
6
    {
7
      for(softx=0;softx<FONTWIDTH;softx++)        // Pixel des Zeichens abarbeiten
8
      {
9
         adcval = ReadChannel(6);
10
        ScrollLeft();                  // Platz schaffen und Zeilen nach links schieben
11
        PrintScrollColumn(pgm_read_byte(tpos),softx,0);  // Ganz rechts eine Spalte des Zeichens ausgeben
12
        Warte(adcval/1);                // Ein bischen warten damit es nicht zu schnell wird
13
      }
14
      tpos++;
15
      switch(ReadChannel(7))                  // was soll eigentlich angezeigt werden
16
      {
17
            case (>1000:)
18
          tpos = text1;
19
          break;
20
            case (>500)
21
          tpos = text2;
22
          break;
23
        case (>100)
24
          tpos = text3;
25
          break;
26
      }
27
    }
28
  return 0;
29
  }

Wie kann man sowas lösen?
Und was noch ein wenig unschön ist, das der Laufende Text verändert 
wird. Besser wäre, wenn die Anzeige komplett gelöscht wird und der 
Scroller mit dem neuen Text von vorne beginnt.

von STK500-Besitzer (Gast)


Lesenswert?

switch-case braucht feste Vergleichswerte, keine Bereiche.
Du wirst ein paar if-Abfragen benutzen müssen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Nur scheint es in C keine vernünftige Anwendungsweise dafür zu geben.
Mit einer If-Abfrage ginge das super...

BTW:
Deine forever loop hat ihren Namen nicht mehr verdient, weil sie durch 
ein return beendet wird   :-o
1
  while(1)                          // Endlosschleife
2
  {
3
    while(pgm_read_byte(tpos))                // Aktuelles Zeichen lesen
4
    {
5
      for(softx=0;softx<FONTWIDTH;softx++)        // Pixel des Zeichens 
6
      :
7
    }
8
    return 0;
9
  }

von P. S. (Gast)


Lesenswert?


von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Peter Stegemann schrieb:
> Du brauchst ein C-Buch:
Als Tipp zum Sparen: es reichen auch die älteren Ausgaben, die für ein 
besseres Trinkgeld zu haben sind...

von Lokus P. (derschatten)


Lesenswert?

Habs jetzt mit einigen IF hinbekommen.
Hat jetzt vielleicht noch jemand einen Tip für mich wie ich die Anzeige 
löschen kann bevor der nächste Text angezeigt wird?

von Klaus W. (mfgkw)


Lesenswert?

Steht das nicht im Datenblatt des Displays?
Du kannst natürlich auch verraten, welches LCD es ist; dann sieht 
bestimmt gerne jemand für dich nach...

von Lokus P. (derschatten)


Lesenswert?

ist kein LCD. Ist eine LED Platine mit 12x10 LEDs.

Noch eine andere Frage. Kann man bei einem else if kein or verwenden?

Also:
1
    if(useText==1) or (ReadChannel(7)>800)           // was soll eigentlich angezeigt werden: Text1 oder Text2?
2
      tpos=text1;
3
      else if(useText==2) or (ReadChannel(7)>400)
4
       tpos=text2;
5
    else
6
      tpos=text3;

von Klaus (Gast)


Lesenswert?

ALTA!!!  Kannst du mir mal verraten, wie du etwas programmieren 
möchtest, ohne die einfachste C-Syntax zu kennen?

Nimm ein C-Buch, oder von mir aus ein Online Tutorial, da steht alles 
der Reihe nach und auf einander aufbauend drin.

Du versuchst doch auch nicht, zum Beispiel Französisch zu lernen, indem 
du als erstes versuchst, einen französischen Buch zu schreiben, oder?

von Werner (Gast)


Lesenswert?

... wie schon von Peter erwähnt:
Du brauchst ein C Buch!

...Natürlich kann man bei einem else if ein "OR" verwenden. Aber nicht 
so wie Du es gemacht hast.

Erst mal: guck mal auf Deine Klammersetzung. Was ist die else if 
Bedingung? Dein Compiler kann nicht hellsehen.

Zweitens: Wie wäre es mit:

else if ( ( Bedingung 1 ) || ( Bedingung 2 ) )



Werner

von Werner (Gast)


Lesenswert?

...  Klaus  war schneller

von Klaus W. (mfgkw)


Lesenswert?

naja, wenn er nicht C meint, sondern C++, dann geht es schon mit or...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Der dezente Hinweis der Vorgängerposts geht in die Richtung:
1
    if( useText==1 || ReadChannel(7)>800 )           // was soll eigentlich angezeigt werden: Text1 oder Text2?
2
      tpos=text1;
3
    else if( useText==2 || (ReadChannel(7)>400 )
4
       tpos=text2;
5
    else
6
      tpos=text3;
Das Thema || sowie && wird in deinem neu zu kaufenden C-Buch unter dem 
Thema logische Operatoren abgehandelt. Binäre Verknüpfungen gehen mit | 
und &.

von Karl H. (kbuchegg)


Lesenswert?

Und für das löschen des Displays schreibst du dir jetzt als allererstes 
eien Funktion, die das macht (nachdem du in deinem neuen C-Buch 
nachgelesen hast, wie man Funktionen macht).

Diese Funktion rufst du dann auf, wenn du den Text wechselst.

von Fred (Gast)


Lesenswert?

Und ich würde mich mal dringends an deiner Stelle mit Array 
beschäftigen. Dann kannste deine Texte über einen Index ansprechen, und 
musst nicht immer extra eine Variable dafür definieren.

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.