avr-gcc schrieb:> uart_putc(27);> uart_puts("[2J");> uart_putc(27);> uart_puts("[H");>> Wie kann man sowas als einen befehl schreiben?
Ich würd's so machen:
Das ganze funktioniert auch recht gut. Nun zwei Fragen,
wenn ich das Display löschen möchte,
wie sieht der Befehl von oben nun hier aus?
1
voiduart_clear(void)
2
{
3
lcd_command(ESC_ERASE_DISPLAY);
4
lcd_command(ESC_CURSOR_POS_RESTORE);// ????
5
}
Des weiteren habe ich keine Möglichkeit, den Cursor zu setzen. Das
sollte in Putty soweit bekannt eigentlich gehen. Attribute wie
ESC_BG_RED funktionieren alle.
Frage 1:
Du gibst dir doch die Antwort schon selbst. Wenn du das Display nur
löschen möchtest, dann mach auch genau das. Was genau hat
CURSOR_RESTORE_POS mit dem Löschen des Displays zu tun. Du brauchst den
Makro Namen nur zu lesen um zu wissen, dass da irgendwas mit dem Cursor
passiert und das hat erst mal nichts damit zu tun, dass die Anzeige
geleert wir
avr-gcc schrieb:> void uart_setCursor(uint8_t x, uint8_t y)> {> uart_command(ESC_CURSOR_POS(x, y));> }
Wie sollte das denn auch gehen? Die Markos erstellen jeweils ein "string
literal" also eine Zeichenkettenkonstante. Du übergibst hier aber
Variablen. Wenn du die brauchst, mußt du den String zur Laufzeit
zusammenbasteln. Das können diese Makros nicht leisten.
Das Makro nimmt einfach x und y als Text und fügt das ein, es ensteht
also
1
"\33[x;yH"
und daß dein Terminal mit diesem String nix anfangen kann, ist klar.
Zur Frage 2:
Das kann auch nicht funktionieren, wenn dir klar waere, dass Makros im
Grunde nur Textersetzungen sind, die zur Compilier Zeit vorgenommen
werden.
Dein Makro expandiert also im besten Fall zu einem String, in dem die
Buchstaben x und y vorkommen und nicht die entsprechenden Zahlenwerte
avr-gcc schrieb:> wie sieht der Befehl von oben nun hier aus? void uart_clear(void)> {> lcd_command(ESC_ERASE_DISPLAY);> lcd_command(ESC_CURSOR_POS_RESTORE); // ????> }
Nein. Um eine Cursor-Position zu restoren, mußt du erstmal eine
gespeichert haben. Dein ESC [H gibt es in deinen Makros nicht. Das habe
ich auch erstmal eine Weile suchen müssen, weil es offenbar keine
Standard-ANSI-Escape-Sequenz ist. Da kommen vor dem H normalerweise noch
die Zielkoordinaten (Siehe ESC_CURSOR_POS).
Übrigens kannst du die Kommandos auch mit einem Aufruf schicken:
> Oktal ist natürlich obercool.
Ach was, damit hat Rolf auf dem International Obfuscated C Code Contest
keine Chance.
Problem ist, einen sinnvollen Mittelweg zu finden.
Nimmt man "\033[2J", weiß der nächste nicht mehr, was 2J eigentlich
macht. Nimmt man ein geniales System an Defines, weiß der nächste nicht
mehr, wie man des Programm auf ein anderes Terminal umstellt.
Mit den gefundenen Befehlen hast du dir halt 2 Probleme eingehandelt. Du
musst herausfinden, was Putty erwartet. Und zusätzlich musst du
herausfinden, ob diese Defines das richtige liefern.
Wenn beides zusammen zu verwirrend ist, warum bleibst du dann nicht
einfach bei dem Vorschlag von Karl Heinz? Oder einfach bei den 4 Zeilen,
mit denen du es ursprünglich gelöst hast?
> Geht so.>> Nur bin ich noch nicht weiter, wie ich das mit dem setCursor realisieren> soll. Konstante Werte gehen ja.>>
1
>uart_command(ESC_CURSOR_POS(5,5));
2
>
>> Nur sowas leider nicht>
1
>_delay_ms(200);
2
>inty=0;
3
>uart_command(ESC_CURSOR_POS(0,y));
4
>uart_putc('a');
5
>y++;
Wie kriegt man denn zur Laufzeit einen String, bei dem Zahlenwerte aus
dem laufenden Programm eingesetzt werden?
Sorry. Aber ein bisschen Nachdenken musst du schon auch selbst. Vergiss
mal die Makros
Hallo kh,
habe es jetzt nun mal Testweise mit sprintf versucht. Geht, aber erzeugt
auf dem Attiny einen ordentlichen Zuwachs des Programm Speichers. (+10%)
Ich würde gerne die Funktion (sprintf) aus diesem Grund vermeiden, da
sie nicht wirklich andersweitig benötigt wird.
void uart_setcursor(uint8_t x, uint8_t y)
{
char str[20];
sprintf(str,"\33[%d;%dH",y,x);
uart_command(str);
}
avr-gcc schrieb:> Bringt meinen µC leider in einem undefinierten Zustand -> stürzt ab.
Da sind auch ziemlich viele Fehler drin.
> void uart_setcursor(uint8_t x, uint8_t y)> {> char buffer[20];> char buffer2[10];> strcat(buffer, '\33');
Das strcat sucht im uninitialisierten Puffer nach dem ersten \0.
Außerdem erwartet es die Adresse eines Strings. '\33' ist keine Adresse.
> itoa(x, buffer2, 10);> strcat(buffer, buffer2);> itoa(y, buffer2, 10);> strcat(buffer, buffer);
Warum wird da der Buffer an sich selbst gehängt?
> strcat(buffer, y+'0');> strcat(buffer, 'H');
Dei beiden haben das gleiche Problem wie oben. Und wo ist das Semikolon
zwischen den beiden Zahlen? Warum wird y zweimal angehängt?
> uart_command(buffer);> }
avr-gcc schrieb:> Hallo kh,>> habe es jetzt nun mal Testweise mit sprintf versucht. Geht, aber erzeugt> auf dem Attiny einen ordentlichen Zuwachs des Programm Speichers. (+10%)
ok. Dann musst du dir einen gleichwertigen Ersatz dafür sorgen, der
genau das kann, was du erreichen willst.
Hinweis: dem Terminal ist es völig egal, ob du in Etappen ausgibst, oder
ob du dir die Mühe machst, den String erst mal komplett zusammen zu
setzen. Das Terminal sieht nur die Zeichen, die aus der Schnittstelle
rauskommen. Und das geht in jedem Fall langsamer, als ein paar
Funktionsaufrufe für Subfunktionen, die zb einen String oder eine Zahl
per UART auf die Reise schickt.
Du willst also
* eine textuelle 'Eröffnungsseqqquenz' senden
* dann die Zeile (in ihrer gewandelten Form als Text)
* dann einen ,
* dann die Spalte (in ihrer gewandelten Form als Text)
* die Abschlusssequenz, in der dann ausgesagt wird, welches Kommando das
ist
Niemand sagt, dass du alles erst mal in einen String sammeln musst. Du
kannst es auch auf Etappen machen und einzeln auf die Reise schicken.
Karl H. schrieb:
Und noch ein Hinweis. Hier ...
> * dann die Zeile (in ihrer gewandelten Form als Text)
... verbirgt sich eine weitere Hilfsfunktion drinnen, die man praktisch
ständig immer wieder braucht: Nämlich die Ausgabe einer Zahl in lesbarer
Form über die UART. Es wird also sinnvoll sein, ähnlich wie bei der
Hilfsfunktion die einen String ausgeben kann, sich hier eine
Hilfsfunktion zu machen die eben genau das kann: Zahlen in ihrer
textuellen Form über die UART auszugeben.
Funktioniert zumindest bedingt schon einmal.
Er macht einmal den Zeilensprung in die 2. Zeile. Danach schreibt er
aber alle Werte immer in die erste Zeile. Die Spalten werden richtig
gesetzt.
avr-gcc schrieb:> Meinst du das so?
IM Prinzip: ja.
Nur wie schon gesagt: Dia Ausgabe einer Zahl ist etwas, was man immer
wieder mal braucht. D.h. man baut sich da eine Hilfsfunktion
1
voiduart_puti(intzahl)
2
{
3
charstr[7];
4
5
itoa(zahl,str,10);
6
uart_command(zahl);
7
}
btw. uart_command ist ein schlechter Name. Denn tatsächlich tut die
Funktion nichts anderes als einen String auszugeben. Dass dieser String
ein Kommando ist, braucht hier nicht mehr zu interessieren.
Damit reduziert sich deine Funktion zu
1
voiduart_setcursor(uint8_tx,uint8_ty)
2
{
3
uart_command("\33[");
4
uart_puti(y);
5
uart_command(";");
6
uart_puti(x);
7
uart_command("H");
8
}
und das sieht dann doch gar nicht mehr so schlecht aus.
Ooops
> uart_puts_P(" ");> uart_setcursor(5,0);> uart_puti(val[count]);
du hast die Funktion bereits!
Warum verwendest du sie dann nicht?
avr-gcc schrieb:> Funktioniert zumindest bedingt schon einmal.> Er macht einmal den Zeilensprung in die 2. Zeile. Danach schreibt er> aber alle Werte immer in die erste Zeile. Die Spalten werden richtig> gesetzt.
Na ja. Was erwartest du. Sieh dir mal deine Aufrufe an.
Du schickst den Cursor immer an dieselben Positionen.
Hallo Karl Heinz,
verstehe das nicht, dass ich immer in der gleichen Zeile schreibe.
Im ersten Teil setze ich den Cursor auf Spalte 5, Zeile 0.
Der alte Text wird ersetzt durch Leerzeichen.
Danach wird der Cursor wieder auf Spalte 5, Zeile 0 gesetzt, damit dort
der neue Wert überschrieben werden kann.
Danach soll in Spalte 7, Zeile 1 gewechselt werden. Dort erfolgt eine
formatierte Ausgabe. Löschen der alten Zeichen nicht erforderlich, da es
die Funktion macht.
avr-gcc schrieb:> Hallo Karl Heinz,>> verstehe das nicht, dass ich immer in der gleichen Zeile schreibe.
Was verstehst du daran nicht.
Wenn du uart_setcursor mit immer den gleichen Zahlenwerten aufrufst,
dann setzt dir die Funktion den Cursor auch immer in genau die
Zeile/Spalte, die du angegeben hast.
> Danach soll in Spalte 7, Zeile 1 gewechselt werden. Dort erfolgt eine> formatierte Ausgabe. Löschen der alten Zeichen nicht erforderlich, da es> die Funktion macht.
Ja schön.
Danach ist deine Schleife einmal durch und das Spielchen beginnt von
vorne: Cursor nach 5,0, ausgeben, etc.
Wenn ich deine Frage richtig verstanden habe, dann ist das auch genau
das, was du siehst. Also passiert genau das, was du programmiert hast.
avr-gcc schrieb:> Danach soll in Spalte 7, Zeile 1 gewechselt werden. Dort erfolgt eine> formatierte Ausgabe. Löschen der alten Zeichen nicht erforderlich, da es> die Funktion macht.
OK. Und wie macht das die Funktion?
avr-gcc schrieb:> Hallo,>> also nach meiner Überlegung dürfte es so nicht aussehen.
Das Problem ist, dass hier keine sieht oder weiss, wie es bei dir am
Terminal *tatsächlich aussieht.
Beschreib es nicht, sondern mach einen Screenshot
Hast du schon kontrolliert, ob die enstprechende Emulation in deinem
Terminal Programm auch aktiviert ist?
Alternativ könntest du auch einfach mal den \33 Teil weglassen und dir
am Terminal ansehen, was du tatsächlich innerhalb der Escape Sequenz
schickst (wenn dein Terminal keine Möglichkeit hat, dir das in Rohform
anzuzeigen)
Ich bin mir ausserdem jezt gar nicht mehr sicher, mit welcher Zahlen bei
der Cursorpositionierung begonnen wird zu zählen. Ist schon zu lange
her.
Ist die oberste Zeile die Zeile 0 oder die Zeile 1?
Einfach ausprobieren. Schicke den Cursor mal in die Zeile 2