Hallo Zusammen,
ich lese immer in irgendwelchen Büchern von der Verwendeung des
"printf();" Befehls. Aber ich kapiere die Funktionsweise nicht so
wirklich... :o(
Der eine verwendet die Funktion zur Ausgabe auf der seriellen
Schnittstelle, der ander schiebt damit Daten zum LCD, usw. . Ich meine
ich habe den printf- Befehl schon zur Ausgabe von Daten auf der
seriellen Schnittstelle von einem 8051 Controller verwendet, aber wie
kann ich dem Compiler sagen das er den Befehl jetzt garnicht für diese
Anwendung nutzen soll, sondern Daten auf dem LCD ausgeben soll... Ich
schnalle das nicht!!
Z.B. habe ich mir die Bücher von Michael Baldischweiler für C51 von Keil
gekauft und gelesen. Dort verwendet er die Funktion erst zur Ausgabe auf
der seriellen Schnittstelle und nachher spricht er mit der Funktion das
LCD an!! Er hat aber nichts davon geschrieben, dass er diese angepasst
hat. Geht das, und wie? Ich kapiere das nicht.... bin blöd ;o)
Gruß
Benjamin
printf benutzt zur Ausgabe eine vom Anwender zur Verfügung zu stellende
Funktion. Wie die heißt, ist von Compiler zu Compiler unterschiedlich;
bei manchen Systemen wird auch eine Default-Implementierung
mitgeliefert, die beipielsweise die serielle Schnittstelle anspricht.
Diese Funktion wird für jedes auszugebende Zeichen einmal aufgerufen und
könnte beispielsweise putc oder putchar heißen.
Näheres steht in der Dokumentation des verwendeten Compilers.
Du verwendest besser die "f"-Funktionen wie "fprintf", "fputs" etc; dazu
benötigst Du noch z.B. "fdev_setup_stream", um die Devices zu
spezifizieren. Du kannst damit mehrere "File-Control-Blocks" definieren.
Dann kannst Du ganz genau steuern, wohin welche Deiner Ausgaben gehen
sollen; das mache ich schon seit langer Zeit so. Im avr-libc-Manual ist
beschrieben, wie das geht.
Günter
Funktionen wie printf, puts, scanf etc. verwenden als low-level alle
putch() oder getch(), je nach Datenrichtung.
Du musst diese Funktionen (meistens putch() für printf) überschreiben.
Wie das geht, kann man den jeweiligen Compiler Manuals entnehmen.
Achso, Du suchst speziell nach WinAVR, also GCC:
int uart_putchar(char c, FILE *stream);
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
_FDEV_SETUP_WRITE);
int uart_putchar(char c, FILE *stream)
{
while( !( UCSR0A & (1<<UDRE0)));
UDR0 = c;
return 1;
}
Und in der Initialisierung einfach noch:
stdout = &mystdout; // Umlenkung!!
Somit wird die obige uart_putchar() als stdout verwendet, also von
printf etc.
Die Erklärungen auf das Wesentliche geschrumpft:
Funktional kannst du dir printf so vorstellen...
Pseudocode:
int printf(char *fmt, ...)
{
return (fprintf(stdout, fmt, ...));
}
Und stdout kannst du beliebig umdefinieren/umprogrammieren.
Thorsten wrote:
> Du musst diese Funktionen (meistens putch() für printf)> überschreiben. Wie das geht, kann man den jeweiligen Compiler> Manuals entnehmen.
Wenn du's nicht genau weißt, dann schreibe bitte lieber nichts dazu.
avr-libc kenn kein putch() oder getch().
Der Weg, wie man bei avr-libc die low-level-IO-Funktionen an einen
Stream bindet, steht in der Doku und wurde ja dann hier auch noch
explizit erwähnt.
Man kann auf diese Weise beliebig viele Streams haben, die auf
verschiedene Geräte zugreifen können (UART, LCD, I²C, ...). Man kann
bei Bedarf auf stdout während der Laufzeit zwischen verschiedenen
Streams hin- und herschwenken. Damit geht printf() dann auf
unterschiedliche Geräte, wobei man mit fprintf() jedes Einzelne immer
explizit ansprechen kann.
Ich habe das gleiche Problem wie oben beschrieben nur bei mir ist die
gcc-avr 4.1.0 (System: Ubuntu Edgy) installiert bzw mit der wird
compiliert.
-------- begin --------
avr-gcc (GCC) 4.1.0
[...]
Ich habe aber das gcc-avr packet bereits installiert und es scheint auch
auf dem neuesten Stand zu sein. Warum habe ich dann nur die 4.1.0?
Linux ist leider immer noch zu sehr ein spanisches Dorf für mich. ;)
Eine eigene Frage?
Dieser Thread ist über 20 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.