Hallo! Ich muss viel Text auf einem Display ausgeben. Dazu habe ich mehrere über 1000 Zeichen lange Strings im Flash (PROGMEM) meines Atmega168. Ich möchte nun den Text scrollen, brauche also einen Zeiger auf die aktuelle Position im Flash, ab der dann ausgegeben wird. Ich möchte der Ausgaberoutine übergeben, ab welchem Buchstaben sie den Text darstellen soll. Diese soll dann soviel text wie möglich auf einem Bildschirm darstellen und zurückgeben, wo der nächste Ausgabebildschirm beginnt. Einfach abzählen geht leider nicht, da u.A. Zeilenumbrüche im Text sind. Vorher müsste ich noch auswählen, welches "Kapitel", also welcher Strings angezeigt werden muss. Wie kann ich das machen?
Heinz schrieb: > Hallo! > Ich muss viel Text auf einem Display ausgeben. Dazu habe ich mehrere > über 1000 Zeichen lange Strings im Flash (PROGMEM) meines Atmega168. > Ich möchte nun den Text scrollen, brauche also einen Zeiger auf die > aktuelle Position im Flash, ab der dann ausgegeben wird. Soweit richtig > Ich möchte der Ausgaberoutine übergeben, ab welchem Buchstaben sie den > Text darstellen soll. Diese soll dann soviel text wie möglich auf einem > Bildschirm darstellen und zurückgeben, wo der nächste Ausgabebildschirm > beginnt. Einfach abzählen geht leider nicht, da u.A. Zeilenumbrüche im > Text sind. Dann muss die Ausgaberoutine sowas wie eine rudimentäre Screenverwaltung machen um festzustellen, wann der Screen voll ist. Das sind: * Zeichen mitzählen um zu wissen, wann ein erzwungener Umbruch erfolgen wird * Umbrüche mitzählen Kommt die Ausgaberoutine zur Erkentnis, das mit dem nächsten Zeichen seine eigene virtuelle Cursorposition unter den sichtbaren Bereich fällt, dann hört sie auf auszugeben und liefert die aktuelle Flashposition als Returnwert. Ist der String zu Ende, liefert sie NULL Ist doch nicht so schwer. Ein bischen mitzählen und sich das Zeichen ansehen, ehe es zum Display geschickt wird. Der Fall "runterscrollen" ist leicht. Interessanter ist der Fall: raufscrollen.
Hallo Heinz, Welcher Compiler? avr-gcc? Warum machst du das nicht mit Zeigern? Aufruf der Routine mit Zeiger auf das erste auszugebende Zeichen, Rückgabe eines Zeigers mit dem nächsten auszugebenden Zeichen. Der wird dann beim nächsten Aufruf verwendet. Eventuell Rückgabe von "nil" als Signal, dass der String komplett ausgegeben wurde. Gruß, DetlevT
Ich würde das schon gerne mit Zeigern machen, weiß aber eben nicht wie. Die Erkennung ob der Bildschirm voll ist klappt schon. Ist ein Grafikdisplay und wird dort gleich mit erledigt. Die Frage ist eben wie ich die Zeiger machen soll (global?) damit ich damit auf einen String im Flash zeigen und den Zeiger weiterschalten kann...
Heinz schrieb: > Ich würde das schon gerne mit Zeigern machen, weiß aber eben nicht wie. > Die Erkennung ob der Bildschirm voll ist klappt schon. Ist ein > Grafikdisplay und wird dort gleich mit erledigt. > Die Frage ist eben wie ich die Zeiger machen soll (global?) damit ich > damit auf einen String im Flash zeigen und den Zeiger weiterschalten > kann... Ähm
1 | const char * DrawOneScreen( const char * Text ) |
2 | {
|
3 | while( noch Zeichen auszugeben sind und der Screen noch nicht voll ist ) { |
4 | male Zeichen hin |
5 | ++Text; |
6 | }
|
7 | |
8 | // warum wurde mit der Ausgabe aufgehört
|
9 | //
|
10 | // Weil der Text zu Ende ist?
|
11 | if( nächstes auszugebendes Zeichen != '\0' ) |
12 | return NULL; |
13 | |
14 | //
|
15 | // Nö, weil kein Platz mehr war. Einen Pointer auf die Stelle im Text
|
16 | // liefern, die nicht mehr ausgegeben werden konnte, und ab der es weiter
|
17 | // gehen soll
|
18 | //
|
19 | return Text; |
20 | }
|
und beim Aufruf
1 | ...
|
2 | const char* Text1 = "ein langer langer Text,\n" |
3 | "mit dem die Ausgaberoutine\n" |
4 | "umgehen können soll."
|
5 | |
6 | |
7 | ....
|
8 | |
9 | const char* ScrollText; |
10 | |
11 | ....
|
12 | |
13 | |
14 | ScrollText = Text1; |
15 | while( ScrollText ) { |
16 | ScrollText = DrawOneScreen( ScrollText ); |
17 | if( ScrollText != NULL ) |
18 | Warte auf Benutzer, der das Zeichen zum Weiterscrollen gibt |
19 | }
|
20 | |
21 | ...
|
Das Problem ist dass ich die Zeichenketten im Flash speichern muss also const char Text1[] PROGMEM = "123..."; und da weiß ich eben nicht wie mit Zeigern umgehen...
Heinz schrieb: > da weiß ich eben nicht wie mit Zeigern umgehen... Das ist halt das frustrierende an Deiner Fragestellung: Wir wissen nicht und können nicht wissen was Du mit "umgehen" meinst. Dir hier erstmal eine Einführung in Zeiger zu geben habe zumindest ich keine Lust. Dafür gibt es Bücher. Von den verbleibenden, nicht-trivialen Möglichkeiten gibt es soviele das die wiederrum ganze Bücher füllen könnten. Im allgemeinen leitet man sich die auch aus den Grundlagen her. Was also, verd... nochmal, ist konkret Dein Problem?
@ Heinz (Gast) >Das Problem ist dass ich die Zeichenketten im Flash speichern muss also >const char Text1[] PROGMEM = "123..."; Das const kannst du weglassen, bringt nix. >und da weiß ich eben nicht wie mit Zeigern umgehen... Dann musst du ein C-Buch lesen, dort steht das drin. Und wird 1:1 auch auf dem AVR so angewandt. Naja, nicht ganz, der Typ ist dann halt PGM_P anstatt char*. Aber das macht vom logischen Gebrauch keinen Unterschied. MFG Falk
Und im Zweifel gibt es dann immer noch das AVR-GCC-Tutorial das einen ganzen Abschnitt über den Flash Speicher und wie man ihn benutzt bietet. Mit dem Wissen und dem Studium von zb der dort angegebenen Funktion uart_puts_p schreibt man sich dann als Ausgangspunkt ganz fix eine Ausgabefunktion für Texte, basierend auf einer Ausgabefunktion für einzelne Nicht-Flash-Zeichen, die man eh schon hat
1 | void drawText_p( PGM_P flashText ) |
2 | {
|
3 | char c; |
4 | |
5 | c = pgm_read_byte( flashText++ ); |
6 | while( c != '\0' ) { |
7 | drawChar( c ); |
8 | c = pgm_read_byte( flashText++ ); |
9 | }
|
10 | }
|
teste die und baut sie dann zur Scroll Maschine aus.
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.