Forum: Mikrocontroller und Digitale Elektronik Text in 2D Arrays, stm32f4xx


von Ma B. (drumstick)


Lesenswert?

Guten Tag

Bei meinem Projekt(c, mdk5, Keil, stm32f4xx) geht es darum eine kleine 
Bedienung zu erstellen. Es soll ein Display angesteuert werden. Die 
Texte sollen in ein FRAM abgelegt werden. Da sechs Sprachen erforderlich 
sind, dachte ich an ein 2D Array. Das Display hat 2 Zeilen, 16 Zeichen, 
ASCII-Code. Um es einfach zu halten stelle ich mir folgendes vor:



Dies wäre die Struktur, die dann ins FRAM abgelegt wird. (Auszugsweise)
1
#define STRING_LENGTH 17
2
#define CNT_LANGUAGES 6
3
4
5
typedef struct  {
6
                  size_t        SetupVersion;
7
                  char          txt_run_RunOpen[CNT_LANGUAGES][STRING_LENGTH];
8
                }
9
                tSetup;
10
11
12
// ---- exported data --
13
14
extern tSetup      setup;


Und im Init_Setup würde dann das Array beschrieben.
1
void Setup_Init(void)
2
{
3
   setup.txt_run_RunOpen[0][0] = {{'M'}};
4
   setup.txt_run_RunOpen[0][1] = {{'a'}};
5
   setup.txt_run_RunOpen[0][2] = {{'c'}};
6
   setup.txt_run_RunOpen[0][3] = {{'h'}};
7
   setup.txt_run_RunOpen[0][4] = {{'i'}};
8
   setup.txt_run_RunOpen[0][5] = {{'n'}};
9
   setup.txt_run_RunOpen[0][6] = {{'e'}};
10
   setup.txt_run_RunOpen[0][7] = {{' '}};
11
   setup.txt_run_RunOpen[0][8] = {{'R'}};
12
   setup.txt_run_RunOpen[0][9] = {{'u'}};
13
   setup.txt_run_RunOpen[0][10] = {{'n'}};
14
   setup.txt_run_RunOpen[0][11] = {{' '}};
15
   setup.txt_run_RunOpen[0][12] = {{'o'}};
16
   setup.txt_run_RunOpen[0][13] = {{'p'}};
17
   setup.txt_run_RunOpen[0][14] = {{'e'}};
18
   setup.txt_run_RunOpen[0][15] = {{'n'}};
19
}
usw.

Micht dünkt dies sehr aufwendig! Andererseits ist das Senden der ASCII 
Zeichen auf den i2c Bus einfach.
1
for(x = 0;x <= 15; x++)
2
  {
3
    LCD_wr_Data(setup.txt_run_RunOpen[0][x]);
4
  }

Hat jemand eine Idee, wie man dies vereinfachen kann.

Vielen Dank schon mal

: Bearbeitet durch User
von Ma B. (drumstick)


Lesenswert?

oder andere Frage, wie kriege ich
1
#define STRING_LENGTH 17
2
#define CNT_LANGUAGES 6
3
4
typedef struct  {
5
                  size_t        SetupVersion;
6
                  char          txt_run_RunOpen[CNT_LANGUAGES][STRING_LENGTH];
7
                }
8
                tSetup;
9
10
extern tSetup      setup;
11
12
13
setup.txt_run_RunOpen[CNT_LANGUAGES][STRING_LENGTH] = 
14
{{"Machine run open"},
15
 {"Anlage oeffnet  "},
16
 {"Macchina aprire "},
17
 {""},
18
 {""},
19
 {""}};

dazu, dass ich ASCII Zeichen ausgeben kann?
1
for(x = 0;x <= 15; x++)
2
  {
3
    LCD_wr_Data(setup.txt_run_RunOpen[0][x]);
4
  }

Welche Methode ist speichertechnisch die beste Lösung?

Vielen Dank

Grüsse

von Ma B. (drumstick)


Lesenswert?

oder hat mir jemand ein Beispiel wie dies gelöst werden könnte? Ich habe 
nichts gefunden, wo genau dieses Problem beschreibt!

Vielen Dank

Grüsse

MC Bu

von Arne (Gast)


Lesenswert?

hab sowas in der Art mal in D/GB für ein Prüfgerät programmiert. Habe 
eine Tabelle wie Du im 2. Post angelegt. Ist auch einfacher zu 
editieren.

von Ma B. (drumstick)


Lesenswert?

Ok, vielen Dank!

Hast Du die Zeichen in den Ascii Code gewandelt für die Ausgabe?

Danke und Gruss

MC Bu

von Route_66 H. (route_66)


Lesenswert?

MC Bu schrieb:
> Hast Du die Zeichen in den Ascii Code gewandelt für die Ausgabe?

Die Frage habe ich nicht verstanden. Die Zeichen sind doch bereits im 
ASCII Code!?

von Dr. Sommer (Gast)


Lesenswert?

MC Bu schrieb:
> Die Texte sollen in ein FRAM abgelegt werden.
Wozu denn der Aufwand... Warum nicht einfach alle Texte ins Flash und 
die der gewünschten Sprache direkt von da direkt auf den I²C oder 
wasauchimmer ausgeben?

von Ma B. (drumstick)


Lesenswert?

@ Dr. Sommer

Ja, diesbezüglich habe ich meine Meinung auch geändert. Die Texte werden 
ja nicht mehr verändert und es muss nur darauf zugegriffen werden.

@Route66
1
setup.txt_run_RunOpen[CNT_LANGUAGES][STRING_LENGTH] = 
2
{{"Machine run open"},
3
 {"Anlage oeffnet  "},
4
 {"Macchina aprire "},
5
 {""},
6
 {""},
7
 {""}};

wie geb ich jetzt einzelne Zeichen des Strings aus? Ich hab da einen 
Knopf in der Leitung.
1
for(x = 0;x <= 15; x++)
2
  {
3
    LCD_wr_Data(setup.txt_run_RunOpen[0][x]);
4
  }
1
void LCD_wr_Data(uint8_t data)
2
{
3
  LCD_wr(true, data);
4
}
1
void LCD_wr(bool dataReg, uint8_t data)
2
{
3
  ExtPort.pin.P14_RS       = dataReg;
4
  ExtPort.pin.P15_R_nW     = false;
5
  ExtPort.pin.P16_E       = true;
6
  ExtPort.pin.P10_Dnibble = data / 0x10;
7
  xferToPortexpander();
8
  
9
  ExtPort.pin.P16_E       = false;
10
  xferToPortexpander();
11
  
12
  ExtPort.pin.P16_E       = true;
13
  ExtPort.pin.P10_Dnibble = data & 0x0f;
14
  xferToPortexpander();
15
  
16
  ExtPort.pin.P16_E       = false;
17
  xferToPortexpander();
18
}

so erhalte ich nur schwarze Zeichen auf dem Display!

Vielen Dank und Gruss

von Karl H. (kbuchegg)


Lesenswert?

MC Bu schrieb:

> wie geb ich jetzt einzelne Zeichen des Strings aus?

So wie immer.

> Ich hab da einen
> Knopf in der Leitung.
>
>
1
> for(x = 0;x <= 15; x++)
2
>   {
3
>     LCD_wr_Data(setup.txt_run_RunOpen[0][x]);
4
>   }
5
>

Im Prinzip schon richtig.
Nur gibt man halt nicht einfach fix 15 Zeichen aus. Schliesslich sagt ja 
kein Mensch, dass alle Texte 15 Zeichen lang sind.

C definiert, dass ein String genau dort zu Ende ist, wo sich das '\0' 
Zeichen befindet.

Also
1
   x = 0;
2
   while( setup.txt_run_RunOpen[0][x] != '\0' )
3
   {
4
     LCD_wr_Data(setup.txt_run_RunOpen[0][x]);
5
     x++;
6
   }

oder ein wenig intelligenter unter Verwendung der Pointer-Schreibweise
1
    const char* ptr = &setup.txt_run_RunOpen[0][0];
2
3
    while( *ptr != '\0' )
4
      LCD_wr_Data( *ptr++ );


> so erhalte ich nur schwarze Zeichen auf dem Display!

Wenn dein allererstes Original funktioniert hat, dann muss auch das 
gehen.


char str[8] = "test";

ist schliesslich auch nichts anderes als

str[0] = 't';
str[1] = 'e';
str[2] = 's';
str[3] = 't';
str[4] = '\0';

nur dass der Compiler die ganze Arbeit für dich in der 
Initialisierungsphase macht.

von Karl H. (kbuchegg)


Lesenswert?

Zeig doch bitte mal den Originalcode.

Denn das hier
1
typedef struct  {
2
                  size_t        SetupVersion;
3
                  char          txt_run_RunOpen[CNT_LANGUAGES][STRING_LENGTH];
4
                }
5
                tSetup;
6
7
extern tSetup      setup;
8
9
10
setup.txt_run_RunOpen[CNT_LANGUAGES][STRING_LENGTH] = 
11
{{"Machine run open"},
12
 {"Anlage oeffnet  "},
13
 {"Macchina aprire "},
14
 {""},
15
 {""},
16
 {""}};

kann er recht offensichtlich nicht sein. Das compiliert nämlich mit 
Sicherheit nicht. Du kannst nicht setup.txt_run_RunOpen einzeln 
initialisieren.

von Ma B. (drumstick)


Lesenswert?

Stimmt, hab ich nicht compiliert. Dies bedeutet ich muss den String bei 
der definition initialisieren. Oder ich kann nur einzelne Zeichen laden?
1
Setup.startup_Text_line1[0][0] = 'M';



Ich möchte aber alle Textelemente in einem Struct vereinen. Wie kann ich 
dies lösen?

Ansonsten funktioniert es so sehr gut.

Vielen, vielen Dank!

Grüsse

MC Bu

von Karl H. (kbuchegg)


Lesenswert?

MC Bu schrieb:
> Stimmt, hab ich nicht compiliert. Dies bedeutet ich muss den String bei
> der definition initialisieren.

Es ist das vernünftigste.

> Oder ich kann nur einzelne Zeichen laden?

Kannst du auch. Aber dann ist es erstens keine Initalisierung mehr und 
zweitens machst du dir eine Menge Arbeit

>
1
> Setup.startup_Text_line1[0][0] = 'M';
2
>

kann man machen. Man kann aber auch

   strcpy( Setup.startup_Text_line1[0], "Meine Idee" );

machen :-)

Ist ein bischen einfacher.
Vielleicht solltest du doch erst mal im C-Buch deiner Wahl nachlesen, 
wie Stringverarbeitung in C überhaupt funktioniert?

> Ich möchte aber alle Textelemente in einem Struct vereinen. Wie kann ich
> dies lösen?

Genau so, wie das da oben gemacht wurde.

von Dr. Sommer (Gast)


Lesenswert?

Karl Heinz schrieb:
> kann er recht offensichtlich nicht sein. Das compiliert nämlich mit
> Sicherheit nicht. Du kannst nicht setup.txt_run_RunOpen einzeln
> initialisieren.
man kann aber
1
typedef struct  {
2
                  size_t        SetupVersion;
3
                  char          txt_run_RunOpen[CNT_LANGUAGES][STRING_LENGTH];
4
                }
5
                tSetup;
6
7
extern tSetup      setup;
8
9
tSetup setup = {  42,
10
        {{"Machine run open"}, 
11
        {"Anlage oeffnet  "},
12
        {"Macchina aprire "}, 
13
        {""},
14
        {""},
15
        {""}}};
 machen.

von Ma B. (drumstick)


Lesenswert?

Ich kann aber nicht die Stringkette in einem Struct anlegen und 
gleichzeitig initialisieren!
1
typedef struct  {
2
                  size_t        SetupVersion;
3
                  char          startup_Text_line1[STRING_LENGTH];
4
                }
5
                tSetup;
Ausser wie es Dr.Sommer vorgemacht hat! Dies würde ja Sinn machen, da 
ich den struct nur für die Texte anlege. Diese Lösung finde ich 
praktikabel.

Das beste wird es sein, ich lese über struct ebenfalls nach. ich 
beschäftige mich leider bisschen zu wenig mit c.

Vielen Dank für Eure Hilfe!

Grüsse

MC Bu

von Arne (Gast)


Lesenswert?

MC Bu schrieb:
> ich beschäftige mich leider bisschen zu wenig mit c.
Keep it simple - am Anfang. Optimieren kannst Du immer noch. Hauptsache 
Du hast erstmal was am Laufen.

von Karl H. (kbuchegg)


Lesenswert?

MC Bu schrieb:
> Ich kann aber nicht die Stringkette in einem Struct anlegen und
> gleichzeitig initialisieren!

Wo genau machst du das denn?

> Ausser wie es Dr.Sommer vorgemacht hat!

Ja, genau das ist ja auch der Normalfall.

> Das beste wird es sein, ich lese über struct ebenfalls nach. ich
> beschäftige mich leider bisschen zu wenig mit c.

Sieht fast danach aus.

: Bearbeitet durch User
von Ma B. (drumstick)


Lesenswert?

Niergends! Das war nur eine Überlegung!


Jetzt siehts bei mir so aus:

im Text.h
1
typedef struct  {
2
                  char  startup_Text_line1[STRING_LENGTH];
3
                  char  operation_Text_line1[STRING_LENGTH];
4
                  char  operation_Text_line2[STRING_LENGTH];
5
                }
6
              tTxt;
7
8
extern  tTxt Text;


im Text.c
1
void Init_Texte(void)
2
{
3
  tTxt Text = {  {"Hallo Welt"},
4
                 {"Operation is"},
5
                 {"running"}
6
              };
7
}

: Bearbeitet durch User
von Dr. Sommer (Gast)


Lesenswert?

MC Bu schrieb:
> Jetzt siehts bei mir so aus:
Das klappt nicht. Zuweisungen von structs gehen in C nicht. Nur 
initialisierungen, wie ich sie oben gezeigt hab. Wenn deine Texte im 
Flash sind, kannst du sie eh nicht ändern/zuweisen. Braucht man ja auch 
nicht, da 1x initialisieren und im Read-Only-Flash zu lassen ja reicht.

von Dr. Sommer (Gast)


Lesenswert?

Uhps, falsch gelesen, das ist ja die Initialisierung einer lokalen 
Variable... Das geht, ist aber wenig sinnvoll da ineffizient. Und die 
globale "Text" Variable wird gar nicht verwendet...

von Karl H. (kbuchegg)


Lesenswert?

MC Bu schrieb:

> im Text.c
>
1
> 
2
> 
3
> void Init_Texte(void)
4
> {
5
>   tTxt Text = {  {"Hallo Welt"},
6
>                  {"Operation is"},
7
>                  {"running"}
8
>               };
9
> }
10
>


Das ist aber eine lokale Variable.

Auch wenn die zufällig den gleichen Namen hat, wie deine globale, sie 
hat nichts mit der globalen Variablen zu tun.

von Ma B. (drumstick)


Lesenswert?

ups ja, jetzt seh ichs

von Karl H. (kbuchegg)


Lesenswert?

im Text.h
1
typedef struct  {
2
                  char  startup_Text_line1[STRING_LENGTH];
3
                  char  operation_Text_line1[STRING_LENGTH];
4
                  char  operation_Text_line2[STRING_LENGTH];
5
                }
6
              tTxt;
7
8
extern  tTxt Text;

im Text.c
1
#include "Text.h"
2
3
tTxt Text = {  "Hallo Welt",
4
               "Operation is",
5
               "running"
6
            };

und die Funktion Init_Texte braucht keiner.

: Bearbeitet durch User
von Dr. Sommer (Gast)


Lesenswert?

> und die Funktion Init_Texte braucht keiner.
Dann noch "const" dran und es landet schön sparsam im Flash.

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.