Nein.
Grundsätzlich fehlt der const zwar schon. Genauso wie er hier
void usart_write_str0(char *str)
und hier
void usart_write_str0(char *str)
fehlt. Aber das ist nicht dein Problem. Sieh dir doch einfach mal an,
was denn eigentlich usart_writePC darstellt. Wenn man fertigen Code von
anderen übernimmt, ist es durchaus erlaubt (manche würden sogar sagen
'erwünscht'), wenn man sich die Dinge im Code genauer ansieht.
Was sagt dir
bzw. auch nicht uninteressant: was macht eigentlich macht usart_write_P0
mit dem Formatstring genau und vor allen Dingen WIE macht es das und was
folgt daraus.
Ich weiss es nicht,
habe früher immer zwei Variablen (Strings) zusammengefügt um diese als
Einzelnes per USART zu übertragen, bis ich das irgendwo gesehen habe
dass das so geht und ich auch in der Libary so drin habe.
Ich vermute das "usart_writePC(format, args...)" aus der stdarg.h kommt:
[c]
void MyPrintf(const char* format, ...)
{
va_list args;
char buffer[BUFSIZ];
va_start(args,format);
vsprintf (buffer, format, args );
FlushFunnyStream(buffer);
va_end(args);
}
[c]
Oder?
Und das PSTR habe ich mal gegoogelt:
PSTR bringt die Zeichenkette "Testnachricht" auch in den Programm-Flash,
das geht logischerweise nur für konstante Werte.
Aber leider hat mir das auch nicht so viel geholfen, ich muss da zu
Hause noch mal mehr recherchieren...
Aber warum das dann nicht einfach funktioniert wenn ich die Funktion nur
in einer Funktion aufrufe, weiss ich auch noch nicht...
> main.h:51: error: invalid initializer
^
Vielleicht suchst du an der falschen Stelle. Die Fehlermeldung nennt
eine Zeilennummer in einem Includefile und nicht in einer
C-Quelldatei.
> usart_writePC(String88Ein,SpeicherDimmwert);
usart_writePC() ist ein MAKRO
>> #define usart_writePC(format, args...) usart_write_P0(PSTR(format) , ## args)
und das funktioniert nur wenn das 1. Argument (format) ein konstanter
String ist, wil der zur Compilezeit mit PSTR ins Flash geschrieben wird
und zur Laufzeit in usart_write_P0() aus dem Flash gelesen wird.
Das Funktionsargument String88Ein, der von diesem Aufruf kommt
>> Licht ("88|01|01|%1i\n",u8SpeicherDimmwert[0][0]);
ist aber kein String im Flash, sondern ein String im RAM.
Abhilfe wäre folgender Aufruf:
Licht (PSTR("88|01|01|%1i\n"), u8SpeicherDimmwert[0][0]);
Mit folgender Definition von Licht():
void Licht (const char *String88Ein, uint8_t SpeicherDimmwert)
> uint8_t SpeicherDimmwert
Aufpassen, du hast da drei Varianten!
1/
>>> Licht("88|01|01|%1i\n",u8SpeicherDimmwert[0][0]);>>> => void Licht (char *String88Ein, uint8_t SpeicherDimmwert)>>> => usart_write_PC(String88Ein);
2/
>>> Licht("88|01|01|%1i\n",u8SpeicherDimmwert[0][0]);>>> => void Licht (char *String88Ein, uint8_t SpeicherDimmwert)>>> => usart_writePC(String88Ein,SpeicherDimmwert);
3/
>>> wie oben?>>> => void Licht (const char *String88Ein, int SpeicherDimmwert)>>> => usart_writePC(String88Ein,SpeicherDimmwert);
Krapao schrieb:> Aufpassen, du hast da drei Varianten!>> 1/>>>> Licht("88|01|01|%1i\n",u8SpeicherDimmwert[0][0]);>>>> => void Licht (char *String88Ein, uint8_t SpeicherDimmwert)>>>> => usart_write_PC(String88Ein);>> 2/>>>> Licht("88|01|01|%1i\n",u8SpeicherDimmwert[0][0]);>>>> => void Licht (char *String88Ein, uint8_t SpeicherDimmwert)>>>> => usart_writePC(String88Ein,SpeicherDimmwert);>> 3/>>>> wie oben?>>>> => void Licht (const char *String88Ein, int SpeicherDimmwert)>>>> => usart_writePC(String88Ein,SpeicherDimmwert);
Du kannst an dieser Stelle usart_writePC überhaupt nicht mehr benutzen!
usart_writePC wird auf jeden Fall mit dem ersten Argument einen PSTR
machen und den String Literal so ins Flash verlagern.
Der String muss aber an dieser Stelle schon im Flash sein, d.h. das PSTR
muss immer weiter rausgezogen werden. Mit jeder Funktionshhierarchie
muss das PSTR mitwandern.
Aus der Funktion 'Licht' heraus ist nur noch usart_write_P0 benutzbar,
wenn das Argument kein String-Literal ist.
Markus schrieb:> Ich vermute das "usart_writePC(format, args...)" aus der stdarg.h kommt:
Ähm.
Hast du dir dein uart.h schon mal angesehen?
Ich (und Krapao ebenfalls) haben dir das hinter usart_writePC stehende
Makro sogar herauskopiert.
> Aber warum das dann nicht einfach funktioniert wenn ich die Funktion nur> in einer Funktion aufrufe, weiss ich auch noch nicht...
Weil du, wenn du kein String-Literal hast, usart_writePC überhaupt nicht
benutzen kannst. Das ist eine Hilfs"funktion", die nur bei
String-Literalen (als direkt angegebenem String) benutzbar ist. Den Fall
hast du aber nicht. Also kannst du usart_writePC auch nicht benutzen.
Und jetzt kannst du dasselbe Spielchen machen, das auch dein UART Code
macht. Du kannst dir ein Makro definieren, welches dir das nervtötende
PSTR einsetzt, so dass du es nicht vergessen kannst. Sozusagen die
Komfortversion, so wie usart_writePC die Komfortversion von
usart_write_P0 ist.
Und es passiert wieder das richtige:
Das PSTR (welches durch das Makro reinkommt), sorgt dafür, dass das
String-Literal im Flash bleibt und ein entsprechender Pointer durch die
Funktino Licht durchgeschleust wird, der dann letztendes in der Funktion
usart_write_P0 ankommt. Denn usart_write_P0 braucht einen Flash Pointer,
weil es sich den Formatstring mittels pgm_read_byte (das ist die Antwort
auf meine 2.te Frage von weiter oben) holt. Und dafür muss der String
nun mal im Flash sein. Ins Flash kannst du den String aber nur bei
seiner 'Entstehung' verschieben. Also muss das PSTR mit dem
String-Literal mitwandern. Dort wo das String-Literal ist, muss auch das
PSTR sein.