Hallo zusammen,
ich habe aus dem Netz ein Beispiel für ein Display Menü genommen
mit C Struktur. (dieses Beispiel wurde hier auch schon öfter
angesprochen)
Da in dieser Strukur ein "const char *text" Pointer deklariert wird,
bin ich etwas gebunden was diese Texte angeht. Ich möchte den Menütext
aber zur Laufzeit ändern
und weiß nicht wie, und ob das so geht.
Eigentlich ist eine const ja so erstmal nicht änderbar.
Hier die Strukturdefinition:
1
typedefstructMenuestruktur// Struktur defnieren
2
{
3
constchar*text;// Pointer auf Textfeld
4
unsignedcharnum_menupoints;// Variable für die Anzahl der Menüpunkte
5
unsignedcharup;// Variable für up
6
unsignedchardown;// Variable für down
7
unsignedcharenter;// Variable für enter
8
unsignedcharoffset;// Variable für zusätzliche Werteübergabe
9
void(*fp)(void);// Pointer auf Void/Void Funktion
10
}MenuEntry;
hier werden die Menüstrings vergeben:
1
constcharmenu_000[]="[Hauptmenue] ";
2
constcharmenu_001[]=" ...anzeigen ";
3
constcharmenu_002[]=" ...aendern ";
nun das Menü organisieren:
1
MenuEntrymenu[]=
2
{
3
// Hauptmenü
4
{menu_000,11,0,0,0,0,0},//1
5
{menu_001,11,1,2,12,0,0},//2
6
{menu_002,11,1,3,34,0,0},//3
7
{menu_003,11,2,4,56,0,0},//4
8
9
10
// Untermenü
11
{menu_100,22,0,0,0,0,0},//5
12
{menu_101,22,12,13,12,0,funktionsaufruf},//6 Funktion aufrufen bei Entertaste
13
14
};
in der Main wird dann das Anzeigen und das Hin- und herspringen
aufgerufen.
Soweit funktioniert das auch alles.
Nun möchte ich die Texte, welche mit (const char menu_000[] =
"[Hauptmenue] ";)
vergeben wurden in der Main Schleife ändern.
Einmal widerspricht das ja der Konstantendefinition und zum Weiteren
weiß nicht, wie ich das konform anstellen muss.
Mein Versuch zur Laufzeit in einer Abfrage in der Main den Text zu
ändern:
1
strcat(*txt_,"NeuText: ");// neuen Text einbringen
2
strcat(*txt_,"\0");// Stringende
3
menu[1].text=*txt_[0];// Zuweisung
Der Code compiliert zwar, zeigt aber bei der Zeile (menu[12].text =
*txt_[0];)
eine Warnung "implicit conversion of int to ptr".
Wo hier int ist kann ich nicht nachvollziehen, denn txt_ ist definiert
als unsigned char *txt_[20];.
Auf dem Display wird in der Zeile dann nur Buchstabensalat angezeigt.
Kann mir jemand helfen das umzusetzen oder geht das so garnicht.?
Ich möchte allerdings nicht das System neu aufsetzen, deshalb bitte kein
anderes Menüprinzip vorschlagen.
Eher würde ich auf dynamische Texte verzichten.
Bitte habt Nachsehen mit Fehlern, ich bin da noch nicht so fit drauf.
PIC18F2585 und mikroc pro compiler.
Gruß und Danke vorab...
CL
Stefan E. schrieb:> Du kannst zwar die Texte selber nicht ändern, aber du kannst doch> einfach den Pointer in der Struktur auf einen anderen Text zeigen> lassen.> menu[1].text = "NeuText: ";
Hol ruhig mal ein bisl weiter aus mit der Beschreibung, wie gesagt, ist
Neuland.
Wenn ich einen anderen Text mit einem String übergebe, funktioniert das
auch prinzipiell.
1
menu[1].text="anderer Text ";
Aber eigentlich soll sich der Text aus einem Text und einer
Floatvariablen zusammensezten. Das hatte ich oben garnicht erwähnt.
quasi "neuer Text: 3.21".
1
strcat(txt_," NeuText:");// neuer Text
2
fltToa(Blechstaerke_Name[0],txt,2);// String mit 2 Kommastellen
3
strcat(txt_,txt);// gewandelte Float Zahl dran
4
Lcd_Cmd(_LCD_CLEAR);// Clear display
5
Lcd_Out(1,1,txt_);// LCD Ausgabe
Der Menüeintrag ist jetzt also ein geänderter String mit Zahlen.
Wenn ich diesen einfach mal direkt aufs LCD Display ausgeben lasse,
klappt das ja. siehe Bild.
Wenn doch alles klappt, warum geht es dann nicht so?
C. L. schrieb:> Konstantendefinition
Ein altes Mißverständnis. const definiert in C keineswegs eine
Konstante. Das Schlüsselwort ist lediglich das Versprechen des
Programmierers an den Compiler, dass er nicht vor hat, auf die
entsprechende Variable zu schreiben. Es verhindert keineswegs, dass man
das tut (genausowenig wie restrict Pointer Aliasing verhindert - das
ist nur das Versprechen, es nicht zu tun).
Diese Versprechen erlauben Compilern Optimierungen durchzuführen, die
sie ohne die entsprechenden Schlüsselworte nicht durchführen könnten.
Versprechen kann man brechen, muss dann aber - wie im richtigen Leben -
mit den potentiellen Folgen leben.
Felix U. schrieb:> C. L. schrieb:>> Aber eigentlich soll sich der Text aus einem Text und einer>> Floatvariablen zusammensezten.>> Dafür verwendet man sprintf.>> also z.B:>
1
>floatf=1.0f;
2
>staticcharmenutext[30];
3
>
4
>sprintf(menutext,"abc: %f",f);
5
>menu[1].text=menutext;
6
>
Ok, sprintf ist eingesetzt und habe ich jetzt probiert, gibt aber eine
"illigal pointer conversion" in der Zeile menu[1].text = menutext;
Warum gibts die Meldung, wenn doch ein sauberer String übergeben wird?
CL
derjaeger schrieb:>>Wahrscheinlich will er, dass du nach (const char *) castest.>> Ich kann den Code auch ohne Casting kompilieren (avr-gcc)
Ich verwende den MikroC pro for PIC V7.1.0.
Klappt das Programm denn bei Euch? Habt Ihr das ausgetestet oder eine
Möglichkeit das zu tun?
CL
Vielleicht kann dir das weiterhelfen:
https://forum.mikroe.com/viewtopic.php?f=72&t=48004&
>707 384 Illegal pointer conversion nokia_6610MyProject.c>getting this error when i compile my code in mikroc compiler>for avr,whereas when i m using avrstudio with same code it works well.
Das habe ich mir gerade angesehen, aber kann es nicht für mich umsetzen
wg. mangelnem Verständnis.
Definiert habe ich const unsigned char *FontTable;
Muss ich jetzt extern const unsigned char auf die Struktur; ???
Hä???
Weis gar nicht, was ich hier mache. Sry
Kann mir das mal jemand eben zeigen, wie ich das Prinzip auf meinen Code
anwenden kann?
CL
C. L. schrieb:> Das habe ich mir gerade angesehen, aber kann es nicht für mich> umsetzen> wg. mangelnem Verständnis.
Der schlägt exakt das gleiche vor, wie ich einige posts weiter oben.
Casten nach (const char *).
> Der schlägt exakt das gleiche vor, wie ich einige posts weiter oben.> Casten nach (const char *).>
1
>menu[1].text=(constchar*)menutext;
2
>
Ich habe das nun genau so eingegeben:
1
menu[1].text=(constunsignedchar*)menutext;
..fehlerfrei compiliert aber im Display geschehen auch in der Richtigen
Zeile Änderungen aber es stehen dort nur wilde Zeichen.
Es wird also in der richtigen Zeile (menu[1].text =) geändert aber
scheinbar nicht richtig interpretiert.
Wir scheinen doch kurz vor dem Ziel zu sein.
Was kann das noch sein?
CL
Wahrscheinlich hast du die Variable in die du sprintf benutzt, nicht
static oder global gemacht, wie ich das oben geschrieben habe. Wie du
jetzt auf das "unsigned" im cast kommst, ist mir auch schleierhaft.
Die daklaration ist: static char menutext[20];
Zeichen hatte ich auf 20 begrenzt weil das Display auf 20 Zeichen pro
Zeile hat.
Dann so verwendet: sprintf(menutext,"abc: %.2f", 3.21);
3.21 als Festwert, später auch mit Float Variable.
Zugewiesen dann so: menu[1].text = (const char *) menutext;
Das unsigned hatte ich mal probiert, weil es so auch nicht ging.
Folgendes ist mir allerdings aufgefallen!
Wenn ich es so mache, wie Du es sagst, dann flackert im Display die
Darstellung.
Wenn ich den String initialisiere bei der Definition mit
1
staticcharmenutext[20]={'a'};
dann ist alles gut, bis auf die wilden Zeichen, allerdings in der
korrekten Zeile.
@ Felix U
Kannst Du das Programm mal in einen PIC18F flaschen und mit Display
testen?
Dann würde ich Dir das mal via PN schicken.
CL
Ich habe leider keinen PIC, aber wenn du mal deinen ganzen Code
hochlädst, dann kann man noch weiterschauen. Versuche vielleicht auch
nochmal eine globale Variable für den Text, ohne static, es scheint ja
als würde der Speicherbereich mit "wilden Zeichen" überschrieben werden.
>bis auf die wilden Zeichen, allerdings in der korrekten Zeile.
Diese "wilden Zeichen" kommen wahrscheinlich, weil dein String nicht
nullterminiert ist.
Probier mal das so:
static char menutext[20] = "a";
Gehen dann diese wilden Zeichen weg?
Oder so:
Felix U. schrieb:> als würde der Speicherbereich mit "wilden Zeichen" überschrieben werden.
Das sieht zumindest genau so aus.
derjaeger schrieb:> static char menutext[20] = "a";>> Gehen dann diese wilden Zeichen weg?
Probiert, keine Änderung.
Anbei auch das Programm.
Die wesentlichen Codezeilen befinden sich am Ende in der while Schleife.
Hinweis. Falls jemand das laufen lässt, könnte euch die Ansteuerung des
I2C Expanders Probleme machen. Wenn er nicht vohanden ist, dann kann er
kein ACK senden und das Programm bleibt stehen. Dann halt in der
Initialisierung auskommentieren.
Dann bin ich mal gespannt, ob ihr noch was beitragen könnt.
Gruß
CL
Hallo,
mal probiert die ganzen "const char..." strings ins flash zu legen? Ich
hatte vor kurzem ein ähnliches Problem auf einem der neueren Tinys,
namentlich ein Tiny816, der dann auch wirres Zeug ausgegeben hat, obwohl
laut Compiler noch reichlich Flash und RAM verfügbar waren. Allerdings
nicht auf LCD, sondern über USART.
Auch wenns bei dir kein AVR ist, wäre es einen Versuch wert. Bei mir war
die Lösung, die Variablen mit "const __flash char..." zu deklarieren,
und dann mit den entsprechenden Funktionen mit _P am Ende aufzurufen.
Grüße,
Martin
Also ich habe das mal bei mir nachgebildet.....
Läuft nicht..... egal was ich mache, es kommt nur Blödsinn dabei rum.
An deinem Hard/Software bundle liegt es wohl nicht.... Ich nutze den
selben Compiler, den selben pic.
Seltsam. Wäre schöner gewesen, ich könnte dir helfen aber vielleicht hat
jemand anderes noch einen Denkanstoß.... Würde mich auch interessieren
Martin B. schrieb:> mal probiert die ganzen "const char..." strings ins flash zu legen
Das habe ich noch nicht gemacht, versuche ich. Weiss jemand wie die
Syntax dafür ist? Muss ich mal in der Compilerdoku nachsehen.
Martin B. schrieb:> und dann mit den entsprechenden Funktionen mit _P am Ende aufzurufen
Das verstehe ich nicht. Einfach _P daranhängen?
Woher kommt das _P?
GZ schrieb:> Wäre schöner gewesen, ich könnte dir helfen
Weisst Du wie ich das mit dem const __flash machen soll?
Mir stellt sich die Frage, wenn das im flash liegt, wie es dann per
Laufzeit geänder werden kann, wenn es nicht im RAM liegt.
CL
>> mal probiert die ganzen "const char..." strings ins flash zu legen>> Das habe ich noch nicht gemacht, versuche ich. Weiss jemand wie die> Syntax dafür ist? Muss ich mal in der Compilerdoku nachsehen.
z.B. const __flash char menu_000[] = "[Hauptmenue]";
> Das verstehe ich nicht. Einfach _P daranhängen?> Woher kommt das _P?
Ich weiß nicht, weo deine Lcd_Out() Routinen herkommen, aber villeicht
gibt es da auch Lcd_Out_P(). Das _P ist halt so eine Namensgebung, wenn
die Routinen (z.B. auch printf_P()) Daten aus dem Flash lesen.
> Mir stellt sich die Frage, wenn das im flash liegt, wie es dann per> Laufzeit geänder werden kann, wenn es nicht im RAM liegt.
Es hält dich ja keiner davon ab, die konstanten Strings aus dem Flash zu
lesen und die variablen im RAM zu haben.
Du kannst ja Lcd_Out() und Lcd_Out_P(), sofern vorhanden, auch mischen.
Grüße,
Martin