Hoi, ich habe mit eine Punktmatrix gebastelt (angesteuert von 4 max2719) Controller ist ein ATmega8. Aber zurück zu meiner Frage/mein Problem... Bisher habe ich sowas hier getippt... bin noch neueinsteiger also sorry für das chaos ^^ char H[]={0b01111110,0b00010000,0b00010000,0b01111110,0b00000000}; char a[]={0b00011110,0b00010010,0b00011110,0b00000010,0b00000000}; char l[]={0b01111110,0b00000000}; char o[]={0b00011110,0b00010010,0b00011110,0b00000000}; char clr[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00}; char j=0; while(1) { for (j=0;j<5;j++) //H Ausgeben { Ausgabe(cursor,H[j]); weiter(); } for (j=0;j<5;j++) //a Ausgeben { Ausgabe(cursor,a[j]); weiter(); } for (j=0;j<2;j++) //l Ausgeben { Ausgabe(cursor,l[j]); weiter(); } for (j=0;j<2;j++) //l Ausgeben { Ausgabe(cursor,l[j]); weiter(); } for (j=0;j<4;j++) //o Ausgeben { Ausgabe(cursor,o[j]); weiter(); } cursor=1; for (j=0;j<20;j++) //löschen { Ausgabe(cursor,clr[j]); weiter(); } cursor=1; } } void weiter(void) { cursor++; _delay_ms(100); } void Ausgabe(char Zeile,char MaxData) { char I=0; char Tmp=0; char Shift=0; char MaxAdress=0; if (Zeile>20) //maximale Spalten return; while (Zeile>5) //Wenn in Zeile 6-10,11-15,16-20 müssen die Daten in den nächsten MAX geschoben werden { Zeile-=5; Shift+=16; } if (Zeile==5) //Kleiner Entflechtungsfehler ^^ MaxAdress=0x01; //Sollte normalerweise so aussehen //12345 12345 12345... if (Zeile==4) //Sieht aber von den zeilen so aus: MaxAdress=0x02; //54321 54321 54321 if (Zeile==3) MaxAdress=0x03; if (Zeile==2) MaxAdress=0x04; if (Zeile==1) MaxAdress=0x05; for(I=0;I<8;I++) //Übtragung seriell an MAX { Tmp=MaxAdress; MaxAdress&=0x80; MaxAdress>>=7; PORTD=MaxAdress; //DIN PORTD|=0x02; //CLK PORTD=0x00; MaxAdress=Tmp; MaxAdress<<=1; } for(I=0;I<8;I++) { Tmp=MaxData; MaxData&=0x80; MaxData>>=7; PORTD=MaxData; //DIN PORTD|=0x02; //CLK PORTD=0x00; MaxData=Tmp; MaxData<<=1; } for(I=0;I<Shift;I++) //daten in hinteren MAX weiterschieben { PORTD|=0x02; //CLK PORTD=0x00; } PORTD=0x04; PORTD=0x00; for(I=0;I<64;I++) //Schieberegister im MAX leeren { PORTD=0x02; PORTD=0x00; } } ich habe um mein "Hallo" auszugeben muss ich also punktmatrixmäßig meine daten in die MAX-Bausteine schreiben. Wie ihr seht habe ich in meiner while-schleife jeden einzelnen buchstaben aufgerufen und ausgegeben... ich bin auf der suche nach einer vereinfachung durch einen String mit inhalt "Hallo". ich weiß aber nicht wie ich eine verbindung meiner binären inhalte zu den buchstaben schaffe. habe mir mal das programm des elektor-kreisels (falls bekannt) reingezogen und gesehen, dass es derartige möglichkeiten gibt =) dort habe ich EIN array gefunden, worin alle buchstaben hintereinander hinterlegt waren und #define string_1 "Text". Woher weiß mein String , dass er erst an der bestimmten stelle für den buchstaben aus dem array auslesen soll ? wenn im array[]={0x00,0x00,0x00,0x00 //Space ,0x12,012 //A, ... usw} steht ? ich hab erst gestern von stück-für-stück-programmierung zum array gefunden. aus meinem lehrbuch "c für dummies" hab ich eine schöne erklärung für die funktionsweise von arrays gefunden. bin bei strings aber völlig ratlos. wenn mir da vielleich jemand auch ein bisschen was erklären könnte wär es ganz nett =) mein ziel ist es später einen beliebigen text auszugeben (später dann in laufschrift) ich hoffe ihr könnt mir helfen mfg hendrik
Die Lösung deines Problems heisst Sprungtabelle. Jedes Zeichen ist eigentlich eine 8 Bit Zahl. Stichwort ASCII Code. die '0' z.B. ist 30h (=48 dezimal) das große 'A' ist 41h. Du legst die Codierung der Zeichen in einem großen Array ab. In einem weiteren Array von Shorts (Der Sprungtabelle) legst Du jetzt die Anfangsadresse der Codierung des entsprechenden Zeichens an genau der Stelle im Array ab, das dem ASCII Code des Zeichens entspricht. In Deinem Codierungsarray musst Du jetzt noch eine Möglichkeit vorsehen zu erkennen wann die Codierung des Zeichens fertig ist. Das kannst Du entweder so machen, daß das erste Byte der Anzahl der folgenden Bytes entspricht, oder Du weisst daß das letzte Codierungsbyte null ist (der Abstand zum nächsten Zeichen). Jetzt brauchst Du nur eine Funktion schreiben, die einen String oder ein Einzelzeichen nimmt und entsprechend die Codierung herausfindet. Beispiel: Du willst ein 'c' ausgeben: Deine Funktion macht jetzt folgendes: Ein 'c' hat den Code 63h. Du holst die 16Bit Wert (unsigned short) an der Stelle 63 deiner Sprungtabelle. Dieser Wert ist der Offset in deinem (großen) Array mit den Codierbytes. Ab dieser Stelle liest Du jetzt solange die aufeinanderfolgenden Bytes und gibst sie aus, bis ein Byte mit dem Wert 0 kommt. Versuch das zu verstehen und probiere es erst mal nur mit ein paar Buchstaben. Das Ganze kann man natürlich noch optimieren, wenn man nur einen Teil der Zeichen (nur Buchstaben und Zifferen) oder nur großbuchstaben benutzen will. Dann implementiert man nur den Teil der Sprungtabelle den man braucht und zieht entsprechend einen Offset von dem Buchstaben ab.
Hendrik S. schrieb: > inhalt "Hallo". ich weiß aber nicht wie ich eine verbindung meiner > binären inhalte zu den buchstaben schaffe. Jeder 'Buchstabe' ist gleichzeitig auch eine Zahl. Siehe ASCII Code. > dort habe ich EIN array gefunden, worin alle buchstaben hintereinander > hinterlegt waren und #define string_1 "Text". Woher weiß mein String , > dass er erst an der bestimmten stelle für den buchstaben aus dem array > auslesen soll ? wenn im array[]={0x00,0x00,0x00,0x00 //Space ,0x12,012 > //A, ... usw} steht ? Wenn im Text der Buchstabe 'A' vorkommt, so steht im Speicher da in Wirklichkeit eine Zahl. Nämlich die Zahl die im ASCII Code für 'A' steht. In einem Computer gibt es keine Buchstaben, nur Zahlen. Erst dein Ausgabegerät weiß, dass wenn es die Zahl 0x41 erhält, dass es dafür ein bestimmtes Bitmuster auf den Schirm pinseln muss, bei dem genau die Pixel dunkel gesetzt sind, so dass dein Gehirn daraus ein 'A' macht. -> Man kann auch mit 'Buchstaben' in ein Array indizieren, da ja ein Buchstabe im Computer nichts anderes als eine Zahl ist 0x41, 65, 'A' sind nur verschiedene Schreibweisen für immer dasselbe. Nämlich das Bitmuster 01000001. So liegt es im Speicher. Alles andere ist eine Interpretationsfrage und wird entschieden wenn es gilt dieses Bitmuster auf ein Ausgabegerät auszugeben. Erst dann erhebt sich die Frage: Welches ist die angemessene Anzeigeform dafür, was interessiert mich? Will ich das als Zahlenwert sehen? Hex oder Dezimal? Oder will ich dieses Bitmuster überhaupt nicht umgeformt sehen und das AUsgabegerät soll den zu diesem Bitmuster gehörenden 'Buchstaben' aus dem ASCII Code anzeigen.
Udo R. S. schrieb:
> Die Lösung deines Problems heisst Sprungtabelle.
Ich denke für einen Einsteiger, der mit Arrays noch auf Kriegsfuss
steht, ist es zunächst wesentlich einfacher sich zunächst an einem
nicht-proportionalen Font zu versuchen.
In diesem Sinne hat man dann einfach nur ein 2D-Array
1 | unsigned char BitCodes[255][5] = { |
2 | { ..... } // Die 5 Codes für das Zeichen mit dem ASCII Code 0 |
3 | ...
|
4 | |
5 | { 0b01111110,0b00010000,0b00010000,0b01111110,0b00000000 }, // Die 5 Codes für das Zeichen mit dem ASCII Code 72, 'H' |
6 | ...
|
zu haben und mit dem Character zu indizieren.
1 | void putc( unsigned char c ) |
2 | {
|
3 | for( unsigned char i = 0; i < 5; ++i ) |
4 | {
|
5 | // ausgabe von BitCodes[c][i]
|
6 | }
|
7 | }
|
8 | |
9 | void puts( const char* s ) |
10 | {
|
11 | while( *s ) |
12 | putc( *s++ ); |
13 | }
|
14 | |
15 | |
16 | int main() |
17 | {
|
18 | ...
|
19 | puts( "Hallo world" ); |
20 | }
|
Und jetzt ran an die Bulletten und die Codetabelle für die noch fehlenden Zeichen ergänzt. Wenn du das hast und begriffen hast, wie das mit den Arrays funktioniert, kannst du dich an Optimierungen versuchen (zb weil die ersten 32 Zeichen im ASCII Code keine sichtbare Darstellung haben und damit auch nicht in der Tabelle sein müssen), bzw. an einem proportionalen Font.
>Ich denke für einen Einsteiger, der mit Arrays noch auf Kriegsfuss >steht, ist es zunächst wesentlich einfacher sich zunächst an einem >nicht-proportionalen Font zu versuchen. hast Du wahrscheinlich recht :-) Wobei ein 2-dimensionales Array auch nicht gerade trivial ist. > void putc( unsigned char c ) gibts da nicht Probleme, das ist eine Standardfunktion, besser für die Funktion einen eigenen Namen nehmen z.B. "myputc".
Udo R. S. schrieb: >> void putc( unsigned char c ) > > gibts da nicht Probleme, das ist eine Standardfunktion, besser für die > Funktion einen eigenen Namen nehmen z.B. "myputc". Ooops. Hast recht. Da hab ich geschlafen. puts() dasselbe.
hallo, hat soweit alles funktioniert ABER mein problem ist momentan, dass ich meine Zeichenanzahl zählen lassen will und in der Zeile: >#define text "-Das ist eine Laufschrift von Hendrik Schulz-" ...... >void zaehl_zeichen(char* k) >{ > if(merker==0) > { > while( *k ) > { > *k++; //<---------------------- > Zeichenanzahl++; > } > time-=Zeichenanzahl; > Zeichenanzahl*=6; > if (time<=0) > time=1; > merker=1; > } >} ..... >zaehl_zeichen(text); die warning vom compiler "../Dotmatrix.c:84: warning: value computed is not used" kommt ?! denke ich falsch ?? es geht bis zu einer zeichenanzahl von 45 in meinem string, dann kommt irgendetwas durcheinander und meine ausgabe fängt von vorne an (so als wär eine variable überfüllt) habe auch mal das komplette programm angehängt. wie mach ich überhaupt so ein weis hinterlegtes kommentar wie Karl heinz Buchegger? ^^ danke für antworten =)
>es geht bis zu einer zeichenanzahl von 45 in meinem string,...
ich hatte in meinem 2D array eine zeile zu viel oben in der eckigen
klammer angegeben... jetzt ist meine maximale länge um ca 10 zeichen
gestiegen
kann es sein, dass das "char * k" überläuft, da char ja nur bis +127
geht ??
Hendrik S. schrieb: >>es geht bis zu einer zeichenanzahl von 45 in meinem string,... > > ich hatte in meinem 2D array eine zeile zu viel oben in der eckigen > klammer angegeben... jetzt ist meine maximale länge um ca 10 zeichen > gestiegen > > kann es sein, dass das "char * k" überläuft, da char ja nur bis +127 > geht ?? Du solltest dir Konventionen für Variablennamen aneigenen. 1) einbuchstabige Variablennamen sind generell nicht so der Bringer 2) einbuchstabige Variablennamen werden normalerweise benutzt um Variablen mit lokalem kleinem Scope anzuzeigen. Also Funktions- lokale Variablen. Diese Variablen erfüllen aber nur Hilfsaufgaben. Wichtige Variablen darf man man schon mehr als nur ein Zeichen im Namen spendieren 3) die Variablennamen i, j, k, l, m, n sind praktisch ausschliesslich für Zählvariablen reserviert. So wie in for( i = 0; i < 27; ++i ) i ist also ein Zähler. Bei dir ist k kein Zähler. k ist ein Pointer auf den Anfang des Strings, den die Funktion übergeben bekommt. Dieser Pointer hätte sich einen besseren Namen als k verdient k++ stellt den Pointer um ein Zeichen weiter Das * vor einem Pointer bedeutet den Pointer zu dereferenzieren. *k++ hat also die Bedeutung: hole das Zeichen, auf das k zeigt und anschliessend stelle k um 1 Zeichen weiter. Gut. Aber was machst du mit dem Zeichen, das hier geholt wird? Die Antwort: Nichts! Daher sagt dir der Compiler: Hey, du willst von mir, das ich da Zeichen hole aber du tust nichts damit. Also wozu dann überhaupt das Zeichen holen? Wenn du die Länge eines Strings wissen willst, warum benutzt du dann nicht die Funktion strlen()? Genau dafür ist die da!
> Wenn du die Länge eines Strings wissen willst, warum benutzt du dann > nicht die Funktion strlen()? Genau dafür ist die da! kannst du mit bitte ein beispiel für die funktion geben ? ^^ in meinem falle dann ein zeichenanzahl=strlen(text); ?! ich dachte mit, dass ich einmal durch den string muss also jede stelle einmal ansehen und meine zeichenanzahl so oft inkrementieren.. ^^
Hendrik S. schrieb: > kannst du mit bitte ein beispiel für die funktion geben ? ^^ > in meinem falle dann ein zeichenanzahl=strlen(text); ?! :D ok nicht dumm rumfragen sondern einfach ausprobieren und geht ^^ zwar mit den warnings: ../Dotmatrix.c:121: warning: implicit declaration of function 'strlen' ../Dotmatrix.c:121: warning: incompatible implicit declaration of built-in function 'strlen' bleibt jedoch mein fehler mit der zeichenbegrenzung meines strings... also zur funktionserklärung habe ich eine art maske (meine anzeige ist 7x20) konstruiert. der gesamte text wird also ausgegeben , fängt halt an der letzten stelle an, wird nach links durchgeschoben (auch weiter aus der anzeige, das jedoch einfach nicht angezeigt wird) und der rest (zeile>20) wird ebenfalls nicht angezeit. ^^ also wenn meine zeichenanzahl <= zeile 0 dann soll es erneut beginnen. warum also tut mein grogramm das schon mitten im text (abhängig von der anzahl an eingetippten buchstaben) ?? irgendetwas muss da doch "überlaufen" =( das programm ist mittlerweile 5,604 kb groß ... kann es sein, dass da was mit dem speicher nicht passt ? (laut datenblatt hab ich aber 8kb ?)
Hendrik S. schrieb: > Hendrik S. schrieb: >> kannst du mit bitte ein beispiel für die funktion geben ? ^^ >> in meinem falle dann ein zeichenanzahl=strlen(text); ?! > > :D ok nicht dumm rumfragen sondern einfach ausprobieren und geht ^^ zwar > mit den warnings: > ../Dotmatrix.c:121: warning: implicit declaration of function 'strlen' > ../Dotmatrix.c:121: warning: incompatible implicit declaration of > built-in function 'strlen' Siehe zb jedes noch so schlechte C-Buch oder http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F für die absolut notwendige Kurzfassung #include <string.h> > bleibt jedoch mein fehler mit der zeichenbegrenzung meines strings... Ganz ehrlich. Der Code ist mir viel zu unübersichtlich als das ich da jetzt groß zu analysieren anfange, was da passiert. Schaff dir ein paar vernünftige Schichten an * Eine Funktion die aus einem String 20 Zeichen (so sie existieren) ab einer pestimmten Position auf dem LCD ausgibt. * Darüber liegt eine Funktion, die einen beliebig langen String ausgeben kann, dass tut sie indem sie nacheinander die vorhergehende Funktion bemüht, wobei immer um 1 Zeichen weitergeschaltet wird, bis der String zu Ende ist. Programmieren bedeutet nicht, möglichst viel Funktionalität in eine Funktion reinquetschen, sondern sich einen Baukasten aus Funktionen zurechtzuschneidern. Von einfachen Funktionen bis zu komplizierteren Funktionen, die die einfachen Funktionen benutzen um ihre komplizierte Arbeit zu erledigen. Gib deinen Funktionen und Variablen vernünftige Namen. Ausg, Ausg_1, Ausg_2 sind keine vernünftige Namen. Ein Funktionsname soll beschreiben was die Funktion tut. Wenn es dabei eine Besonderheit gibt, dann soll sich diese Besonderheit im Namen wiederspiegeln. Den Unterschied zwischen Ausg_1 und Ausg_2 kann man am Namen nicht ablesen.
ich denke mein problem ist es, dass ich mir das selbst beibringe und
sonst keinen habe , der mich auf formfehler hinweist und mir iwas
erklären kann =( ich würde gerne mein c-buch richtig durchackern und
alles mal ausprobieren.. ich hab aber nur die möglichkeit direkt auf µc
umzusteigen und zu testen ob ich irgendwas verstanden habe und dazu
fehlen mir vielleich grundlegende dinge...
hierzu kommt: ich finde hier im forum einen batzen an lustigen befehlen,
die ich noch nie gesehen habe und da ich mein c-buch (sofern es da
irgendwo wirklich drinnen steht) noch nicht "auswendig" kann. ich würde
gerne stück für stück sachen ausprobieren um mich an C zu gewöhnen ^^
darum entschuldige ich mich für jegliche verwirrungen und verplantheit
in meinem code wenn du das jedoch so siehst , dann ist es nicht ganz wie
ein lcd mit 20 stellen zu sehen sondern wie ein lcd mit 3,5 xD ich muss
also buchstaben auch teilweise ausgeben
ich werde mich dann wohl mal an eine andere durchführung meiner ausgabe
kümmern. die stand nämlich schon ganz am anfang und ich hab versucht
mein programm darauf anzupassen...
dennoch kleine frage:
ich hab ja teilweise "prototyp"-Namensvergebungen gemacht oder wie man
das wirklich nennt :D...
geht das auch mit dem hier ?
>void Ausg_1(char* stringzeiger)
hab da einige möglichkeiten ausprobiert finde dazu aber keine lösung
oder vielleich eine ohne warnungen vom compiler ? oder muss ich das
komplett anders schreiben ?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.