Forum: Mikrocontroller und Digitale Elektronik LCD-Anzeige: Verständnisproblem bei einem Pointer


von S. L. (lonci)


Lesenswert?

Hallo,

ich habe gerade eine Routine für ein 2-zeiliges (2x16) LCD Display 
(DOGM-Serie) programmiert.

Mit
1
Disp_String("Hello World");  // Send string to display

übergebe ich eine Zeichenkette an die Funktion
1
void Disp_String(char *cData)

Als Übergabeparameter habe ich hier einen Pointer auf char. Dieser 
Pointer zeigt auf das erste Zeichen, welches übergeben wurde. Wurde das 
erste Zeichen an das Display übertragen, wird mit  ++ cData;  der 
Pointer um eins erhöht und zeigt somit auf das zweite Zeichen usw.

Verstehe ich das so richtig?


Hier der Code:
1
void Disp_String(char *cData)
2
{
3
  PORTB = (1 << RS); // Data Mode vorbeireiten; setze RS high
4
5
  while (*cData)
6
  {
7
    SPDR = *cData; // Starte übertragung
8
    while(!(SPSR & (1<<SPIF)));  // Warte auf ende der Übertragung
9
    
10
    //Übertragung abschließen durch RS toggle
11
    PORTB &= ~(1 << RS); //low
12
    PORTB = (1 << RS); // high
13
    _delay_us(50); // warte auf Display
14
    
15
    ++ cData;  // increment pointer
16
  }
17
}
18
19
int main ()
20
{
21
  InitSPI();            // SPI init
22
  InitDisp();            // Display init
23
  _delay_ms(100);          // Delay for display
24
25
  while (1)
26
  {
27
    Disp_Clear();        // Clear display
28
    _delay_ms(10);        // Display delaytime
29
    dogm_gotoxy(3, 0);      // Cursorposition column 3, row 0
30
    Disp_String("Hello World");  // Send string to display
31
    dogm_gotoxy(4, 1);      // Cursorposition column 4, row 1
32
    Disp_String("2. Zeile");    // Send string to display
33
    
34
    for(uint8_t i=0; i<50 ;i++)  // Delaytime 5 seconds
35
    {
36
      _delay_ms(100);
37
    }
38
  }
39
}

von Georg G. (df2au)


Lesenswert?

Genau so ist es

von S. L. (lonci)


Lesenswert?

ok, dann noch eine Frage zu:
1
while (*cData)
2
{
3
  ....
4
}

*cData ist ja der Pointer. Also führe die Schleife aus solange der 
Pointer "true" ist ?

Wann ist der Pointer nicht mehr "true" bzw. wann ist er überhaupt 
"true"?

von Alram L. (alram)


Lesenswert?

streng genommen, heisst es nicht "führe die schleife aus, solange der 
pointer true ist", sondern "führe die schleife aus, solange der inhalt, 
auf den der pointer zeigt, true ist". der stern vor cData macht da den 
unterschied aus.

in c ist generell alles, was nicht 0 ist, true. da am ende des strings 
ein Null-Char zwecks terminierung ist, wird die schleife dort dann 
abbrechen.

vg

von Karl H. (kbuchegg)


Lesenswert?

S. Lonci schrieb:

> Wann ist der Pointer nicht mehr "true" bzw. wann ist er überhaupt
> "true"?

Wie Alram schon sagte, der Dereferenzierstern macht den Unterschied. 
Hier wird also nicht der Pointer befragt, sondern das worauf der Pointer 
zeigt.

In C gilt die Regel:
0 wird als logisch falsch gewertet, alles was nicht 0 ist gilt als 
logisch wahr.

Und da kommt jetzt ins Spiel, wie in C Strings aufgebaut sind.
Strings sind nichts anderes als eine Abfolge von Zeichen (die in Form 
ihres ASCII Code gespeichert sind, alles ist in einem Computer letzten 
Endes immer nur eine Zahl), die mit einem 0-Byte abgeschlossen wird.

Hast du also den String
"Hallo World"
dann steht der so im Speicher
1
    +---+---+---+---+---+---+---+---+---+---+---+---+
2
    | H | a | l | l | o |   | W | o | r | l | d |\0 |
3
    +---+---+---+---+---+---+---+---+---+---+---+---+

d.h. eigentlich steht er nicht so im Speicher, sondern die Zeichen 
stehen in Form ihres ASCII Codes dort
1
    +---+---+---+---+---+---+---+---+---+---+---+---+
2
    | 48| 61| 6C| 6C| 6F| 20| 57| 6F| 72| 6C| 64| 00|
3
    +---+---+---+---+---+---+---+---+---+---+---+---+

und es ist genau dieses abschliessende Byte mit dem Wert 0x00 (in 
C-Schreibweise als Zeichen '\0' geschrieben), welches dafür sorgt, dass 
die Schleife hier
1
  while( *cData )
2
...
abbricht. Denn ein Wert von 0 (der ja im Speicher ganz hinten im String 
steht und auf den der Pointer irgendwann mal zeigen wird, wenn er 
laufend erhöht wird) gilt ja als logisch falsch. Man könnte die 
Schleifenbedingung auch so formulieren
1
  while( *cData != '\0' )
2
...
das wäre genau dasselbe aussagt bzw. macht.
In C ist das oft eine Gratwanderung, ob man den Vergleich != 0 explizit 
hinschreibt oder nicht, denn der ist bei der Auswertung eines Ausdrucks, 
der als Bedingung für irgendwas benutzt wird, sowieso automatisch mit 
drinnen.


BTW:
Teile dir deine Stringausgabefunktion auf
1
void Disp_Char(char c)
2
{
3
  PORTB = (1 << RS); // Data Mode vorbeireiten; setze RS high
4
5
  SPDR = c;                    // Starte übertragung
6
  while(!(SPSR & (1<<SPIF)));  // Warte auf ende der Übertragung
7
    
8
  //Übertragung abschließen durch RS toggle
9
  PORTB &= ~(1 << RS); //low
10
  PORTB = (1 << RS); // high
11
  _delay_us(50); // warte auf Display
12
}
13
    
14
void Disp_String(char *cData)
15
{
16
  while (*cData)
17
    Disp_Char( *cData++ );
18
}

denn eine Funktion die ein einzelnes Zeichen ausgeben kann, ist genauso 
nützlich, wie eine die einen String ausgeben kann.

von Karl H. (kbuchegg)


Lesenswert?

1
    for(uint8_t i=0; i<50 ;i++)  // Delaytime 5 seconds
2
    {
3
      _delay_ms(100);
4
    }

brauchst du nicht so kompliziert machen.
Es gab mal eine Beschränkung für _delay_ms. Aber seit langer, langer 
Zeit ist die aufgehoben. Heute kannst du problemlos ganz einfach
1
   _delay_ms( 5000 );
schreiben.

von S. L. (lonci)


Angehängte Dateien:

Lesenswert?

@ Karl Heinz: Danke für deine ausführliche Erklärung!

Ich habe noch eine Frage zu den Adressen des Pointers bzw. der 
Pointervariablen.

Beim Debuggen im Atmel-Studio stehen bei mir folgende Werte im RAM:
(siehe Abbildung)

Hier meine eigene Interpretation:

1. Der String "Hello World" steht nach dem flashen im RAM an den 
Adressen 0x0100 bis 0x010B (inkl.0-Byte).

2. Die Pointervariable selbst steht an der Adresse 0x0490. Der Inhalt 
dieser Adresse ist der Wert der Pointervariablen.

Habe ich das so richtig verstanden?

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.