Datum:
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
Datum:
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.
Datum:
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
Datum:
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.
Datum:
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
Datum:
Hallo, ==> Arrays werden nicht mit Pointern übergeben <== wie sonst ? Bitte zeige uns noch mal deinen neuen Code. Danke.
Datum:
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
Datum:
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
Datum:
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