Hallo, liebe Gemeinde,
da ich zu meinem Grafik-Display noch keinerlei Libraries für
Schriftarten gefunden habe (falls es so etwas überhaupt schon gibt), hab
ich mir mal eine kleine Routine für eigens angelegte Fonts geschrieben.
Das Problem ist nur, dass ich mit einer verschachtelten Schleife etwas
Probleme habe:
Ich bekomme damit ausschießlich den ersten Buchstaben (arrLcdString[0])
ausgegeben, der Rest bleibt mir irgendwo verborgen...
Hat da draußen vielleicht jemand einen Rat?
LG, Marcel
Kauf dir ein C-Buch
In deinem Code gibt es so viele Problemstellen, dass man gar nicht weiß
wo man anfangen soll.
PS: Der ganze Ansatz, wie du das mit den Fonts machen willst, ist
verkorkst.
Mach dir eine Funktion, die 1 zeichen ausgeben kann (also alle Spalten).
Und die rufst du dann für jedes Zeichen deines Strings einzeln mit dem
jeweiligen Buchstaben auf.
Aber vorher nachlesen, wie das mit den Strings wirklich funktioniert.
Die Idee mit dem _xEnd ist keine gute Idee. Damit schränkst du dich in
den Möglichkeiten ein, was du mit deinen Fonts alles anzeigen kannst.
Beschränke dich erst mal auf Fonts, bei denen für jedes Zeichen gleich
viele Bytes auszugeben sind. Und wenn du die im Griff hast, dann lass
jede Buchstabenbeschreibung mit der Anzahl der zu diesem Buchstaben
gehörenden Bytes beginnen.
Hallo Karl-Heinz,
... sag mal... schreibt ihr jetzt unter JEDE Antwort, dass man sich ein
C-Buch kaufen soll?;-)))
Ich habe ganze FÜNF C/C++Bücher, etliche eBooks UND Galileo-Press-Werke.
Dennoch bin ich aber in C ein Anfänger!;-)))
Ich wollte es anfangs ganz schlicht über eine switch-Anweisung machen
(übersichtlicher geht´s eigentlich gar ned), ich fände es aber sehr viel
eleganter, wenn ich es über eine Schleife und ein einziges Array
erreichen könnte. Zumal dieses Array (wie man oben sieht) auch sehr gut
zu managen wäre.
LG, Marcel
Marci schrieb:> Hallo Karl-Heinz,>> ... sag mal... schreibt ihr jetzt unter JEDE Antwort, dass man sich ein> C-Buch kaufen soll?;-)))
Wenn es notwendig ist: Ja
> Ich habe ganze FÜNF C/C++Bücher, etliche eBooks UND Galileo-Press-Werke.> Dennoch bin ich aber in C ein Anfänger!;-)))
Dann LIES sie! Udn mach die Übungen (auf einem PC)
Insbesondere die Kapitel über Arrays und Strings und Funktionen!
Wenn dein Code so anfängt
1
voidlcdString(charstrLcdString)
dann hast du Strings bzw. Arrayverarbeitung und wie das bei
Funktionsaufrufen funktioniert, nicht kapiert!
Deine Funktion bekommt so nur ein einzelnes Zeichen und keinen String.
Und das wird auch nicht besser, wenn du dich hier
char arrLcdString[] = {strLcdString};
ins eigene Bein schiesst.
Hallo,
1.
void lcdString(char strLcdString)
Deine Funktion erwartet einen character, sprich ein Zeichen.
void lcdString(char *strLcdString)
So erwartet die Funktion einen String, wie du ihn übergibst.
2.
(sizeof(arrLcdString)/sizeof(uint8_t))
Das ergibt bei einer 8 Bit Maschine immer 1, egal wie lang der String
ist, da du hier ein sizeof auf den Pointer machst.
Die Länge von einem String bekommst du mit strlen(arrLcdString) aus
string.h.
Das warn mal die Sachen die mir schnell aufgefallen sind.
lg Heinz
Zum Rest, wie du das ganze angehen kannst, hab ich mich hier
Beitrag "Re: Schleifenproblem"
ja schon geäussert.
Alles beginnt mit einer Funktion, die 1 Zeichen (nicht String) ausgeben
kann. Darauf aufbauend ist dann eine Stringfunktion ein Kinderspiel.
Hm...... ich hab jetzt den String mal in Hochkommata gesetzt. Das Wort
wird zwar in die Funktion geladen, aber nur zwei Buchstaben werden
angezeigt. Der letzte zuerst, dann folgt der Erste. Macht das einen
Sinn?
Ps.: Und ja, es kann gut sein, dass ich noch fehlendes Wissen dazu habe.
Allein schon der Gedanke an die fast 1000 Seiten eines jeden C-Buches in
meinem Schrank, machen mir große Sorgen...)§/&!"&§&(§/!46!734 ;-)))))
LG, Marcel
> Alles beginnt mit einer Funktion, die 1 Zeichen (nicht String) ausgeben> kann. Darauf aufbauend ist dann eine Stringfunktion ein Kinderspiel.
Und wenn du (Marci) diese Funktion schreibst, dann verabschiede dich
bitte ganz schnell davon, den Zeichensatz in einer nicht statischen
lokalen Variable zu speichern. Das ist HORREND ineffektiv.
Marci schrieb:> Ps.: Ich wollte halt gern eine Funktion, die man einfach bedienen kann> (xxx("...")).
Kriegst du auch!
Aber eines nach dem anderen. Zuerst die 'einfachere' Funktion und dann
darauf aufbauend die Funktion, die mit komplizierteren Daten umgehen
kann.
Hier ist sie
1
voidlcd_string(constchar*string)
2
{
3
charc;
4
5
c=*string;
6
while(c!='\0'){
7
lcd_char(c);
8
c=*string;
9
string++;
10
}
11
}
(So gesehen ist die "kompliziertere" Funktion die C-technisch
einfachere. Aber du brauchst eine Funktion lcd_char als Grundlage, damit
du darauf aufbauend die Funktion für Strings schreiben kannst. Daher
fängt man zuerst mit der Funktion lcd_char an)
Stefan Ernst schrieb:> Karl Heinz Buchegger schrieb:>> Hier ist sie>> Bitte die letzten beiden Zeilen der while-Schleife tauschen. ;-)
Oops. Hast recht.
Das hat man davon, wenn man nicht in der C-üblichen dichten Form
schreiben will :-)
Hui... ihr seid´s ja schnell! Supi!;-)
Jepp, mach ich.
Hmmmm... kann ich das nicht irgendwie ohne Zeiger machen - ich glaub,
des is noch zu hoch für mich.;-)))
LG
@ Karl Heinz
wird wohl nicht compilierbar sein.
const char* string -> string++;
const bedeutet konstant, daher kann string nicht verändert werden.
void lcd_string( const char* string )
{
char *c;
c = string;
while( c != '\0' ) {
lcd_char( *c );
c++;
}
}
lg heinz
Marci schrieb:> Hui... ihr seid´s ja schnell! Supi!;-)>> Jepp, mach ich.>> Hmmmm... kann ich das nicht irgendwie ohne Zeiger machen - ich glaub,> des is noch zu hoch für mich.;-)))
kann man.
Aber
es ist für den µC mehr Aufwand
man muss einen Datentyp für einen Index einführen, was man nur
ungern tut. Denn: wie gross macht man ihn denn?
die meisten String-Operationen gewinnen durch Zeiger. Also kein
Grund Zeiger links liegen zu lassen.
Irgendwann musst du sowieso an Zeiger rann. Arrays und Strings ohne
Zeiger ist wie ein Fisch ohne Wasser.
1
voidlcd_string(constchar*string)
2
{
3
size_ti=0;
4
while(string[i]!='\0')
5
lcd_char(string[i]);
6
i++;
7
}
8
}
Daher auch die Sache weiter oben mit dem Buch. Denn in JEDEM Buch werden
solche Dinge im Kapitel über Strings bis zur Vergasung geübt! Eben WEIL
es wichtige Grundlagen sind.
Ineffizient ist es deswegen, da dieses Array bei jedem Aufruf der
Funktion im RAM angelegt wird und dann mit den Werten aus dem Flash
befüllt wird.
Wenn es global und const ist, liegt es im Flash und nur dort.
lg Heinz
Heinz schrieb:> @ Karl Heinz> wird wohl nicht compilierbar sein.> const char* string -> string++;>> const bedeutet konstant, daher kann string nicht verändert werden.
Unsinn. Nicht string ist konstant, sondern das, worauf string zeigt.
Heinz schrieb:> @ Karl Heinz> wird wohl nicht compilierbar sein.> const char* string -> string++;>> const bedeutet konstant, daher kann string nicht verändert werden.
Nö
Die Zeichen sind konstant, aber nciht der Zeiger.
Ein const char* ist etwas anderes als ein char * const
Heinz schrieb:> Tschuldigung, meinte char const *string> Mein Fehler
Dumm nur, dass dafür das gleiche gilt. Auch hier ist der Pointer nicht
konstant. ;-)
Hab ich des jetzt richtig verstanden? Mein Font-Array soll erhalten
bleiben??????
Aber dann geht ja dein \0\-Vergleich GAR NED!? Dies bedeuted ja ein
0-Byte... es gibt ja aber auch z.B. das Zeichen ", und dann habe ich
mittendrin ein 0-Byte, worauf die Schleife vorzeitig verlassen würde?!
Richtig???
LG
Heinz schrieb:> Tschuldigung, meinte char const *string> Mein Fehler
:-)
Ein "char const *" ist dasselbe wie ein "const char *"
const wirkt immer auf den Teil links von ihm. Es sei denn es steht schon
ganz links, dann wirkt es auf den Teil rechts von ihm
char * const
links vom const steht der *. Also ist der Pointer const
char const *
links vom const steht das char. Also sind die char const
const char *
links vom const steht .... nichts mehr. Also wirkst das const
auf das rechts von ihm stehende char. Die Zeichen sind const
char const * const
Sowohl der Zeiger, als auch die Character sind const
Marci schrieb:> Hab ich des jetzt richtig verstanden? Mein Font-Array soll erhalten> bleiben??????
Natürlich. Irgendwo müssen ja die Pixel für ein Zeichen des Fonts
abgespeichert sein. Aber was interessiert das die String-Ausgabe wie
genau die Einzelzeichenausgabe zu ihren Ergüssen kommt? Genau. Gar
nicht.
> Aber dann geht ja dein \0\-Vergleich GAR NED!?
Warum nicht?
AUf dieser Ebene innerhalb der lcd_string sind wir doch noch gar nicht
bei den Pixel. Da ist noch immer von einzelnen Zeichen die Rede. Und da
in C jeder String ausnahmslos immer mit einem '\0' Zeichen aufhört, kann
man das natürlich benutzen, wenn man in einem String ein Zeichen nach
dem anderen zur Verarbeitung herausholen will.
Ob ich dann dieses eine Zeichen per UART verschicke oder auf ein
Text-LCD ausgebe oder wie in deinem Fall einer Funktion übergebe, die
für das Zeichen entsprechende Pixel auf ein Grafik-LCD hinmalt, ändert
ja nichts daran, wie ich in einem String an ein Zeichen nach dem anderen
komme.
> es gibt ja aber auch z.B. das Zeichen ", und dann habe ich> mittendrin ein 0-Byte, worauf die Schleife vorzeitig verlassen> würde?!> Richtig???
Falsch.
Auch wenn es dir nicht gefällt. Das steht alles in deinen Büchern.
Tee ist gekocht!;-)))))))
Ok. Ich glaub, ich setz mich jetzt erstmal zur Bearbeitung hin. Danke
Jungs!;-)
LG, Marcel
Ps.: Wenn ich mich ned mehr melden sollte, hat mich die Funktion dann
wahrscheinlich innerlich zerlegt.;-)))))
Karl Heinz Buchegger schrieb:> const wirkt immer auf den Teil links von ihm. Es sei denn es steht schon> ganz links, dann wirkt es auf den Teil rechts von ihm
Für diesen Krempel sollte man K&R mal leicht verhauen...
> char const * const> Sowohl der Zeiger, als auch die Character sind const
Wäre const char const * auch richtig?
Marci schrieb:> Ps.: JAAAAAAAAaaaaaaaaaa. ICH werde LESEN!!! Versprochen!!!!!!!!;-))
Am besten wäre:
Die Übungen im Buch nach jedem Kapitel auf einem PC durchmachen.
Anfänger schrieb:> Karl Heinz Buchegger schrieb:>> const wirkt immer auf den Teil links von ihm. Es sei denn es steht schon>> ganz links, dann wirkt es auf den Teil rechts von ihm> Für diesen Krempel sollte man K&R mal leicht verhauen...
Da können K&R nichts dafür. Zu ihrer Zeit gab es noch kein const.
>> char const * const>> Sowohl der Zeiger, als auch die Character sind const> Wäre const char const * auch richtig?
Das wäre doppelt gemoppelt. Beide const beziehen sich auf dasselbe: auf
die char
Karl Heinz Buchegger schrieb:> Da können K&R nichts dafür. Zu ihrer Zeit gab es noch kein const.
Achso? Auch gut.
> Das wäre doppelt gemoppelt. Beide const beziehen sich auf dasselbe: auf> die char
Argh, ich muss mir wohl die Bibel (steht K&R drauf) nochmal zu Gemüte
führen. :-(
Man könnte natürlich das const auch einfach ganz weglassen... duckundweg
Marci schrieb:> Hab ich des jetzt richtig verstanden? Mein Font-Array soll erhalten> bleiben??????
nicht so, wie es da steht.
Global:
char myFont[][] = {
{ ..... },..
};
Fang z.B. mit 'A' an und subtrahiere in
lcd_char( char c )
'A' von c für den Indexzugriff auf Dein Font,
und achte auf die Indexgrenzen
> Aber dann geht ja dein \0\-Vergleich GAR NED!?
Der Dein Vergleich funktionierte vorher auch nur per Zufall, weil Du die
\0 nicht _xEnd nicht initialisiert hast.
Sicher funktioniert aber Karl Heinz Vergleich.
Übrigens sollte man Unterstriche am Bezeichneranfang lieber lassen.
(Findest Du auch in Deinen C/C++-Büchern warum)
> Hmmmm... kann ich das nicht irgendwie ohne Zeiger machen - ich glaub,> des is noch zu hoch für mich.;-)))
Basic?
Michael Schikora schrieb:> Der Dein Vergleich funktionierte vorher auch nur per Zufall, weil Du die> \0 nicht _xEnd nicht initialisiert hast.
Ach, das hab ich ja noch gar nicht gesehen.
Wie gesagt: In der ersten Version würde ich mal einen Fixed Font machen.
Alle Zeichen gleich viele Bytes.
Und bei variablen Fonst dann kein Ende Zeichen, sondern als erstes Byte
die Anzahl der Codebytes für dieses Zeichen.
Und der Buchstabe .... der sollte dort sowieso nicht im Array sein. Die
Reihenfolge der Buchstaben ist ja durch den ASCII Code sowieso
festgelegt.
Karl Heinz Buchegger schrieb:> Ach, das hab ich ja noch gar nicht gesehen.
Für mich war es neu, dass in der Initialisierung für eine nicht
statische lokale Variable andere Variablen stehen können. Wenn ich die
Tage mal etwas Langeweile habe, werde ich mal checken, ob das so im
Standard steht, oder ob das eine C-Extension vom GCC ist.
Oder weißt du das zufällig so aus dem Stegreif?
Stefan Ernst schrieb:> Karl Heinz Buchegger schrieb:>> Ach, das hab ich ja noch gar nicht gesehen.>> Für mich war es neu, dass in der Initialisierung für eine nicht> statische lokale Variable andere Variablen stehen können. Wenn ich die> Tage mal etwas Langeweile habe, werde ich mal checken, ob das so im> Standard steht, oder ob das eine C-Extension vom GCC ist.> Oder weißt du das zufällig so aus dem Stegreif?
nicht 100% sicher
In C dürfte das nicht erlaubt sein.
In C++ schon.
In C müssen Initialiser Compiler-Time Konstanten sein, während in C++
eine Expression (also auch ein Funktionsaufruf) erlaubt ist.
Aber wie gesagt: 100% sicher bin ich mir auch nicht.
Karl Heinz Buchegger schrieb:> In C müssen Initialiser Compiler-Time Konstanten sein, während in C++> eine Expression (also auch ein Funktionsaufruf) erlaubt ist.
Eben, das war auch mein Kenntnisstand.
Aber ich habe doch gleich mal nachgeschaut, und seit C99 ist das vom
Standard abgedeckt. Und wenn ich etwas darüber nachdenke, dann habe ich
das auch schon öfter benutzt, ohne es zu merken:
(du wahrscheinlich auch ;-)
Es funktioniert zwar reibungslos, ich bekomme aber ganze 3
Warnmeldungen:
1. array subscript has type 'char';
Zeile: lcdSendData(myFont[c][nColumn]);
2. array subscript has type 'char';
Zeile: if(nColumn == myFont[c][0])
3. assignment discards qualifiers from pointer target type;
Zeile: c = string;
Hallöchen, ich bin´s nochmal,^^
... es geht doch noch ned!:(
Es lässt sich nur eine Zeile ausgeben. Dann streikt das Programm völlig
und zeigt nix mehr an.
Scheinbar liegt der Fehler in lcdString8() und event. auch an falschen
Typendeklarationen.
Jemand einen Rat???????
LG, Marcel
Hallo Bernd,
... am RAM kann´s ned liegen. Der ist nur mit 0,8% belegt. (ATmega2560)
Ich hab die Funktion jetzt ein wenig umgebaut, und,... vóila... OHNE
eine einzige Fehler- oder Warnmeldung.
1
voidlcdChar8(intcInt)// c ist hier zugleich der jeweilige ASCII-Wert (z.B.: "A">65) des gesendeten Charakters