PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Laufschrift aktualisieren, Probleme mit char*



PCMan
17.07.2007, 21:47
Hallo Forum,
nachblutigem rumprogrammieren bin ich mit meiner Geduld am Ende und ersuche hier erneut Rat. Kurz und Knapp:
- Mittels den Bibliotheken von P. Fleury steuere ich erfolgreich ein LCD an
- Durch einen Timer habe ich eine kleine Laufschrift realisiert.
- Mit einem anderen Timer frage ich 4 Tasten ab.
- Ich möchte, dass bei jedem Tastendruck ein anderer Text als Laufschrift auftaucht. Das klappt "eigentlich", nur nicht so wie ich will. Ich möchte dass bei dem Tastendruck die Laufschrift von Vorne startet, bisher ist es aber so, dass sich immer an's Ende des zuvorgehenden anhängt. Hier erstmal etwas Code:

Hier wird die eigentliche Laufschrift gebildet.Ich muss immer die Länge des Strings ermitteln lassen. Wenn ich ihn einmal ermittle und in einer Variablen zwischenspeicher, dann läuft der Text sozusagen aus.



ISR(TIMER2_OVF_vect)
{

if (LCD_hold==0){
if (T2Counter == 0) {
lcd_gotoxy(0,LCD_SCROLLING_ROW);

for (uint8_t i=0; i<=LCD_ROW_LENGTH; i++) {
lcd_putc(LCD_lauftext[i]);
}

LCD_temp=LCD_lauftext[0];
for (uint8_t i=0; i<=strlength((const char *)LCD_lauftext); i++) {
LCD_lauftext[i]=LCD_lauftext[i+1];
}
LCD_lauftext[strlength((const char *)LCD_lauftext)]=LCD_temp;

T2Counter = T2Counter_backup;
} else T2Counter--;
}
T2Of=1;
TCNT2=T2Preloader;
}

Die Funktionen, die mir den Timer initialisieren:


void lcd_clr_scrollbar() {

TCCR2 &= ~(1<<CS22); //timer abstellen
TCCR2 &= ~(1<<CS21);
TCCR2 &= ~(1<<CS20);
lcd_gotoxy(0,LCD_SCROLLING_ROW);
lcd_puts(" "); //löscht Zeile
}

void lcd_scroll_text(char* text, uint16_t Hz, uint8_t delay_factor){
/* Hier haebe ich schon verschiedenes getestet: direkte Zuweisung wie unten gezeigt, oder über eine for Schleife die einzelnen chars neu beschrieben, funktionierte alles nicht so wie ich wollte. Bei der For Schleife z.B. wurde einfac garnichts in den String LCD_lauftext aufgenommen. LCD_lauftext ist übrigens eine globale volatile char* variable*/
LCD_lauftext=text;

T2Counter=delay_factor;
T2Counter_backup=delay_factor;
TCCR2|=(1<<CS22)|(1<<CS21)|(1<<CS20); //Prescaler=1024
T2Preloader=256-F_CPU/LCD_PRESCALER/Hz;
TCNT2=T2Preloader;
TIMSK |= (1<<TOIE2);
T2Of=0;
LCD_hold=0;
}


In der Hauptschleife dann die Abfrage der Taste und Reaktion auf dem Display anzeigen:


keypad_open(KEYPAD_SCANNING_FREQUENCY,KEYPAD_DEBOU NCE_SLOW);
for (;;) {

uint8_t key = keypad_check();
if (key==KEYPAD_KEYOK) { lcd_clr_scrollbar(); lcd_scroll_text("Es wurde die Taste [OK] betaetigt +++ ",LCD_SCANNING_FREQUENCY,LCD_DELAY_FACTOR); keypad_open(KEYPAD_SCANNING_FREQUENCY,KEYPAD_DEBOU NCE_SLOW); } else
if (key==KEYPAD_KEYESC) { lcd_clr_scrollbar(); lcd_scroll_text("Die Taste [ESC] gedrueckt +++ ",LCD_SCANNING_FREQUENCY,LCD_DELAY_FACTOR); keypad_open(KEYPAD_SCANNING_FREQUENCY,KEYPAD_DEBOU NCE_SLOW); } else
if (key==KEYPAD_KEYINC) { lcd_clr_scrollbar(); lcd_scroll_text("[+] wurde betaetigt +++ ",LCD_SCANNING_FREQUENCY,LCD_DELAY_FACTOR); keypad_open(KEYPAD_SCANNING_FREQUENCY,KEYPAD_DEBOU NCE_SLOW); } else
if (key==KEYPAD_KEYDEC) { lcd_clr_scrollbar(); keypad_open(KEYPAD_SCANNING_FREQUENCY,KEYPAD_DEBOU NCE_SLOW); }
}
}


So das war's eigentlich, wenn noch Fragen sind, bitte posten.
System:
ATMega 32, JTAGEN disabled, Crystal = 8MHz. Das Keypad verwendet Timer0, das LCD Timer2 (salopp formuliert)


Freue mich auf Antworten,
viele Grüße,
Simon

Pierce466
17.07.2007, 23:38
Hallo,


Hier wird die eigentliche Laufschrift gebildet.Ich muss immer die Länge des Strings ermitteln lassen. Wenn ich ihn einmal ermittle und in einer Variablen zwischenspeicher, dann läuft der Text sozusagen aus.....

setz jedesmal bevor du die laufschrift auf dem dispaly aktualisierst ein


lcd_clear();

davor....

dann sollte der aktuelle text gelöscht werden und der neue erscheinen...

mfg pierce

PCMan
18.07.2007, 09:15
Meinst du jedes mal bevor ein neuer Text geladen wird oder vor jedem mal, wo die Buchstaben verschoben werden?
Bevor ein neuer Text geladen wird lösche ich ja jedesmal bereits die Zeile (lcd_clr_scrollbar();). Das Problem ist, dass im Speicher (also in der globalen volatile Variablen LCD_lauftext) noch was drin steht. Und das muss ich löschen, aber ich weiß nicht wie ich das hinbekomme. Mit For-Schleifen zeichenweise zu überschreiben funktioniert nicht und eine Zuweisung à la LCD_lauftext = "" funktioniert auch nicht, da bleibt der Inhalt gänzlich unangetastet...
vG

Pascal
18.07.2007, 09:23
Mit For-Schleifen zeichenweise zu überschreiben funktioniert nicht

Eigentlich müsste das schon funktionieren. Zeig mal deinen code dazu.

PCMan
18.07.2007, 09:38
Das würde dann so aussehen:


void lcd_scroll_text(char* text, uint16_t Hz, uint8_t delay_factor){

for (uint8_t i=0; i<=strlength(text); i++){
LCD_lauftext[i]=text[i];
}
//LCD_lauftext=text;
T2Counter=delay_factor;
T2Counter_backup=delay_factor;
TCCR2|=(1<<CS22)|(1<<CS21)|(1<<CS20); //Prescaler=1024
T2Preloader=256-F_CPU/LCD_PRESCALER/Hz;
TCNT2=T2Preloader;
TIMSK |= (1<<TOIE2);
T2Of=0;
LCD_hold=0;
}


Ergbnis: Scrollende Zeile bleibt schlict und ergreifend leer. Wieso? Das ergibt keinen Sinn!?

Ich habe übrigens in die Anweisung, wo die Buchstaben verschoben werden (ISR v. TIMER2) ein lcd_clrscr() eingefügt. Das ändert aber ebenfalls nicht das Problem, dass bei einem neuen Text noch Reste des alten vorhanden sind. Scheinbar wird der neue Text auch "irgendwo" im alten eingefügt und nicht angehängt...
vG Simon

PCMan
18.07.2007, 09:44
nochwas: außer "function isnt a prototype" habe ich sonst keine compiler warnungen die auf einen Fehler hindeuten. Aber das Prototypen-Problem hat damit ja nichts zu tun...

PCMan
18.07.2007, 10:33
Hallo Freunde,
wenn ich aus
volatile char* LCD_lauftext;

volatile char LCD_lauftext[30]; mache funktioniert die Geschichte. Der Algorithmus funktioniert also. Das ganze erscheint mir aber recht undynamisch. Im Übrigem bestätigt es die Vermutung, dass es Pobleme mit char* gibt, dass sich wohl nicht wie ein Array behandeln lässt. Habt ihr eine Ahnung, wie sich das Problem beheben lässt?
vG Simon

ogni42
18.07.2007, 11:14
Wenn LCD_lauftext ein globaler char-Pointer ist muss er vor Benutzung auf einen existierenden Speicherbereich zeigen.



const textLength = 32;
char* globalPointer = NULL;

char myCharArray[textLength];

void init( void )
{
globalPointer = myCharArray;
}

PCMan
18.07.2007, 13:47
also damit ich das richtig verstehe: ich muss so oder so einen festen Speicher als Array reservieren? Kann man das auconh irgendwie dynamisch machen? In deinem Code beschränke ich mich auf 32 Zeichen, oder?
Vielen Dank,
vG Sim

ogni42
20.07.2007, 10:40
Du brauchst Speicher, wo Deine Daten reinkommen. Ergo entweder den Speicher fest allokieren (z.B. char bla[länge]) oder dynamischen Speicher holen


char* globalPointer = NULL

bool init( void )
{
globalPointer = malloc( stringlength * sizeof( char ) );
return globalPointer != NULL;
}


Ich würde in Deinem Fall die statische Variante bevorzugen, weil das viel Platz im Flash spart, da im dynamischen Fall, die ganze Heapverwaltung mit hinzu gelinkt werden muss.

PCMan
20.07.2007, 13:01
Hi!
Auf die Funktionen mallloc und new bin ich auch schon gestoßen. Es gibt da ja eine Bibliothek zum Anlegen von Strings, die diese Speicherallokation automatisch übernimmt. Doch ehrlichgesagt bleibe ich tatsächlich bei der statischen Variante als eine neue Bibliothek einzubinden.
Vielen Dank für die Hilfe,
vG Simon