Es geht um die Anbindung eines LCD mit 4x27 Zeichen und 2 Controllern
der HD44780-Familie.
Ich habe keine Idee mehr, warum diese Warnung erscheint, wenn ich die
Funktion mit
Deklariere ich diese nicht, gibt es keine Warnung.
Das fertige Hex (mit demo_lcd_test.sh uebersetzt) tut in beiden Faellen,
was es soll.
Hat jemand von den C-Gurus eine Erklaerung?
Danke Matthias
Matthias S. schrieb:> expected ‘char *’ but argument is of type ‘__flash const __flash char> (*)[12]’
Dein Compiler schreibt dir doch alles. Wo ist das Problem?
Was soll man da viel erklären? Das Problem gibt der Compiler ja aus.
Der ursprüngliche Autor hat vermutlich die Warnungen entweder abgestellt
oder ignoriert.
@ df2au
Ich versteh gerade nicht, worauf sich das "Nein" bezieht.
Im Democode wird ja auch der __flash qualifier verwendet.
Aber noch etwas:
Es wird mit "&titel_0" ein Zeiger auf ein Array mit bestimmter Länge
übergeben. Die Funktion will aber nicht so etwas, sondern einen Zeiger
auf char.
Theor schrieb:> Es wird mit "&titel_0" ein Zeiger auf ein Array mit bestimmter Länge> übergeben. Die Funktion will aber nicht so etwas, sondern einen Zeiger> auf char.
Meine Absicht war, einen Zeiger auf den Anfang des 0-terminierten
Strings zu uebergeben. Das klappt ja auch, der 0-terminierte String wird
bis vor die "\0" auf das Display geschrieben.
Was mir unerklaerlich ist: einfaches Auskommentieren der Zeile:
1
voidlcd_write_string_p(uint8_t,uint8_t,char*x);
in demo_lcd.h reicht, um alle Warnungen verschwinden zu lassen, obwohl
da m.M.n. exakt dasselbe ablaeuft, warum?
Matthias
Matthias S. schrieb:> Theor schrieb:>> Es wird mit "&titel_0" ein Zeiger auf ein Array mit bestimmter Länge>> übergeben. Die Funktion will aber nicht so etwas, sondern einen Zeiger>> auf char.>> Meine Absicht war, einen Zeiger auf den Anfang des 0-terminierten> Strings zu uebergeben. Das klappt ja auch, der 0-terminierte String wird> bis vor die "\0" auf das Display geschrieben.>> Was mir unerklaerlich ist: einfaches Auskommentieren der Zeile:>
1
voidlcd_write_string_p(uint8_t,uint8_t,char*x);
> in demo_lcd.h reicht, um alle Warnungen verschwinden zu lassen, obwohl> da m.M.n. exakt dasselbe ablaeuft, warum?>> Matthias
Verschwinden die Warnungen oder funktioniert es auch?
Das Problem ist: ein char* zeigt ins RAM, ein __flash char* zeigt ins
Flash. Bein AVRs braucht man zum Zugriff unterschiedliche Befehle. Und
wenn der Compiler keine Deklaration einer Funktion hat, dann glaubt er
dem Aufrufer.
Carl D. schrieb:> Das Problem ist: ein char* zeigt ins RAM, ein __flash char* zeigt ins> Flash.
In demo-lcd wird ein char * als Übergabe Parameter vereinbart.
void lcd_write_string_p(uint8_t, uint8_t, char *x);
In der Schreibroutine wird dann per pgm_read auf das Flash zugegriffen.
Damit wird das Pointer Ziel automatisch korrigiert.
void lcd_write_string_p(uint8_t line, uint8_t column, const char *s){
[...]
while(c = pgm_read_byte(s)){s++; lcd_write_byte_top(c);};
Hier würde der Compiler maulen, wenn das .h File auch im .c mit
eingebunden würde. Denn die Definition aus .h stimmt nicht mit der
Realisierug im .c überein (char * <-> const char *).
in demo-lcd-test kommt dann aber die Definition
const __flash char titel_0[] = "Time \0";
wobei __flash automatisch const ist.
Als Abhilfe könnte man z.B. durchgängig __flash verwenden, muss dann
aber die pgm_read weglassen. Das macht der Compiler selbst richtig. Also
void lcd_write_string_p(uint8_t, uint8_t, __flash char *x);
void lcd_write_string_p(uint8_t line, uint8_t column, __flash char *s){
while(c = *s)){s++; lcd_write_byte_top(c);};
Fazit: Der Compiler ist schlauer, als man denkt :-)
Georg G. schrieb:> Als Abhilfe könnte man z.B. durchgängig __flash verwenden, muss dann> aber die pgm_read weglassen. Das macht der Compiler selbst richtig. Also> void lcd_write_string_p(uint8_t, uint8_t, __flash char *x);> void lcd_write_string_p(uint8_t line, uint8_t column, __flash char *s){> while(c = *s)){s++; lcd_write_byte_top(c);};>
Ja, das klappt.
> Fazit: Der Compiler ist schlauer, als man denkt :-)
Sowieso.
Allerdings war der Schluessel das, was ich letztes Jahr schon selbst
geschrieben hatte:
Matthias S. schrieb:> Meine Absicht war, einen Zeiger auf den Anfang des 0-terminierten> Strings zu uebergeben.
Also so:
1
lcd_write_string_p(0,0,&titel_0[0]);
Das zeigt auf das erste Byte und nicht falsch wie hier:
1
lcd_write_string_p(0,0,&titel_0);
Das zeigte auf den String.
Schoenes neues Jahr noch und Vielen Dank.
Matthias
Matthias S. schrieb:> Also so:lcd_write_string_p(0,0,&titel_0[0]);Das zeigt auf das erste Byte> und nicht falsch wie hier:lcd_write_string_p(0,0,&titel_0);
Das wäre kürzer und macht das Richtige.
lcd_write_string_p(0,0,titel_0);
Matthias S. schrieb:>> Fazit: Der Compiler ist schlauer, als man denkt :-)> Sowieso.
Sowieso? Der einzige Fehler, den ich hier sehe besteht darin, daß du
viel zu wenig von der Hardware kennst, insbesondere nicht den
Unterschied zwischen Harvard und v.Neumann-Architekturen.
Zum Programieren von µC gehört eben zuvörderst eine ordentliche Kenntnis
der Hardware. Nicht alles, was in gewöhnlichem C syntaktisch richtig
ist, darf man hier als gegeben ansehen. Und wenn dann der Compiler einem
im Klartext sagt, was man falsch gemacht hat, dann sollte man das auch
sorgfältig lesen und verstehen.
Du bist hier nicht der Einzige, dem das passiert. Viele Leute hier
glauben, wenn sie nur eine tolle C-Quelle von irgendwo her haben, sich
nicht weiter um die HW scheren zu müssen. Stattdessen wird dann mit
neumodischen Tinnef-Bezeichnern herumgefummelt und man glaubt, damit
über alle erdenklichen Systeme hinweg portabel zu sein. Ist aber nicht
so.
W.S.
W.S. schrieb:> daß du> viel zu wenig von der Hardware kennst, insbesondere nicht den> Unterschied zwischen Harvard und v.Neumann-Architekturen.
Nein. Auf Hardwareebene weiss ich sehr genau, was da passiert und wie
das laufen soll.
Wie ich das dem C-Compiler so beibringe, dass der nicht meckert, ist
eine andere Sache und genau um die ging es hier.
W.S. schrieb:> Nicht alles, was in gewöhnlichem C syntaktisch richtig> ist, darf man hier als gegeben ansehen.
Nochmal, es ging darum, dass der Compiler eben nicht der Meinung war,
das sei syntaktisch richtig - obwohl er das Richtige daraus kompiliert
hat, es hat ja trotz der Warnungen funktioniert, wie ich schon im
Eingangspost geschrieben hatte.
Georg G. schrieb:> Das wäre kürzer und macht das Richtige.> lcd_write_string_p(0,0,titel_0);
Ja, das klappt auch.
Matthias
Edit: Typos.
Matthias S. schrieb:> der Compiler eben nicht der Meinung war, das sei syntaktisch richtig
Die Warnung sagt eher: "Bist du dir sicher, dass du das so haben willst?
Über diese Konstruktion kann man durchaus geteilter Meinung sein." Die
Syntaxprüfung in C ist meist recht lasch, man kann sich selbst von
hinten erschiessen. Gute Compiler geben vorher wenigstens eine Warnung.
Viele Programmierer schalten die Warnungen auf niedrige Level oder ganz
ab, weil sie nerven. So gesehen, warst du auf der richtigen Seite.