Hallo zusammen,
ich habe eine 8x8 Matrix auf der ich einzelne Zeichen dargestellt
bekomme. Nun soll eine Laufschrift her. Dazu habe ich ein paar Fragen.
1. Den anzuzeigenden Text werde ich vermutlich Zeichen für Zeichen
prüfen müssen. Mit anderen Worten nehme ich mir den ersten Buchstaben
und überprüfe ihn auf eine Übereinstimmung mit meinem Font. Dies würde
ich jetzt über eine if Abfrage realisieren, was mir funktional aber
nicht effektiv erscheint. Geht das vielleicht auch einfacher und wenn ja
wie?
2. Momentan ist mein Quellcode so konzipiert, dass ich aus dem Font mir
eine Kopie in ein char PufferArray[8] ziehe. Dieses wird dann auf der
LED Matrix ausgegeben. Ich könnte jetzt dieses Pufferarray linksshiften,
dann würde der Buchstabe rauslaufen. Es würde aber nicht der zweite
Buchstabe hinter laufen. Hier ist mir auch noch keine Lösung
eingefallen.
Vielleicht hat jemand eine einfache und verständliche Lösung für mich.
Vielen Dank.
Le Ha schrieb:> 1. Den anzuzeigenden Text werde ich vermutlich Zeichen für Zeichen> prüfen müssen. Mit anderen Worten nehme ich mir den ersten Buchstaben> und überprüfe ihn auf eine Übereinstimmung mit meinem Font. Dies würde> ich jetzt über eine if Abfrage realisieren, was mir funktional aber> nicht effektiv erscheint. Geht das vielleicht auch einfacher und wenn ja> wie?
Äh.
Du überprüfst nicht auf übereinstimmung mit dem Font, sondern du
organisierst dir den Font so, dass du mit dem ASCII Code des Zeichens
genau auf die zu diesem Zeichen gehörenden Fontdaten zugreifen kannst.
Das Array ist dein Freund!
> 2. Momentan ist mein Quellcode so konzipiert, dass ich aus dem Font mir> eine Kopie in ein char PufferArray[8] ziehe. Dieses wird dann auf der> LED Matrix ausgegeben.
Hoffentlich in einem Interrupt.
Dann sieh dieses Array mal nicht als dein Puffer Array an, sondern
dieses Array IST deine softwareseitige Repräsentierung der Anzeige. Dein
Screen.
Wenn du in diesem Screen 1 Bit setzt, dann leuchtet der Bildpunkt auf.
Wenn du das Bit wieder löscht, dann verlöscht auch wieder der Bildpunkt.
An dieser Stelle weisst du nichts mehr von Zeichen oder dergleichen. Was
auch immer an Bits in deinem Screen gesetzt sind, das leuchtet. Ob das
jetzt Zeichen sind oder eine Grafik, interessiert auf dieser Ebene nicht
mehr. Pixel ist Pixel und wer die auch immer setzt, der setzt sie eben
wie er sie für das Anzuzeigende braucht.
D.h. die Aufgabe ein Zeichen auszugeben besteht dann darin, in diesem
Screen die entsprechenden Bits zu setzen bzw. zu löschen. Bzw. wenn du
den Screen als ganzes nach links oder richts 'schieben' willst, dann
eben die entsprechenden Bitmanipulationen in diesem Screen-Array
vorzunehmen. Ob da dann dahinter eine LED-Matrix steckt, oder
Klapptafelantriebe, oder fallende Wassertropfen, oder ... das
interessiert diesen Programmteil nicht mehr sondern ist Aufgabe des
Programmteils, der die Abbildung des Screens auf die reale Hardware
macht.
Bei einer LED-Matrix macht normalerweise ein Multiplexen in einem Timer-
Interrupt am meisten Sinn für die Übertragung des Screen Arrays an die
real vorhandenen LED.
> dann würde der Buchstabe rauslaufen. Es würde aber nicht der zweite> Buchstabe hinter laufen.
Dann brauchst du eine andere Lösung:
du brauchst zum Beispiel Routinen, der du sagen kannst:
* von diesem Buchstaben brauch ich die rechten x Spalten und zwar brauch
ich die im Screen Array beginnend ab 'dieser' Spalte (normalerweise
beginnend ab 0, also ganz links im Screen Array)
* von diesem Buchstaben brauch ich die linken x Spalten und zwar brauch
ich die im Screen Array beginnend ab 'dieser' Spalte.
D.h. die meiste Zeit zeigt dein Screen Array also 2 Buchstaben an. Die
allerdings nur in Teilen und ja nach aktuellem 'Schiebezustand' in
wechselndem (spaltenmässigem) Anteil.
Man könnte das allerdings auch ganz anders lösen, wenn man wirklich nur
am 'nach links reinschieben' von Text interessiert ist. Man verschiebt
dann eben die jetzige Screen Darstelung um 1 Spalte nach links. Dadurch
wird die ganz rechte Spalte frei und dort kopiert man dann eben die
jeweils nächste Spalte des nächsten Zeichens rein.
Ob das Softwaretechnisch einfacher ist, kann ich nicht sagen.
Wahrscheinlich ist es das. Dafür ist es aber auch unflexibler. Mit den
vorgenannten beiden Funktionen kann man auch noch andere Effekte
erreichen (zb nach rechts scrollen, Scheibenwischereffekte, etc), ist
als ein wenig universeller.
> Vielleicht hat jemand eine einfache und verständliche Lösung für mich.
Selber aufmalen und die entsprechenden Funktionen ausknobeln. Das ganze
ist nicht mehr als eine heftige Anwendung von Bitmanipulationen. Und
Organisation.
Aber mehr ist das nicht.
Le Ha schrieb:> Es würde aber nicht der zweite> Buchstabe hinter laufen.
Dann leg einfach den Puffer für 2 Zeichen an und schiebe diesen in den
sichtbaren Bereich. Und sobald im unsichtbaren Bereich Platz für das
nächste Zeichen ist, schreibe es hinein.
Eine 1-Zeichen Laufschrifft ist allerdings sehr schwer zu lesen. Es
sollte wenigstens ein Wort, besser 2 komplett dargestellt werden.
Le Ha schrieb:> Vielleicht hat jemand eine einfache und verständliche Lösung für mich.
Erst mal grundlegend Programmieren lernen.
Es gibt 2 Varianten:
Entweder du hast genug Speicher für ein char PufferArray[15], dann
kannst du beliebige Pixelmuster über das Display schieben. Ein Zeichen
wird immer per font umgewandelt in eine 8x8 Muster.
Oder du hast zu wenig Speicher, es reicht nur für char
darstellZeichen[2], dann musst du ständig wiederholt aus dem Zeichencode
ermitteln welche Pixel per font gesetzt werden müssen. Damit kannst du
keine beliebigen Pixelmuster über das Display schieben sondern nur die
Zeichen aus dem font.
> nehme ich mir den ersten Buchstaben> und überprüfe ihn auf eine Übereinstimmung mit meinem Font.
?!?
Normal wäre für das Zeichen ch:
1
for(row=0;row<8;row++)
2
{
3
PufferArray[row]=font[ch][row];
4
}
Da wird nicht gesucht, es gibt für alle 256 (oder 128 oder 64) Zeichen
ein Pixelmuster im font.
Ein großes Array anlegen, indem 2 Zeichen platz finden und immer wenn
ein Zeichen rausgeshiftet wurde, ein neues einfügen.
Auf meiner 16x16 Matrix sieht das so aus.
Sehr schwer nachzuvollziehen, selbst für mich. Ich habe natürlich wieder
an Kommentaren gespart.
CopyDisplay shiftet die Anzeige und die andere Funktion füllt ein
Zeichen nach. Ich unterscheide bei den Shifts zwischen kurzen Zeichen
wie einem 'i' und langen Zeichen, damit es optisch besser passt
(fontabhängig).
Edit:
Karl Heinz schrieb:> Äh.> Du überprüfst nicht auf übereinstimmung mit dem Font, sondern du> organisierst dir den Font so, dass du mit dem ASCII Code des Zeichens> genau auf die zu diesem Zeichen gehörenden Fontdaten zugreifen kannst.>> Das Array ist dein Freund!
Hallo Karl-Heinz,
danke zunächst für deine Bereitschaft mir zu helfen. Das freut mich
sehr.
Das Font liegt in einem Array, allerdings nicht im ASCII Code. Ich hatte
doch das Problem, dass ich die 128*8 in meinen ATMEGA8 nicht gespeichert
bekomme. So habe ich den Zeichensatz erstmal um eine Grundfunktion
hinzubekommen auf die notwendigen 26 Buchstaben reduziert.
Der Buchstabe 'A' der im normalen ASCII Code auf 0x41 liegt, ist bei mir
jetzt im FontArray auf 0x00.
Wenn ich nun folgenden Text habe, iteriert man jedes Zeichen durch und
gibt es einfach als ASCII Code aus?
Peter Dannegger schrieb:> Eine 1-Zeichen Laufschrifft ist allerdings sehr schwer zu lesen. Es> sollte wenigstens ein Wort, besser 2 komplett dargestellt werden.
Danke für den Hinweis. Das befürchte ich auch. Allerdings reicht es mir
persönlich erstmal wenn eine 8x8 Matrix läuft. Schritt für Schritt, denn
mir fallen leider nicht die Lösungen einfach so aus den Ärmeln.
Le Ha schrieb:> Wenn ich nun folgenden Text habe, iteriert man jedes Zeichen durch und> gibt es einfach als ASCII Code aus?
Jep.
Vielleicht nicht ganz so schnell, sonst kann man nix lesen.
(PS: wie du schon gesehen hast: viele Wege führen nach Rom und wenn ich
so darüber nachdenke, dann hat PeDa wohl die einfachste Variante
gepostet)
Karl Heinz schrieb:> Jep.> Vielleicht nicht ganz so schnell, sonst kann man nix lesen.>> (PS: wie du schon gesehen hast: viele Wege führen nach Rom und wenn ich> so darüber nachdenke, dann hat PeDa wohl die einfachste Variante> gepostet)
Ok dann pack ich wohl noch ein Delay hinzu und versuch das mal. Ich
melde mich später nochmal zu dem Ergebnis oder erbitte um weitere Hilfe.
Danke allen erstmal bis hierhin.
Karl Heinz schrieb:> (PS: wie du schon gesehen hast: viele Wege führen nach Rom und wenn ich> so darüber nachdenke, dann hat PeDa wohl die einfachste Variante> gepostet)
Anstatt einem char
1
charleds[8]={0b11111000,\
2
0b10000000,\
3
0b10000000,\
4
0b10000000,\
5
0b11100000,\
6
0b10000000,\
7
0b10000000,\
8
0b11111000};
nimmst du hier einen uint16_t (und PS: das hier waren einfach nur noch
Bytes. Hier willst du daher nicht den Datentyp 'char' benutzen, sondern
für Bytes immer einen uint8_t)
1
uint16_tleds[8];
und bei der Ausgabe in der ISR gibst du immer nur die oberen 8 Bit von
jedem uint16_t aus
1
...
2
Set_Column(leds[isrZeile]>>8);
3
...
Damit hast du pro Matrix-Zeile 16 Bits, von denen immer nur die oberen 8
Bits die tatsächlichen LED ansteuern
1
###################
2
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
3
leds[0] #| | | | | | | | |#| | | | | | | | |
4
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
5
leds[1] #| | | | | | | | |#| | | | | | | | |
6
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
7
leds[2] #| | | | | | | | |#| | | | | | | | |
8
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
9
leds[3] #| | | | | | | | |#| | | | | | | | |
10
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
11
leds[4] #| | | | | | | | |#| | | | | | | | |
12
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
13
leds[5] #| | | | | | | | |#| | | | | | | | |
14
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
15
leds[6] #| | | | | | | | |#| | | | | | | | |
16
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
17
leds[7] #| | | | | | | | |#| | | | | | | | |
18
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
19
leds[8] #| | | | | | | | |#| | | | | | | | |
20
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
21
###################
22
23
Diese Bits
24
steuern die tatsächliche
25
Anzeige
Was passiert also, wenn du in den rechten Teil (also die unteren 8 Bits
von jedem uint16_t zb das Muster für ein A einschreibst
1
###################
2
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
3
leds[0] #| | | | | | | | |#| |*|*|*|*|*|*| |
4
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
5
leds[1] #| | | | | | | | |#|*| | | | | | |*|
6
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
7
leds[2] #| | | | | | | | |#|*| | | | | | |*|
8
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
9
leds[3] #| | | | | | | | |#|*| | | | | | |*|
10
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
11
leds[4] #| | | | | | | | |#|*| | | | | | |*|
12
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
13
leds[5] #| | | | | | | | |#|*|*|*|*|*|*|*|*|
14
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
15
leds[6] #| | | | | | | | |#|*| | | | | | |*|
16
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
17
leds[7] #| | | | | | | | |#|*| | | | | | |*|
18
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
19
leds[8] #| | | | | | | | |#| | | | | | | | |
20
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
21
###################
und jeden einzelnen uint16_t um 1 Stelle nach links schiebst?
1
###################
2
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
3
leds[0] #| | | | | | | | |#|*|*|*|*|*|*| | |
4
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
5
leds[1] #| | | | | | | |*|#| | | | | | |*| |
6
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
7
leds[2] #| | | | | | | |*|#| | | | | | |*| |
8
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
9
leds[3] #| | | | | | | |*|#| | | | | | |*| |
10
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
11
leds[4] #| | | | | | | |*|#| | | | | | |*| |
12
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
13
leds[5] #| | | | | | | |*|#|*|*|*|*|*|*|*| |
14
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
15
leds[6] #| | | | | | | |*|#| | | | | | |*| |
16
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
17
leds[7] #| | | | | | | |*|#| | | | | | |*| |
18
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
19
leds[8] #| | | | | | | | |#| | | | | | | | |
20
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
21
###################
genau: die erste Spalte vom 'A' hat sich in den sichtabren Bereich
reingeschoben.
Ein weiteres 'jeden uint16_t' um 1 Stelle nach links schieben.
1
###################
2
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
3
leds[0] #| | | | | | | |*|#|*|*|*|*|*| | | |
4
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
5
leds[1] #| | | | | | |*| |#| | | | | |*| | |
6
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
7
leds[2] #| | | | | | |*| |#| | | | | |*| | |
8
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
9
leds[3] #| | | | | | |*| |#| | | | | |*| | |
10
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
11
leds[4] #| | | | | | |*| |#| | | | | |*| | |
12
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
13
leds[5] #| | | | | | |*|*|#|*|*|*|*|*|*| | |
14
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
15
leds[6] #| | | | | | |*| |#| | | | | |*| | |
16
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
17
leds[7] #| | | | | | |*| |#| | | | | |*| | |
18
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
19
leds[8] #| | | | | | | | |#| | | | | | | | |
20
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
21
###################
und die nächste Spalte vom A wird sichtbar.
Nach 8 mal links schieben jedes einzelnen uint16_t, ist das A komplett
im sichtbaren Bereich
1
###################
2
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
3
leds[0] #| |*|*|*|*|*|*| |#| | | | | | | | |
4
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
5
leds[1] #|*| | | | | | |*|#| | | | | | | | |
6
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
7
leds[2] #|*| | | | | | |*|#| | | | | | | | |
8
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
9
leds[3] #|*| | | | | | |*|#| | | | | | | | |
10
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
11
leds[4] #|*| | | | | | |*|#| | | | | | | | |
12
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
13
leds[5] #|*|*|*|*|*|*|*|*|#| | | | | | | | |
14
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
15
leds[6] #|*| | | | | | |*|#| | | | | | | | |
16
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
17
leds[7] #|*| | | | | | |*|#| | | | | | | | |
18
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
19
leds[8] #| | | | | | | | |#| | | | | | | | |
20
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
21
###################
und wird daher auch von den realen LED in seiner ganzen Pracht
angezeigt.
Aber: Der rechte Teil, also die unteren 8 Bit von jedem uint16_t sind
jetzt frei und du kannst dort den jeweils nächsten Buchstaben aus den
Fontdaten einsetzen. Zum Beispiel ein 'E'
1
###################
2
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
3
leds[0] #| |*|*|*|*|*|*| |#| |*|*|*|*|*|*| |
4
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
5
leds[1] #|*| | | | | | |*|#| |*| | | | | | |
6
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
7
leds[2] #|*| | | | | | |*|#| |*| | | | | | |
8
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
9
leds[3] #|*| | | | | | |*|#| |*|*|*|*|*| | |
10
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
11
leds[4] #|*| | | | | | |*|#| |*| | | | | | |
12
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
13
leds[5] #|*|*|*|*|*|*|*|*|#| |*| | | | | | |
14
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
15
leds[6] #|*| | | | | | |*|#| |*| | | | | | |
16
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
17
leds[7] #|*| | | | | | |*|#| |*|*|*|*|*|*| |
18
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
19
leds[8] #| | | | | | | | |#| | | | | | | | |
20
#+-+-+-+-+-+-+-+-+#+-+-+-+-+-+-+-+-+
21
###################
Wieder: alle 8 uint16_t um 1 Stelle nach links verschoben, bewirkt was?
Na, die ganz linke Spalte (vom 'A') fällt raus, und dafür rückt die
erste (linke) Spalte vom 'E' in den sichtbaren Bereich.
Und so geht das weitere 8 mal dahin, bis sich das 'E' komplett in den
sichtbaren Bereich verschoben hat. An dieser Stelle ist dann wieder der
komplette rechte Teil von jedem uint16_t frei und dort kann das nächste
Zeichen mittels Bitoperationen einkopiert werden und wird seinerseits
durch 8 maliges links-Schieben Spalte für Spalte in den sichtbaren
Bereich transportiert.
Und so geht das die ganze Zeit immer weiter: Das Muster für den nächsten
Buchstaben mittels Bitoperationen in den 'rechten' Teil jedes uint16_t
einkopieren und mit entsprechenden Schiebeoperationen von rechts in den
sichtbaren Bereich sukzessive reinschieben, wobei gleichzeitig das
vorher im sichtbaren Bereich gewesene sich Spalte um Spalte links
rausschiebt.
Allerdings: ein simples memcpy wirds da jetzt eben nicht mehr tun, um
das Muster aus den Fontdaten ins Anzeigearray zu kopieren.
Le Ha schrieb:> Ich hatte> doch das Problem, dass ich die 128*8 in meinen ATMEGA8 nicht gespeichert> bekomme.
Fonts gehören in den Flash, nicht in den SRAM.
Ein kompletter 5*8 Font belegt 256 * 5 = 1,3kB, der ATmega8 hat 8kB
Flash, das paßt dicke.
Ansonsten nimm den ATmega328P.
Peter Dannegger schrieb:> Fonts gehören in den Flash, nicht in den SRAM.> Ein kompletter 5*8 Font belegt 256 * 5 = 1,3kB, der ATmega8 hat 8kB> Flash, das paßt dicke.
Danke Peter. Den Tipp hat mir Karl-Heinz an anderer Stelle schon
gegeben. Wenn ich die Laufschrift auf der Matrix sehe, kümmere ich mich
darum das komplette Font in den Flash zu packen - versprochen.
Karl Heinz schrieb:> Allerdings: ein simples memcpy wirds da jetzt eben nicht mehr tun, um> das Muster aus den Fontdaten ins Anzeigearray zu kopieren.
Mit memcpy könnte ich nur arrays gleicher Größe bzw. Format kopieren.
Deswegen muss ich mir jetzt wohl etwas über Schleifen einfallen lassen.
Das habe ich getan und bekleckere mich nicht gerade mit Ruhm.
Ich hab zunächst das leds-Array auf den Datentyp int16_t geändert. In
der while(1) schreibe ich dann aus dem font-Array den Buchstaben in das
niederwertige Byte des leds-Array. Im folgenden verschiebe ich die Bits
8 mal nach links. Damit wandern diese in das höherwertige Byte. Auf der
Matrix macht er bis hierhin auch genau das.
Nun sollte die Schleife von vorne beginnen und der nächste Buchstabe in
das niederwertige Byte geschrieben werden und anschließend verschoben
werden. Anscheinend überschreibt er mir allerdings immer auch das
höhenwertige byte, denn der erste Buchstabe verschwindet urplötzlich.
Warum werden die Bits im MSB so plötzlich gelöscht?
Le Ha schrieb:> Ich hab zunächst das leds-Array auf den Datentyp int16_t geändert. In> der while(1) schreibe ich dann aus dem font-Array den Buchstaben in das> niederwertige Byte des leds-Array.
Nö.
mit
1
for(inti=0;LaufText[i]!='\0';i++)
2
{
3
uint8_tascii_help=LaufText[i]-0x41;
4
5
leds[0]=font[ascii_help][0];
6
leds[1]=font[ascii_help][1];
7
leds[2]=font[ascii_help][2];
8
leds[3]=font[ascii_help][3];
9
leds[4]=font[ascii_help][4];
10
leds[5]=font[ascii_help][5];
11
leds[6]=font[ascii_help][6];
12
leds[7]=font[ascii_help][7];
beschreibst du jeweils den ganzen(!) uint16_t und nicht nur die
niederwertigen Bits.
Ich sagte doch: Mit deinen Bitoperationen musst du schon auf du-und-du
stehen. Ob das jetzt das gezielte Setzen eines einzelnen Bits an einem
Port oder das Überschreiben von einem Byte in einem 2 Byte Wert ist.
Diese Dinge müssen einfach klappen. Mit den binären Operationen UND und
ODER, sowie Bitmasken musst du umgehen können, wenn du µC programmieren
willst. Ist eh immer das gleiche Prinzip: mit einem UND und geeigneter
Maske erzwingt man Bits auf 0. Mit einem ODER und geeigneter Maske
erzwingt man Bits auf 1
zb
1
leds[0]=(leds[0]&0xFF00)|font[ascii_help][0];
und das ganze dann natürlich in einer SChleife anstatt da 8 mal
Copy&Paste
1
for(j=0;j<8;j++)
2
leds[j]=(leds[j]&0xFF00)|font[ascii_help][j];
auch solche Dinge musst du schon sehen können.
> Warum werden die Bits im MSB so plötzlich gelöscht?
weil du bei
1
i=j;
alle Bits von i zugewiesen haben willst!
ist i ein long Wert und j ein int, dann willst du den kompletten i
überschrieben haben. Selbst wenn ja (wegen int) aus 2 Bytes besteht und
i (wegen long) aus 4 Bytes. Hat j den Wert 5, dann soll i nach der
Zuweisung auch den Wert 5 haben. Unabhängig davon welcher Wert vorher in
i gestanden hat. Das ist ja schliesslich die ureigenste Bedeutung einer
Zuweisung: die links Seite der Zuweisung erhält exakt den Wert, der sich
aus der Auswertung der rechten Seite ergibt. Und ja: der Wert, der sich
auf der rechten Seite ergibt kann (und wird) zum Zwecke der Zuweisung an
den Datentyp der linken Seite angepasst.
Karl Heinz schrieb:> zb leds[0] = ( leds[0] & 0xFF00 ) | font[ascii_help][0];
Ok zum Verständnis. Wir nehmen das erste Element des Arrays und
verknüpfen es binär UND mit 0xFF00 bzw. 11111111 00000000. Damit kann
jetzt nur das MSB erfolgreich binär UND verknüpft werden.
Angenommen leds[0] = 0b0011110000000000;
Dann wäre das Ergebnis der UND Verknüpfung 00111100 00000000.
Dieses Zwischenergebnis verknüpfe ich nun ODER mit den entsprechenden
Buchstaben aus der font.
Die Buchstaben aus den font sind alle nur 8 Bit groß. Angenommen
font[ascii_help][0] = 0b01010101;
Die einzelnen Bits werden dann nun in das LSB kopiert, sodass in leds[0]
letztendlich steht 00111100 01010101.
Kann ich denn das 16 Bit Array so einfach mit den 8 Bit Font
Bitverknüpfen?
Danke zunächst mal für deinen super Vorschlag. Auf die Lösung wäre ich
sicher so schnell nicht gekommen, da ich mit den Bitverschiebungen noch
zu wenig Erfahrungen habe.
Die Schleife hatte ich vorher auch schon, hab diese dann aber zur
Fehlersuche rausgenommen.
Ich teste es gleich mal am Controller. Danke
Le Ha schrieb:> Karl Heinz schrieb:>> zb leds[0] = ( leds[0] & 0xFF00 ) | font[ascii_help][0];>> Ok zum Verständnis. Wir nehmen das erste Element des Arrays und> verknüpfen es binär UND mit 0xFF00 bzw. 11111111 00000000. Damit kann> jetzt nur das MSB erfolgreich binär UND verknüpft werden.
Nö.
Damit werden gezielt im Ergebnis alle Bits, bei denen in der Maske eine
0 war, auf 0 gezwungen.
Das ist im Grunde nur eine Sicherungsmassnahme, falls du aus irgend
einem Grund noch nicht den kompletten Buchstaben ins obere Byte
geschoben hast. Zb. Weil du die Laufschrift komplett abwürgen willst und
einen neuen Text reingeschoben haben willst.
> Dieses Zwischenergebnis verknüpfe ich nun ODER mit den entsprechenden> Buchstaben aus der font.>> Die Buchstaben aus den font sind alle nur 8 Bit groß. Angenommen> font[ascii_help][0] = 0b01010101;> Die einzelnen Bits werden dann nun in das LSB kopiert
Darauf läuft es hinaus, aber technisch läuft das so ab, dass erst mal
der 8 Bit Wert ebenfalls auf 16 Bit aufgeblasen wird.
Merke: Bei allen Operationen werden immer nur gleiche Datentypen
miteinander verrechnet. Ist einer der Operanden 'kleiner', dann wird er
auf die Größe des anderen Operanden aufgeblasen. Die 00111100 00000000
sind aus einem 16 Bit Wert entstanden und haben auch den Datentyp
uint16_b
Um also einen uint16_t mit einem uint8_t zu verknüpfen (mittels ODER),
wird zuerst der uint8_t ebenfalls auf 16 Bit gebracht. Da es sich dabei
um einen unsigned Wert handelt, wird ganz einfach links mit 0-Bits
aufgefüllt (man kann an jede Zahl beliebig viele führende 0-en anhängen,
ohne dass sich der Zahlenwert ändert. Ob du 7, 07, 007, 0007, 00007, ...
schreibst macht keinen Unterschied in der Zahl der Schafe auf der Weide.
Es sind immer genau so viele wie du Finger an der rechten Hand und
zusätzlich noch 2 an der linken Hand hast. Ausser 007, das ist eine
Ausnahme. Der hat aber auch die Lizenz zum deleten :-)
1
00111100 00000000
2
| 00000000 01010101
3
----------------------
4
00111100 01010101
Das Ergebnis enthält also alle 1 Bits aus der ersten Zeile (die vom
leds[0] stammt) und alle 1 Bits von der zweiten Zeile (die aus den Font
Daten stammt).
Bachte: mit einer Oder-Operation kann man immer nur Bits auf 1 zwingen,
nicht auf 0. Wenn also in der ersten Zeile gestanden hätte.
1
00111100 00001111
2
| 00000000 01010101
3
----------------------
4
00111100 01011111
dann würden die 1-Bits aus der ersten Zeile genauso im Ergebnis
auftauchen. Genau deshalb, damit das unter keinen Umständen passiert,
habe ich zunächst mittels der UND-Operation
1
00111100 00001111
2
& 11111111 00000000
3
----------------------
4
00111100 00000000
diese Bits erst mal auf 0 gezwungen. Und nachdem dann hier alles
vorbereitet ist und die unteren 8 Bit wunderbar alle auf 0 sind, kann
man mittels dem Oder die 1 Bits aus den Font Daten reinzwingen. Das
wiederrum war ein 8 Bit Wert, von dem wir wissen, dass er beim Aufblasen
auf 16 Bit links nur lauter 0-er rein bekommt, so dass mir die Font
Daten wiederrum in den oberen 8 Bits nix zerstören werden.
Warum nicht einen Font bilden, der als "Abschluss" oder "Trennung"
eine "0" ergibt.
Damit kann man einen dynamischen Font bilden.
Ich erinner mich, das ich das mal aus einem RAM gemultiplext habe.
Damals gab es zwar schon Prozzessoren , ich hatte aber keine Ahnung
davon, und hab das dann in Hardware aufgebaut.
Ein "i" ist ebend nur 2 Bytes lang, die anderen Zeichen bis zu
7 Bytes lang.
Das Logo meines frueheren Arbeitgebers war 22 Bytes lang !!
(falls sich noch jemand erinnern kann, die Schrift-/Leuchtanzeige
von ehemals "Radio-Girndt" war eigentlich als User-Benutzte
"aktivanzeige" geplant.
Ich bekam damals eine Tuete mit 100 LED´s. (VQA 13)
Also auf deutsch, der letzte Schrott den es gab.
Und das bei Stueckpreisen von 2,30 Mark
Von den 100 LEDs waren evtl. 80 konkret zu gebrauchen.
Ich hab damals bestimmt ein Vierteljahr gebraucht um die
"brauchbaren" herauszusortieren".
Heutzutage kein Thema mehr.
Aber mitte der 80er war das schon ein Thema, vor allem
ein finanzielles.
Und letztendlich hab ich dann die Kunden wie Fische vor dem
Schaufenster stehen sehen, wenn sie versucht haben den Inhalt der
"Message" mitzulesen.
Gruss Asko.
Hi
Es verwundert mich etwas, das du erst einmal nicht in der Lage bist, das
Problem Laufschrift zu analysieren. Zuerst mal solltest du dir klar
werden, wieviel LED Reihen du a 8 Stück für eine Anzeige benötigst.
Versuch mal einfach nur 8 Spalten a 8 Kreise zu malen und setz mal
Punkte für deine Zeichen. Da wirst du feststellen, so schön wie eine 8x8
Matrix ist, es ist vermutlich besser, eine 6x8 Matrix zu nehmen. Mach
dir mal den Spaß, und zeichen mit Paint solch eine Matrix mit Kreisen
und bilde darin deine Zeichen ab. (siehe Anlagen)Erst einmal mit
Strichen. Anschließend füllst die Kreise und siehst dir das Bild an. Ist
die Darstellung so, das man jedes Zeichen gut erkennt? Wenn ja, kommt
nun der Punkt, wo du dir im klren werden musst, wie du einen beliebigen
Text als Laufschrift darstellen kannst. Zuerst sortierst du die Zeichen
und beginnst mit 0-9. Am besten hälst du dich an den ASCII-Code. Die
Ziffern fangen mit 48 an. So kannst du deinen text dann auswerten:
Zahlen sind zwischen von 48 bis 57, Großbuchstaben zwischen 65 und 90
und Kleinbuchstaben von 97 bis 122 angesiedelt. Die verbleibenden
Sonderzeichen sortierst du auch passend. Insgesamt ist die
Matrixvorlage bei meinem Vorschlag 468 Byte groß. So passt sie auch noch
zur Not in den EEProm. Zur Adressvergabe in BASCOM kann ich leider nicht
helfen, aber in Assembler würde ich folgende Variablen deklarieren:
Ziff_0: .Byte 10
Gr_Buch: .Byte 24
Kl_Buch: .Byte 24
Sonder: .Byte 10
Damit sind erst mal die Voraussetzungen für eine Ausgabe von Zeichen
geschaffen. Um ein fließendes Schriftbild zu bekommen, sind 2 Zeichen in
einen Puffer einzutragen. Der Multiplexer für eine 6x8 Matrix greift nun
auf die entsprechenden Spalten in diesen beiden Puffern zu. So ist eine
gleichmäßige Anzeige möglich. Und das funktioniert in wie folgt. Auch
hier wieder erst mal ein Bild vom Puffer. Da wir nur eine Matrix von 6x8
definiert haben, reicht ein Puffer von 12 Byte. Wir brauchen nun einen
Zähler für die Spalten und ein Byte mit dem Selectbit auf die aktive LED
Spalte. Das üben wir nun zuerst, bevor überhaupt an eine Laufschrift
gedacht werden kann. Im 2. Bild habe ich mal den Puffer aufgezeichnet.
Als Zeichen hab ich KI eingetragen. Nun versuch erst mal über einen
Multiplexer das K darzustellen, welches im Ausgabepuffer für die LED
steht. wenn das geht, setzt du eine 2. Zeit, die nun die Geschwindigkeit
für die Laufschrift vorgibt. Ist diese abgelaufen, kopierst du den
Inhalt vom 2. Puffer um eine Stelle weiter, d,h.
Byte 1 -> Byte 0
Byte 2 -> Byte 1
Byte 3 -> Byte 2
Byte 4 -> Byte 3
Byte 5 -> Byte 4
Byte 6 -> Byte 5
Byte 7 -> Byte 6
Byte 8 -> Byte 7
Byte 9 -> Byte 8
Byte 10 -> Byte 9
Byte 11 -> Byte 10
Das sollte geschehen, wenn dein Multiplexer den letzten Schritt beendet
hat und bevor der erste Schritt beginnt. Hast du die 6 Zeichen weiter
geschoben, kopierst du das nächste Zeichen (6 Byte) in den nicht
sichtbaren Puffer. Dazu nimmst du den Code, wertest den Bereich aus,
subtrahierst den Ascii-Startwert und addierst zur Speicherstelle den
Restwert. Also, die 0 hat den ASCII-Code 48. Das ist auch der
Ziffernbereich. Ist dein ASCII-COde zwischen 48 und 57 dann ziehst du 48
ab. Übrig bleibt die entsprechende Zahl. Diese multiplizerst du nun mit
6, das ist die Anzahl der Reihen der Matrix und du erhälst die dann die
Basisadresse 6 Reihen der ASCII Ziffer. Mit einer Schleife kopierst du
nun die aufeinander folgenden Bytes in den unsichtbaren Puffer. Ist es
ein Großbuchstabe ist entsprechend der Bereich für die Basisadresse der
Großbuchstaben zugrundezulegen.
Und wenn du deine Matrix ausbauen willst..... nun, dann vergrößere
enfach den sichtbaren Bereich. natürlich muss auch die Schieberoutine
des Multiplexers angepasst werden, aber... hier bekommst du ein anderes
Problem. Dein Multiplexer wird es dann vermutlich nicht schaffen, ohne
flackern die LED-Spalten anzuzeigen. Das liegt daran, das du eine LED
Spalte für ca. 2ms anzeigst und dann für (x-1) * 2ms abschaltest. X
steht hier für die Anzahl der LED-Spaltten. Auch das bekommt man in den
Griff, indem die LED-Reihen gemultiplext werden. Aber darüber darfst du
selbst nachdenken.
PS: Natürlich kannst du die leere Spalte auch so eintragen und die
Matrix mit nur 5 Byte aufbauen. Sie sollte aber im Puffer sein und immer
mitgeschoben werden.
Also laufen tut die Laufschrift nun.
Jetzt wollte ich das Problem mit der Speicherbelegung durch das Font im
RAM angehen und eine Art "Looktable" in den Flash ablegen.
Dazu habe ich mir den Artikel im Tutorial angeschaut und bin auf die
__flash Variante nach PROGMEM gestoßen.
In der while(1) arbeitet der Controller dann die for Schleife ab, in der
auch auf das Arrays font zugegriffen wird.
1
//Schleife zum Kopieren der einzelnen Elemente des Fonts in das Array 8 Bit
2
for(intj=0;j<8;j++)
3
{
4
leds[j]=(leds[j]&0xFF00)|font[ascii_help][j];
5
}
Ich bekomme nun für den Aufruf des Arrays font folgenden Error.
Multiple markers at this line
- Symbol 'font' could not be
resolved
- Line breakpoint: main.c [line:
214]
Liegt mein Array font im Flash oder ist die Deklaration schon falsch, da
ich hier schon einen Syntax Error erhalte.
Soweit ich das in Eclipse sehe, sollte ich den Avr-gcc verwenden. Und
der Terminalauswurf sagt Version 4.9.1. Das sollte für __flash doch
ausreichen?
Erics-MBP:~ #######$ avr-gcc -v
Es werden eingebaute Spezifikationen verwendet.
COLLECT_GCC=avr-gcc
COLLECT_LTO_WRAPPER=/opt/local/libexec/gcc/avr/4.9.1/lto-wrapper
Ziel: avr
Konfiguriert mit:
/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macp
orts.org_release_tarballs_ports_cross_avr-gcc/avr-gcc/work/gcc-4.9.1/con
figure --prefix=/opt/local --target=avr --infodir=/opt/local/share/info
--mandir=/opt/local/share/man --datarootdir=/opt/local/share/avr-gcc
--with-system-zlib --with-gmp=/opt/local --with-mpfr=/opt/local
--with-mpc=/opt/local --enable-stage1-checking --enable-multilib
--enable-lto --enable-languages=c,c++
Thread-Modell: single
gcc-Version 4.9.1 (GCC)
Ok habe Eclipse einfach mal geschlossen und neu gestartet. Der Error ist
weg, aber der Syntaxerror bei der Deklaration von font bleibt.
Korrigiere: Nach mehrmaligen Build tritt der Fehler wieder auf.
Wäre es nicht deutlich einfacher, die Byte vertikal auszurichten? Also
jedes Byte steuert eine vertikale Reihe von LED's. Dann braucht man
nämlich überhaupt keine Bit-Schubserei mehr.
Hi
Stefan Us schrieb:> Wäre es nicht deutlich einfacher, die Byte vertikal auszurichten? Also> jedes Byte steuert eine vertikale Reihe von LED's. Dann braucht man> nämlich überhaupt keine Bit-Schubserei mehr.
Dann schau dir mal meine Skizzen an...
Gruß oldmax
Stefan Us schrieb:> Benutze diese Library:>> http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html> #include <avr/pgmspace.h>>> const uint8_t font[91][8] PROGMEM = ...>> Zum lesen benutzt du die Funktionen aus der Library.
Hallo Stefan,
ich hab es dann auch mit PROGMEM gelöst. Anscheinend ist der Compiler
wirklich zu alt?!
oldmax schrieb:> Dann schau dir mal meine Skizzen an...> Gruß oldmax
Danke Oldmax. Ich bin froh das es jetzt erstmal läuft. Wahrscheinlich
ist das wirklich sinnvoller. Bei Gelegenheit schau ich mir demnächst
deine Variante an und versuche diese noch einmal umzusetzen.