Forum: PC-Programmierung LCD Display - Ausgabe mittels Char Array


von Elektrotiger (Gast)


Lesenswert?

Ein Array von Charactern soll am LCD Display ausgegeben werden.
Aktuell wird nur der Erste Buchstaben angezeigt.
lcd_string(const char* data) ist der Befehl dazu.
Nach Tastendrücken, wird das Array Lauftext aktualisiert. Dabei wird 
jeder Buchstaben bei hinzufügen eines neuen Buchstabens bei der Ausgabe 
um eins nach Rechts verschoben und die 2. Stelle bleibt immer leer!

Ausgabebeispiel: A
                 B A
                 B BA
                 C BBA
1
char lauftext[16];
2
char* plauftext = lauftext;
3
 
4
void text(char* test)
5
{
6
  for(uint8_t j=6;j<8;j++)
7
  {
8
    for(uint8_t i=2;i<16;i++)
9
    {
10
      test[i+1]=test[i]; // Zeile um eins verschieben
11
    }
12
    test[2]=test[0];     // 2. Feld immer leer !!
13
    if((adc[j]<256) && flag_high[j])
14
    {
15
      if(j==6) test[0]='A';
16
      else if(j==7) test[0]='B';
17
      flag_high[j]=0;
18
    }
19
    else if(adc[j]>255)flag_high[j]=1;
20
  }
21
}
22
23
int main()
24
{ [...]
25
          case 1:  // Standardbetrieb
26
  {
27
            for(uint8_t m=0; m<ADCINPUTS; m++)
28
      {
29
        adc[m] = ADC_Read_Avg(m,5);
30
      }
31
      text(plauftext);  // lauftext array wird aktualisiert
32
      lcd_setcursor(0,1);
33
      lcd_string(plauftext); // Displayaktualisierung
34
        }
35
}

von Karl H. (kbuchegg)


Lesenswert?

1
    for(uint8_t i=2;i<16;i++)
2
    {
3
      test[i+1]=test[i]; // Zeile um eins verschieben
4
    }

Vorsicht!
Array Überlauf!

Dein Array wurde mit einer Länge von 16 definiert.
Hier wird i als Maximalwert den Wert 15 annehmen. D.h. i+1 ergibt 16. 
Ein Array Element mit dem Index 16 existiert aber nicht.
1
    test[2]=test[0];     // 2. Feld immer leer !!

das ist nicht leer.
Nur weil du am LCD nichts sehen willst, heist das noch lange nicht, dass 
das Array Element leer ist. Ein Leerzeichen ist ein Buchstabe wie jeder 
andere auch. Und wenn du ein Leerzeichen haben willst, dann musst du 
auch eines an die entsprechende Stelle im Array einfügen.
Ansonsten steht bei einem global allokierten char-Array lauter 0-Bytes 
in den entsprechenden Array Elementen. Und ein 0-Byte in einem String 
bedeutet nun mal, dass der String an dieser Stelle zu Ende ist. Hast du 
also von Anfang an in lauftext[1] ein 0-Byte stehen, dann verändert sich 
das durch deine Manipulationen nicht. Das 0-Byte bleibt genau dort 
stehen und somit ist für alle String-Funktionen dort der String zu Ende.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

1
char lauftext[16];
2
char* plauftext = lauftext;

die Pointer Variable braucht kein Mensch.
1
      text(lauftext);
ist völlig ok. Siehe jedes noch so grindige C-Lehrbuch über Array 
Handling.

von Elektrotiger (Gast)


Lesenswert?

Das ist mir alles klar. Und nein, dass Array hat 16 Elemente, wird 
allerdings von 0 angefangen zu zählen. Also ist es richtig bis i<16 zu 
laufen.

Und mir ist auch bewusst, dass Leerzeichen auch keine Eigentliche 
Leerstelle ist. Es soll, ja auch ein Leerzeichen an dieser Stelle 
ausgegeben werden ;).

von Karl H. (kbuchegg)


Lesenswert?

Elektrotiger schrieb:
> Das ist mir alles klar. Und nein, dass Array hat 16 Elemente, wird
> allerdings von 0 angefangen zu zählen. Also ist es richtig bis i<16 zu
> laufen.

so, so.
i wird maximal 15. Was ergibt dann i + 1
1
    for(uint8_t i=2;i<16;i++)
2
    {
3
      test[i+1]=test[i]; // Zeile um eins verschieben
4
           ***
5
           ***
6
    }

Im letzten Schleifendruchlauf läuft es dann auf
1
     test[15+1] = test[15];
hinaus.
15+1 ergibt 16. Also
1
     test[16]=test[15];

existiert test[16]?

Nein.


> Und mir ist auch bewusst, dass Leerzeichen auch keine Eigentliche
> Leerstelle ist. Es soll, ja auch ein Leerzeichen an dieser Stelle
> ausgegeben werden ;).

Und wo machst du das.
In dem Codeschnipsel ist das nicht erkennbar.

: Bearbeitet durch User
von Elektrotiger (Gast)


Lesenswert?

Karl Heinz schrieb:
> ist völlig ok. Siehe jedes noch so grindige C-Lehrbuch über Array
> Handling

Nicht, wenn ein Mikrocontroller begrenzten Speicher besitzt

von Karl H. (kbuchegg)


Lesenswert?

Elektrotiger schrieb:
> Karl Heinz schrieb:
>> ist völlig ok. Siehe jedes noch so grindige C-Lehrbuch über Array
>> Handling
>
> Nicht, wenn ein Mikrocontroller begrenzten Speicher besitzt

An deiner Stelle würde ich mich mit deinen begrenzten mangelhaften C 
Kenntnisse nicht mit mir anlegen.

von Elektrotiger (Gast)


Lesenswert?

Karl Heinz schrieb:
> Und wo machst du das.
> In dem Codeschnipsel ist das nicht erkennbar.

Kann schlecht 1000 Zeilen Code zeigen :(.
Aber danke, habe in der Schleife nicht mehr daran gedacht. Den Überlauf 
muss ich abfangen.
Leerzeile wird vorher im Programm schon definiert.

Das löst, aber alles mein Problem bisher nicht. Es wird immer noch nur, 
das Erste Symbol angezeigt.

von Karl H. (kbuchegg)


Lesenswert?

Elektrotiger schrieb:

> Kann schlecht 1000 Zeilen Code zeigen :(.

Dann speck auf das wesentliche ab, aber so dass der Code vollständig 
ist.

> Leerzeile wird vorher im Programm schon definiert.
Das kann ich dir glauben oder auch nicht.
Wie hast du die Leerzeile definiert?

> Das löst, aber alles mein Problem bisher nicht. Es wird immer noch nur,
> das Erste Symbol angezeigt.

Weil dein Programm fehlerhaft ist.
Ganz einfach.

von Karl H. (kbuchegg)


Lesenswert?

OK.
Machen wirs kurz
1
void text(char* test)
2
{
3
  for(uint8_t j=6;j<8;j++)
4
  {
5
    for(uint8_t i=2;i<14;i++)
6
//                    **                <------
7
    {
8
      test[i+1]=test[i]; // Zeile um eins verschieben
9
    }
10
    test[15] = '\0';                    // <-------
11
    test[1] = ' ';                      // <-------
12
    test[2] = test[0];
13
...

ist zwar ein wenig Overkill, die Sicherheitsterminierung bzw. das 
Leerzeichen jedesmal wieder neu einzufügen, aber im Vergleich zum 
lcd_string kostet das praktisch nichts. Durch die 2 Schleifendurchläufe 
weniger wird es auf jeden Fall wieder aufgefangen.

: Bearbeitet durch User
von Vlad T. (vlad_tepesch)


Lesenswert?

mir ist der gesamte sinn und zweck des Programmes nicht klar.

In einem Zyklus, werden zuerst alle ADC-Inputs eingelesen (scheinen ja 
mindestens 8 zu sein)

dann wird für den input 6 und 7 jeweils einmal alle character nach 
rechts geschoben und nur ein buchstabe ausgegeben, wenn eine Flanke 
hoch->niedrig auftaucht.

Das heißt, das alte Zeichen wird jeweils kopiert und eventuell 
geupdated.
Ich glaube nicht, dass man dem Display dann irgendwelche sinnvollen 
Informationen entnehmen kann, weil man nicht weiß, ob das das Zeichen 
jetzt da noch vom letzten mal steht, oder in diesem Frame neu gesetzt 
wurde, außerdem wird es in jedem Frame 2 mal bewegt, aber nur der adc[7] 
input wird vom anderen abgetrennt dargestellt ....

komisches Interface.



Ansonsten würde ich dem TO empfehlen ein wenig mehr Demut an den Tag zu 
legen.
Als Anfänger kann man nicht alles wissen, das wirft dir auch niemand 
vor, aber dann die Helfenden belehren zu wollen, und dann noch in so 
einem Ton...

von Elektrotiger (Gast)


Lesenswert?

Funktioniert leider nicht. Sobald ich eine Zuweisung für das Array 
festlege. Wie z.B. lauftext[1]=' ';
Schwimmt das Display, sprich es gibt Zufällige Sonderzeichen und dass so 
schnell hintereinander neue, dass man da nichts mehr erkennt.
1
char lauftext[16];
2
char* plauftext = lauftext;
3
4
5
void text(char* test)
6
{
7
8
  for(uint8_t i=2;i<15;i++)
9
  {
10
    test[i+1]=test[i];  // Zeile um eine Darstellung verschieben
11
  }
12
  test[2]=test[0]; // 2. Feld immer leer !!
13
  for(uint8_t j=6;j<8;j++)
14
  {
15
    if((adc[j]<256) && flag_high[j])
16
    {
17
      if(j==6) test[0]='A';
18
      else if(j==7) test[0]='B';
19
      flag_high[j]=0;
20
    }
21
    else if(adc[j]>255)flag_high[j]=1;
22
  }
23
}
24
25
int main( void )
26
{
27
  lauftext [1]=' ';
28
  lauftext [15]='\0';
29
[...]
30
case 1:  // Standardbetrieb
31
          {
32
            for(uint8_t m=0; m<ADCINPUTS; m++)
33
            {
34
              adc[m] = ADC_Read_Avg(m,5);
35
            }
36
            text(plauftext);  // lauftext array wird aktualisiert
37
            lcd_setcursor(0,1);
38
            lcd_string(plauftext);
39
}

: Bearbeitet durch User
von Vlad T. (vlad_tepesch)


Lesenswert?

Karl Heinz schrieb:
> ist zwar ein wenig Overkill, die Sicherheitsterminierung bzw. das
> Leerzeichen jedesmal wieder neu einzufügen,

dann reicht aber auch eine 13, wenn du die [15] sowiso überschreibst :)

Aber ich denke, der Puffer sollte eins länger gemacht werden, weil das 
Display ja wahrscheinlich 16 Zeichen hat.

von Elektrotiger (Gast)


Lesenswert?

Vlad Tepesch schrieb:
> Das heißt, das alte Zeichen wird jeweils kopiert und eventuell
> geupdated.
> Ich glaube nicht, dass man dem Display dann irgendwelche sinnvollen
> Informationen entnehmen kann, weil man nicht weiß, ob das das Zeichen
> jetzt da noch vom letzten mal steht, oder in diesem Frame neu gesetzt
> wurde, außerdem wird es in jedem Frame 2 mal bewegt, aber nur der adc[7]
> input wird vom anderen abgetrennt dargestellt ....
>
> komisches Interface.

Liegt daran, dass der Prototyp nur 2 angesteuerte ADC Eingänge besitzt 
und die anderen Pins zum testen anderweitig genutzt werden.

Das ergibt so wie es geplant ist für unsere Zwecke Sinn.

Nochmal es geht mir nicht darum den Code schöner zu gestalten, sondern 
Allgemein zu Wissen warum nur das Erste Symbol angezeigt wird.

von Elektrotiger (Gast)


Lesenswert?

Vlad Tepesch schrieb:
> Aber ich denke, der Puffer sollte eins länger gemacht werden, weil das
> Display ja wahrscheinlich 16 Zeichen hat.

Richtig, habe ich übernommen.

von Vlad T. (vlad_tepesch)


Lesenswert?

Vlad Tepesch schrieb:
> dann reicht aber auch eine 13, wenn du die [15] sowiso überschreibst :)

ach ist ja quatsch, steht ja <14

von Volker S. (vloki)


Lesenswert?

De

Elektrotiger schrieb:
> Nochmal es geht mir nicht darum den Code schöner zu gestalten, sondern
> Allgemein zu Wissen warum nur das Erste Symbol angezeigt wird.

Schon mal was von "debuggen" gehört ?

: Bearbeitet durch User
von Vlad T. (vlad_tepesch)


Lesenswert?

Elektrotiger schrieb:
> Das ergibt so wie es geplant ist für unsere Zwecke Sinn.

das bezweifele ich, weil sich komplett unterschiedliche Situationen mit 
diesem Output nicht unterscheiden lassen.


zB bei gleichbleibendem Signal 7 kannst du nicht sagen, ob sich 6 
ändert, weil da nur As stehen werden, egal wie sich 6 verändert. high 
geht, low geht, so bleibt oder wild toggelt - sieht alles gleich aus.
vice versa

von Karl H. (kbuchegg)


Lesenswert?

Elektrotiger schrieb:
> Funktioniert leider nicht. Sobald ich eine Zuweisung für das Array
> festlege. Wie z.B. lauftext[1]=' ';
> Schwimmt das Display, sprich es gibt Zufällige Sonderzeichen und dass so
> schnell hintereinander neue, dass man da nichts mehr erkennt.

Wer weiss schon, welche sonstigen Array Überläufe du sonst noch so in 
deinem Programm hast.

: Bearbeitet durch User
von Elektrotiger (Gast)


Lesenswert?

Vlad Tepesch schrieb:
> zB bei gleichbleibendem Signal 7 kannst du nicht sagen, ob sich 6
> ändert, weil da nur As stehen werden, egal wie sich 6 verändert. high
> geht, low geht, so bleibt oder wild toggelt - sieht alles gleich aus.
> vice versa

Das ist richtig, aber für uns irrelevant bzw sogar gewünscht.
Beim Drücken eines Knopfes liegt High an. Sollte ein Dauersignal 
anliegen, wissen wir, dass ein Fehler vorliegt. Sprich ein Bruch im LWL 
Kabel oder Taste hängt fest ;).

von Karl H. (kbuchegg)


Lesenswert?

1
void text(char* test)
2
{
3
4
  for(uint8_t i=2;i<15;i++)
5
//                  **
6
  {
7
    test[i+1]=test[i];  // Zeile um eine Darstellung verschieben
8
  }

Immer noch falsch.
Damit überschreibst du dir irgendwann die 0-Terminierung von hier
1
int main()
2
{
3
  ....
4
  lauftext [15]='\0';

von Elektrotiger (Gast)


Lesenswert?

Habs... ist kein Syntaxfehler, sondern Logischer Fehler.
Habe die Leerstelle rekursiv nach rechts weiter kopiert.
Also Element 2 zu 3 und dann 3 zu 4 welches ja schon 2 ist.

von Karl H. (kbuchegg)


Lesenswert?

Elektrotiger schrieb:
> Habs... ist kein Syntaxfehler, sondern Logischer Fehler.

Sagen wir mal:
Das kommt auch noch dazu.

(und eigentlich eine Schande für mich, dass ich es nicht gesehen habe).

von Vlad T. (vlad_tepesch)


Lesenswert?

Elektrotiger schrieb:
> Habs... ist kein Syntaxfehler, sondern Logischer Fehler.
syntaxfehler hätte der Compiler ja mit größter Wahrscheinlichkeit 
bemängelt, oder eventuell wenigstens gewarnt.

> Habe die Leerstelle rekursiv nach rechts weiter kopiert.
> Also Element 2 zu 3 und dann 3 zu 4 welches ja schon 2 ist.

Nicht die Leerstelle, das entsprechende Zeichen.
nach der ersten Flanke, sollte ja da aber ein Buchstabe stehen, der 
kopiert wird.
Wenn da also vorher ein Fehler war, der dir nur das erste Zeichen 
ausgegeben hat, sollte der jetzt ja immer noch da sein.

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.