C Lauftschrift auf einem LCD 2 x 20

Dann würde das "H" aber jedesmal direkt an der 20 ten Stelle stehen beim wiederholen. Das will ich eben nicht. Es soll auch reingeschoben werden. Also brauche ich einen virtuellen Grafik RAM
 
du löschst doch die Zeile vorm scrollen, ist doch das selbe…
 
Wie gesagt das mit der Laufschrift funktioniert schon. Nur ich muss halt in meinem String die Leerzeichen mit berücksichtigen, dass wollte ich halt in der Funktion machen und nicht im String die "Leerzeichen" expliziert noch einmal mit angeben zu müssen.
 
Hi Janiiix,

hier mal eine mögliche Lösung von mir.

Der erste Parameter ist int8_t und adressiert die Spalte. Bei x=0 befindet sich das erste Zeichen des Strings in der ersten Spalte. Bei negativen werten ist der String nach links verschoben, bei positiven nach rechts.




CodeBox C
#include <stdlib.h>
#include <string.h>

// ...

#define DISPLAY_WIDTH2  12  // bei dir sollten es 20 sein

void display_string(int8_t x, uint8_t y, char *s)
{
   uint8_t col = 0;

 
   if (y == 1)
   lcd_gotoxy(0, 1);  // Zweite Zeile
   else
   lcd_gotoxy(0, 1);  // Erste Zeile
 

   // Leerzeichen vor dem String
   if (x>=0)
   {
     // Leerzeichen vor dem String
     while((col < x) && (col < (DISPLAY_WIDTH2)))
     {
       lcd_putc(' ');
       col++;
     
     }
   
     // Der String
     while ((*s) && (col < (DISPLAY_WIDTH2)))
     {
       lcd_putc(*s++);
       col++;
     }
   
     // Leerzeichen nach dem String
     while (col < (DISPLAY_WIDTH2))
     {
       lcd_putc(' ');
       col++;
     }
   
   
   } else {
   
   
     if ((x+strlen(s)) <= 0)
     {
       // String links, nur Leerzeichen ausgeben
       while (col < (DISPLAY_WIDTH2))
       {
         lcd_putc(' ');
         col++;
       }
     } else {
       // Der String
       uint8_t i = abs(x);
       while ((s[I]) && (col < (DISPLAY_WIDTH2)))
       {
         lcd_putc(s[i++]);
         col++;
       }
       // Leerzeichen nach dem String
       while (col < (DISPLAY_WIDTH2))
       {
         lcd_putc(' ');
         col++;
       }
       
     }
     
   }
   
}


Und so rufe ich die Funktion auf, das Ergebnis siehst du unten im Video.

Ich verwende ein Grafik LCD, da ich im Moment nichts anderes hier habe. Das Autoinkrement (um ein Zeichen) habe ich in der Routine lcd_putc nachgebildet, damit sich die Funktion display_string bei deinem LCD genauso verhält (ich könnte bei mir den String auch pixelweise setzen).

Das ganze könnte man nun noch für Strings aus dem Flash Memory umschreiben, dann wird für die Strings nicht so viel sram benötigt.

Dirk :ciao:


CodeBox C
int8_t x;
while (1)
{
   x = -30;
   do
   {
     display_string(x, 0, "Dies ist ein Test-String!");
     _delay_ms(100);
     x++;
   } while (x<17);
   
   do
   {
     display_string(x, 0, "Dies ist ein Test-String!");
     _delay_ms(100);
     x--;
   } while (x>-30);
   
}


 
Cool, dass sieht schon mal richtig geil aus. Was genau macht das Marko "abs" ? Es gibt den relativ Wert von der Variable aus? Das heißt er macht einfach nur das Vorzeichen weg?

Aber, während ich diese Funktion aufrufe, kann ich ja nichts anderes machen (anzeigen)
 
Aber, während ich diese Funktion aufrufe, kann ich ja nichts anderes machen (anzeigen)

Die Funktion display_string benötigt (wenn man die lcd Funktionen nicht betrachtet) grob 2 bis 5us bei 16MHz Systemtakt.

Du meinst wahrscheinlich den Code in der unteren Codebox? Das ist ja nur zum Testen. Wenn du die Funktion bei dir ausprobieren möchtest, kannst du das ja erst mal genau so übernehmen. Danach programmierst du dein "Task-System", so dass die _delay_ms wegfallen. Das solltest du nun eigentlich hinbekommen ;)

Dirk :ciao:
 
Sorry Dirk, habe das delay in dem aufrufer übersehen. Das delay kann ich natürlich mit meinem Timer Takt koppeln. Werde es direkt nacher mal ausprobieren.

Wo kann man das Board kaufen was du benutzt? Oder hast du dies selber gemacht?
 
Wo kann man das Board kaufen was du benutzt? Oder hast du dies selber gemacht?

...ist von mir und man kann es kaufen.
Es ist ein Mikrocontrollermodul mit ATmega2560.
MEGA2560-USB_1.jpg

Infos findest du zum Beispiel hier im Forum in der Ressource
Bootloader für meine AVR-Mikrocontrollermodule.
Links zum Shop findest du weiter unten in dieser Ressource.

Dirk :ciao:

http://www.makerconnect.de/index.ph...2b-an-mega2560-usb-mikrocontrollermodul.6589/
http://www.makerconnect.de/index.ph...lermodule-mega2560-usb-und-xmega-a4-usb.3654/
 
Zuletzt bearbeitet:
Hier die Flash Version.:



CodeBox C
void display_string_flash(int8_t x, uint8_t y,const char *s)
{
   uint8_t col = 0;
   
   
   if (y == 1)
   lcd_gotoxy(0, 1);  // Zweite Zeile
   else
   lcd_gotoxy(0, 1);  // Erste Zeile
   
   
   // Leerzeichen vor dem String
   if (x>=0)
   {
     // Leerzeichen vor dem String
     while((col < x) && (col < (DISPLAY_WIDTH)))
     {
       lcd_putc(' ');
       col++;
       
     }
     
     // Der String
     while ((pgm_read_byte(s)) && (col < (DISPLAY_WIDTH)))
     {
       lcd_putc(pgm_read_byte(s++));
       col++;
     }
     
     // Leerzeichen nach dem String
     while (col < (DISPLAY_WIDTH))
     {
       lcd_putc(' ');
       col++;
     }
     
     
     } else {
     
     
     if ((x+strlen(s)) <= 0)
     {
       // String links, nur Leerzeichen ausgeben
       while (col < (DISPLAY_WIDTH))
       {
         lcd_putc(' ');
         col++;
       }
       } else {
       // Der String
       uint8_t i = abs(x);
       while ((pgm_read_byte(s)) && (col < (DISPLAY_WIDTH)))
       {
         lcd_putc(pgm_read_byte(s++));
         col++;
       }
       // Leerzeichen nach dem String
       while (col < (DISPLAY_WIDTH))
       {
         lcd_putc(' ');
         col++;
       }
       
     }
     
   }
   
}
 
Zuletzt bearbeitet:
Okay,

Er rollt zwar die Zeichen rein (aber auch nur eine bestimmte Anzahl) und dann bleibt der unvollständige Text stehen. Aber nur bei meiner Flash Version.
 
Er rollt zwar die Zeichen rein (aber auch nur eine bestimmte Anzahl) und dann bleibt der unvollständige Text stehen. Aber nur bei meiner Flash Version.

Dafür gibt es zwei Gründe.

1.


CodeBox C
if ((x+strlen(s)) <= 0)

Du benötigst die Länge des Strings im Flash Memory, nicht die eines Strings im sram.

2.


CodeBox C
uint8_t i = abs(x);

Was passiert in deinem Code mit i?


Deine Code habe ich korrigiert.

Probleme hatte ich mit strlen_P (ermittelt Länge des Strings im Flash). Damit gibt oder gab es auch irgendein Problem. Ich habe im Moment keine Zeit danach weiter zu suchen und das manuell eingebaut.

Dirk :ciao:



CodeBox C
void display_string_flash(int8_t x, uint8_t y, const char *s)
{
   uint8_t col = 0;
   
   
   if (y == 1)
   lcd_gotoxy(0, 1);  // Zweite Zeile
   else
   lcd_gotoxy(0, 1);  // Erste Zeile
   
   
   // Leerzeichen vor dem String
   if (x>=0)
   {
     // Leerzeichen vor dem String
     while((col < x) && (col < (DISPLAY_WIDTH)))
     {
       lcd_putc(' ');
       col++;
       
     }
     
     // Der String
     while ((pgm_read_byte(s)) && (col < (DISPLAY_WIDTH)))
     {
       lcd_putc(pgm_read_byte(s++));
       col++;
     }
     
     // Leerzeichen nach dem String
     while (col < (DISPLAY_WIDTH))
     {
       lcd_putc(' ');
       col++;
     }
     
     
   } else {
     
     
     uint8_t len = 0;
     while (pgm_read_byte(&s[len])) len++;

     if ((x+len) <= 0)
     {
       // String links, nur Leerzeichen ausgeben
       while (col < (DISPLAY_WIDTH))
       {
         lcd_putc(' ');
         col++;
       }
     } else {
       // Der String
       uint8_t i = abs(x);
       while ((pgm_read_byte(&s[i])) && (col < (DISPLAY_WIDTH)))
       {
         lcd_putc(pgm_read_byte(&s[i++]));         
         col++;
       }
       // Leerzeichen nach dem String
       while (col < (DISPLAY_WIDTH))
       {
         lcd_putc(' ');
         col++;
       }
       
     }
     
   }
   
}
 
Aha,

Wieso ist der String im Flash größer als im SRAM?
 
Wieso ist der String im Flash größer als im SRAM?

Ist er doch nicht :hmmmm:

Bei mir sieht die Belegung des Flash Memory zum Beispiel so aus ...


CodeBox C
display_string_flash(x, 0, PSTR("Dies ist ein Test-String!"));

000000fe <__c.2243>:
  fe:   44 69 65 73 20 69 73 74 20 65 69 6e 20 54 65 73  Dies ist ein Tes
  10e:   74 2d 53 74 72 69 6e 67 21 00  t-String!.
 
Ich mutmaße mal dass nach dem Warum ein Komma fehlt.
Auf Flash Speicher muss anders zugegriffen werden wie auf den SRAM. Auch in Assembler sind es andere Befehle.
 
Dafür gibt es zwei Gründe.

1.


CodeBox C
if ((x+strlen(s)) <= 0)

Du benötigst die Länge des Strings im Flash Memory, nicht die eines Strings im sram.

2.


CodeBox C
uint8_t i = abs(x);

Was passiert in deinem Code mit i?


Deine Code habe ich korrigiert.

Probleme hatte ich mit strlen_P (ermittelt Länge des Strings im Flash). Damit gibt oder gab es auch irgendein Problem. Ich habe im Moment keine Zeit danach weiter zu suchen und das manuell eingebaut.

Dirk :ciao:

}[/C]


Ich habe es so verstanden, dass es einen größen Unterschied gibt.
 
Ich habe es so verstanden, dass es einen größen Unterschied gibt

Nein, strlen_P ermittelt nicht die richtige Länge. (Ich habe hier nicht weiter nach dem Grund gesucht)

Alternativ ermittel ich die Länge so ...



CodeBox C
uint8_t len = 0;
while (pgm_read_byte(&s[len])) len++;


Auf Flash Speicher muss anders zugegriffen werden wie auf den SRAM. Auch in Assembler sind es andere Befehle.
Das ist klar. Der C Compiler hat hierfür diverse Macros und Funktionen. Janiiix hatte nur vergessen, auch die Länge des Strings im Flash zu ermitteln und dann war noch ein Indexierungsfehler des String-Arrays in seiner Funktion.
 
uint8_t len = 0;while (pgm_read_byte(&s[len])) len++;

Du übergibst der Funktion die Adresse und incrementierst dann vom String den Index.
Woher weißt du wann der String zu ende ist ?
 
Woher weißt du wann der String zu ende ist ?
Es gibt ein Stringende-"Zeichen", das ist 0.

000000fe <__c.2243>:
fe: 44 69 65 73 20 69 73 74 20 65 69 6e 20 54 65 73 Dies ist ein Tes
10e: 74 2d 53 74 72 69 6e 67 21 00 t-String!.

vielleicht verständlicher ...


CodeBox C
uint8_t len = 0;
while (pgm_read_byte(&s[len]) != 0) len++;
 
Okay. Dann ist es ja richtig clever dafür die while zu nutzen. Solange die Bedingungen in der while wahr sind also 1 arbeitet sie ja.

Aber wieso übergibt man nochmal die Adresse? Müsste die nicht bekannt sein Dank des Parameters vom Aufruf?
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)