www.mikrocontroller.net

Forum: GCC Problem mit Progmem und LED-Matrix


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Valentin Buck (nitnelav) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
in meinem Projekt verwende ich eine LED-Matrix, auf der ich Zahlen 
ausgeben möchte.
Dafür habe ich die Ziffern von 0 bis 9 jeweils einzeln als
8-bit-Integer-Array im Progmem abgelegt.

In einer Funktion lade ich diese nun aus dem Speicher und gehe Byte für 
Byte ab. Wenn das Byte '1' ist, dann setze ich einen Pixel, wenn '0', 
dann nicht.

Das funktioniert für die Ziffern 0, 3,4,5,6,7,8 und 9 auch ganz toll, 
nur leider werden bei 1 und zwei nur merkwürdige Symbole angezeigt.

Die Symbole habe ich in einer Header-Datei definiert:
#include <avr/pgmspace.h>

const uint8_t one[3][5] PROGMEM= 
{{0,0,0,0,0},
{0,0,0,0,0},
{1,1,1,1,1}};

const uint8_t two[3][5] PROGMEM=
{{1,0,1,1,1},
{1,0,1,0,1},
{1,1,1,0,1}};

const int three[3][5] PROGMEM=
{{1,0,1,0,1},
{1,0,1,0,1},
{1,1,1,1,1}};

//...

Die Routine, mit der ich ein Symbol zeichne sieht so aus:
void writeSign(int px, int py, int* sign[3][5], uint8_t color){
   for (int x = 0; x < 3; x++) {
                for (int y = 0; y < 5; y++) {
                    if (pgm_read_byte(&(sign[x][y])) > 0)
                     plot(px +x, py +y, color);
                    else
                       plot(px +x, py +y, BLACK);

                }
               
            }
}

Wenn ich nun diesen void aufrufe, dann kann ich eine 3 zeichnen, aber 
keine 1 oder 2.

Das hier:
writeSign(0,0, &one, GREEN);
writeSign(4,0, &two, RED);
writeSign(8,0, &three, ORANGE);

Führt zur folgenden Displayausgabe (X für LED an):
 XX XX  XXX
 XX XX    X
 XX XX  XXX
  X       X
 X      XXX


Könnt ihr mir sagen, was ich da falsch mache?

Mit freundlichen Grüßen,
Valentin Buck

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Valentin Buck schrieb:

> Wenn ich nun diesen void aufrufe, dann kann ich eine 3 zeichnen,

das ist maximal Zufall

Das hier

void writeSign(int px, int py, int* sign[3][5], uint8_t color){

besagt, dass sign ein 3*5 Array ist, und in diesem Array sind Pointer 
auf int abgelegt. Das hast du aber nicht. Du hast in deinem Array keine 
Pointer, du hast dort uint8_t abgelegt.

Also

void writeSign(int px, int py, uint8_t sign[3][5], uint8_t color){


Der Rest der Funktion kann nach schnellem drüberschauen so bleiben wie 
er ist.

Aufrufseitig

writeSign(0,0, &one, GREEN);

No, kein &. Arrays werden sowieso immer übergeben, in dem die 
Startadresse des Arrays übergeben wird. Da brauchst du (und sollst) du 
nicht selbst den AdressOf Operator anwenden.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Valentin Buck schrieb:
> Wenn ich nun diesen void aufrufe, dann kann ich eine 3 zeichnen, aber
> keine 1 oder 2.

Weil die unterschiedlich definiert sind (2* 8Bit-, 1* 16Bit-Array).


3*5*16 Bit (int) ist ziemlich verschwenderisch (1400% zuviel).

3*5 = 15Bit, da reicht ein einziges int dicke aus. Die Bitwerte 
ermittelt man mit Schieben.


Peter

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger schrieb:
> Valentin Buck schrieb:
>> Wenn ich nun diesen void aufrufe, dann kann ich eine 3 zeichnen, aber
>> keine 1 oder 2.
>
> Weil die unterschiedlich definiert sind (2* 8Bit-, 1* 16Bit-Array).

tatsächlich. Ist mir entgangen.

Da frag ich mich, wie er das überhaupt durch den Compiler gekriegt hat.

Autor: Valentin Buck (nitnelav) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank,
jetzt funktionierts!
Da hab ich wieder was gelernt: Arrays werden nicht mit Pointern 
übergeben!
Danke!

@Peter Dannegger:
Wie würde man das denn machen?
Mit Bitmasken?
Denn da kann man ja wirklich noch viel Speicherplatz sparen (2 Byte 
statt 15)!

Mit freundlichen Grüßen,
Valentin Buck

Autor: Uwe S. (de0508)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

==> Arrays werden nicht mit Pointern übergeben <==

wie sonst ?

Bitte zeige uns noch mal deinen neuen Code. Danke.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Valentin Buck schrieb:
> Vielen Dank,
> jetzt funktionierts!
> Da hab ich wieder was gelernt: Arrays werden nicht mit Pointern
> übergeben!

Doch werden sie.
Aber das passiert sowieso.

Und du hast in der Funktion 2 Möglichkeiten das zu schreiben.
Die eine berücksichtigt, dass ein Array als Pointer auf das erste 
Element übergeben wird
void foo( int * data )
{
  printf( "%d", data[0] );
  printf( "%d", data[1] );
}

int main()
{
  int check[2] = { 2, 3 );

  foo( check );
}

während die andere in der Argumentliste durch die andere Schreibweise 
etwas besser ausdrückt, dass ein Array erwartet wird
void foo( int data[] )
{
  printf( "%d", data[0] );
  printf( "%d", data[1] );
}

int main()
{
  int check[2] = { 2, 3 );

  foo( check );
}

Passieren tut aber in beiden Fällen genau das gleiche: es wird ein 
Pointer übergeben. Die [] Schreibweise ist nur syntaktischer Zucker.


> Danke!
>
> @Peter Dannegger:
> Wie würde man das denn machen?
> Mit Bitmasken?

Ein ganzes Byte kann 8 Pixel darstellen. Du musst die Bits nur 
rausholen. Ganz stink normale Bitoperationen, wie sie in jedem 
AVR-Programm massenhaft vorkommen.

Bitmanipulation

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void writeSign(int px, int py, uint16_t pattern, uint8_t color){
   for (int x = 0; x < 3; x++) {
                for (int y = 0; y < 5; y++) {
                    if (pattern & 1)                // LSB first
                     plot(px +x, py +y, color);
                    else
                       plot(px +x, py +y, BLACK);
                    pattern >>= 1;                  // next bit
                }
               
            }
}

pattern ist der 16Bit Wert (Bit 0 .. 14), einen Pointer brauchst Du 
nicht mehr.


Peter

Autor: Valentin Buck (nitnelav) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Erklärung und den Lösungsansatz!
Das spart für alle Zeichen so etwa 500 Bytes Programmspeicher!

Ich hab dann mal einen Generator für Zeichen im 3x5-Font geschrieben.
Wer so was braucht, kann ihn hier runterladen:
http://apexys-toan.blogspot.com/2011/08/simple-3x5...

Nochmals vielen Dank!

Mit freundlichen Grüßen,
Valentin Buck

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.