Hallo miteinander
Ich habe einmal eine kleine Frage, ob es möglich ist, die
Printf-Funktion auch für andere C-Funktionen zu nützen?
Damit man bequem zum Beispiel ein LCD ansteuern könnte, oder ein
Ringbuffer für eine Kommunikation "bedienen"...
Ich dachte, dass ich schon mal so etwas gesehen hätte:
1
void lcd_putc(char c){
2
//
3
}
4
printf(lcd_putc,"Hallo Welt: %d\n",datum);
Gibt es so etwas schon oder wie müsste das aussehen?
Besten Dank für die Hilfe
MFG
Patrick
Patrick B. schrieb:> Hallo miteinander>> Ich habe einmal eine kleine Frage, ob es möglich ist, die> Printf-Funktion auch für andere C-Funktionen zu nützen?
Möglich (beim gcc) schon.
Aber dazu muss man eine Ausgabefunktion für Einzelzeichen unter das
printf in das I/O System für den Ausgabe-Stream einschmuggeln
> Damit man bequem zum Beispiel ein LCD ansteuern könnte, oder ein> Ringbuffer für eine Kommunikation "bedienen"...>> Ich dachte, dass ich schon mal so etwas gesehen hätte:>
1
> void lcd_putc(char c){
2
> //
3
> }
4
> printf(lcd_putc,"Hallo Welt: %d\n",datum);
5
>
So höchst wahrscheinlich nicht.
Wenn da eine zusätzliches Argument beim 'printf' war, dann war das
höchst wahrscheinlich
Patrick B. schrieb:> Ich habe einmal eine kleine Frage, ob es möglich ist, die> Printf-Funktion auch für andere C-Funktionen zu nützen?
printf ist eine Funktion aus der Standard-library, und alles
wissenswerte dazu steht in der der Doku zu der von dir benutzten
Version.
Falls du zufällg AVR's progrtammierst, und das auch noch zufällig mit
avr-gcc und der avr-libc machst, dann geht das. Wie, steht in der
avr-libc-Doku zu printf.
Oliver
sprintf() schreibt aber nur in einen Puffer, der dem aufrufenden
Programm gehört. Mittels fprintf() kann man jedoch in verschiedene
Ausgabedateien bzw. -datenströme schreiben. Ursprünglich bei unixoiden
Betriebssystemen, aber mittlerweile durchaus auch allgemein
gebräuchlich, sind die Dateideskriptoren 0-2 für Standardausgabe,
Standardeingabe und Standardfehlerkanal (stdout, stdin, stderr)
reserviert. "Echte" Dateideskriptoren besitzen dann höhere Kennungen.
Um eine Ausgabeumlenkung zu realisieren, sollte man in den Quelltext der
C-Bibliothek schauen. Dann kann man schnell entscheiden, ob man z.B.
einen eigenen Handler für stderr realisiert oder zusätzliche Geräte
"erfindet".
Ggf. befinden sich in den Beschreibungen zu
Compiler/Standardbibliotheken auch schon entsprechende Hinweise oder
Anleitungen, wie eine Anpassung der Ein-/Ausgabekanäle erfolgen kann.
Patrick B. schrieb:> Hallo miteinander>> Ich habe einmal eine kleine Frage, ob es möglich ist, die> Printf-Funktion auch für andere C-Funktionen zu nützen?>> Damit man bequem zum Beispiel ein LCD ansteuern könnte, oder ein> Ringbuffer für eine Kommunikation "bedienen"...>> Ich dachte, dass ich schon mal so etwas gesehen hätte:>
1
> void lcd_putc(char c){
2
> //
3
> }
4
> printf(lcd_putc,"Hallo Welt: %d\n",datum);
5
>
>> Gibt es so etwas schon oder wie müsste das aussehen?
Falls du die avr-libc verwenden willst/kannst kann man sich nen eigenens
stdout bauen so wie beschrieben in
http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#stdio_without_malloc
Damit kommt printf allerdings nur mit dem Standardumfang. Funktionalität
wie wie zB Cursor-Positionierung, Display löschen etc. sind da nur
holprig unterzubringen.
Die Neu-Definition von der Stream-Funktion beim AVR GCC kenne ich, aber
ich habe das noch nie für eine andere Funktion gesehen.
Bei einem CCS-Compiler für PIC's in der Schule habe ich diese
möglichkeit gesehen, und auch schon angewendet.
Momentan versuche ich mich gerade an einem HI-Tech Compiler, aber leider
habe ich da nicht viel in der Doku (immerhin >450 Seiten) gesehen.
in den Header-Files habe ich nur volgendes gefunden:
1
extern char * gets(char *);
2
extern int puts(const char *);
3
extern int scanf(const char *, ...);
4
extern int sscanf(const char *, const char *, ...);
5
extern int vprintf(const char *, va_list);
6
extern int vsprintf(char *, const char *, va_list);
7
extern int vscanf(const char *, va_list ap);
8
extern int vsscanf(const char *, const char *, va_list);
9
10
#pragma printf_check(printf) const
11
#pragma printf_check(sprintf) const
12
extern int sprintf(char *, const char *, ...);
13
extern int printf(const char *, ...);
Soweit ich weiss, ist der CCS nicht immer Regelkonform.
Könnte man so eine Funktion auch selber schreiben?
MFG
Patrick
Patrick B. schrieb:> Momentan versuche ich mich gerade an einem HI-Tech Compiler, aber leider> habe ich da nicht viel in der Doku (immerhin >450 Seiten) gesehen.> in den Header-Files habe ich nur volgendes gefunden:>
1
> extern char * gets(char *);
2
> extern int puts(const char *);
3
> extern int scanf(const char *, ...);
4
> extern int sscanf(const char *, const char *, ...);
5
> extern int vprintf(const char *, va_list);
6
> extern int vsprintf(char *, const char *, va_list);
7
> extern int vscanf(const char *, va_list ap);
8
> extern int vsscanf(const char *, const char *, va_list);
9
>
10
> #pragma printf_check(printf) const
11
> #pragma printf_check(sprintf) const
12
> extern int sprintf(char *, const char *, ...);
13
> extern int printf(const char *, ...);
14
>
>> Soweit ich weiss, ist der CCS nicht immer Regelkonform.
Solche Sachen sind nie 'regelkonform', vor allen Dingen deshalb nicht,
weil der C-Standard nicht fordert, das du das machen kannst.
> Könnte man so eine Funktion auch selber schreiben?
Man könnte.
Siehe zb hier
Beitrag "AVR32 printf umleiten stdout"
Allerdings hat man dann einen fix dimensionierten Buffer drinnen, den
man da eigentlich nicht haben möchte.
Meiner Meinung nach, wird die Möglichkeit printf direkt auf einem
'Gerät' benutzen zu können, auf µC überschätzt. Das bringt viel weniger
als man sich erwartet oder auf einem Desktop System zur Verfügung hat.
Hauptsächlich deshalb, weil man meistens sowieso Spezialfunktionalität
benötigt, um zb den Cursor irgendwo hin zu schicken.
Und den Rest kann man auch mit einer guten String-Ausgabefunktion und
Funktionen zur Konvertierung von Zahlen in Strings gut und vor allen
Dingen resourcenschonend erledigen. Muss man nicht auf Speicher und
Laufzeit achten, und hat man eine gute Verwendung für die
Formatiermöglichkeiten, die einem die ...printf() Familie bietet, ist
auch sprintf eine nicht allzuschlechte Möglichkeit.
Patrick B. schrieb:> sprintf(lcd_string_buf,"\fConnected with PC\nWaiting for> command\n/data");> lcd_write(lcd_string_buf);
Wozu brauchst du ganz konkret bei dieser einen Ausgabe den sprintf?
1
lcd_write("\fConnected with PC\n"
2
"Waiting for command\n"
3
"/data");
lcd_write gibt einen String aus.
Du hast einen String.
Wenn ich direkt einen String ind die Funktion lcd_write geschrieben
habe, bekam ich eine Fehlermeldung wegen eines ungültigen Pointer-Typs.
über eine Array habe ich dann keine Fehlermeldung mehr bekommen.
Patrick B. schrieb:> Wenn ich direkt einen String ind die Funktion lcd_write geschrieben> habe, bekam ich eine Fehlermeldung wegen eines ungültigen Pointer-Typs.> über eine Array habe ich dann keine Fehlermeldung mehr bekommen.
Ich vergass. Du benutzt ja keinen gcc.
Höchst wahrscheinlich benutzt dein Compiler für konstante Texte einen
anderen Speicherort und darum musst du den Umweg gehen.