Forum: Compiler & IDEs Anweisungsverhalten von printf() unter WinAVR


von Benjamin (Gast)


Lesenswert?

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

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von Günter R. (galileo14)


Lesenswert?

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

von Thorsten (Gast)


Lesenswert?

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.

von Thorsten (Gast)


Lesenswert?

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.

von Werner B. (Gast)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Josef K. (zumlin)


Lesenswert?

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. ;)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.