mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Zeiger auf mehrere lange Strings im Flash


Autor: Heinz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Detlev T. (detlevt)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Heinz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
const char * DrawOneScreen( const char * Text )
{
  while(  noch Zeichen auszugeben sind und der Screen noch nicht voll ist ) {
    male Zeichen hin
    ++Text;
  }

  // warum wurde mit der Ausgabe aufgehört
  //
  // Weil der Text zu Ende ist?
  if( nächstes auszugebendes Zeichen != '\0' )
    return NULL;

  //
  // Nö, weil kein Platz mehr war. Einen Pointer auf die Stelle im Text
  // liefern, die nicht mehr ausgegeben werden konnte, und ab der es weiter
  // gehen soll
  //
  return Text;
}

und beim Aufruf
  ...
  const char* Text1 = "ein langer langer Text,\n"
                      "mit dem die Ausgaberoutine\n"
                      "umgehen können soll."


  ....

  const char* ScrollText;

  ....


  ScrollText = Text1;
  while( ScrollText ) {
    ScrollText = DrawOneScreen( ScrollText );
    if( ScrollText != NULL )
      Warte auf Benutzer, der das Zeichen zum Weiterscrollen gibt
  }

  ...

Autor: Nobody (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heinz schrieb:
> Die Frage ist eben wie ich die Zeiger machen soll (global?)

Pusten.

Autor: Heinz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: Nobody (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
void drawText_p( PGM_P flashText )
{
  char c;

  c = pgm_read_byte( flashText++ );
  while( c != '\0' ) {
    drawChar( c );
    c = pgm_read_byte( flashText++ );
  }
}

teste die und baut sie dann zur Scroll Maschine aus.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.