PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : wie benutzt man fdevopen()?



Felix G
09.01.2005, 14:16
Hallo!

Ich bin ja gerade dabei eine LCD-Bibliothek zu schreiben, und jetzt dachte ich mir es wäre doch ganz praktisch
wenn man da auch ganz bequem mit printf drauf zugreifen könnte.

Wenn ich das richtig verstanden habe wird stdout beim Aufruf von fdevopen() dem gewünschten "Gerät" zugewiesen,
wobei für dieses "Gerät" eine Funktion zur Ausgabe eines Zeichens existieren muss. (also ein putchar())


Aber die Deklaration alleine bringt mir irgendwie nicht so wirklich viel.
Kann mir Jemand sagen wie diese Funktion zu verwenden ist?
(bzw. wo es eine genaue Beschreibung gibt)

Felix G
09.01.2005, 19:20
Also ich habe es inzwischen selbst rausgefunden...

Man übergibt als Parameter eine putchar und/oder getchar Funktion.
Die putchar Funktion muss genau einen Parameter des Typs Char haben,
und eine 0 zurückliefern wenn das Zeichen erfolgreich geschrieben wurde.
Die getchar Funktion muss ein Zeichen lesen und als int zurückliefern.

ganz allgemein müssen die Funktionen also so aussehen:
int putchar(char c) und int getchar(void)

fdevopen liefert letztendlich einen Pointer auf eine Variable vom Typ FILE.



FILE* lcdout;

lcdout = fdevopen(LCD_putchar, NULL, 0);
Das ist alles

Man kann jetzt mit der Funktion fprintf() formatierten Text ausgeben.
(Dabei muss als erster Parameter der Ausgabestream angegeben werden)

z.B.
fprintf(lcdout, "Das ist ein Integer: %u", 1234);



Leider funktionieren standardmässig nicht alle Formatierungszeichen.
%f und %X z.B. liefern keine sinnvolle Ausgabe.

Man kann aber im Makefile einstellen welche Implementierung von printf() verwendet werden soll.
dabei ist u.a. eine vollständige Variante bei der auch %f etc. funktionieren, allerdings steigt die Codegrösse dann enorm an.

bei meinem Testprogramm von 11% bei der kleinsten Implementierung auf 21% bei der grössten
(ganz ohne Verwendung von printf werden nur 5% Flash belegt)

navyseal
06.10.2005, 18:04
hey !

hab hier ein ähnliches problem ... nur wollen wir kein lcd sondern den hyperterminal was schicken :)

aber irgendwie werd ich aus dem nicht gscheid wie man so schön sagt :)
nun die platine is über serielles kabel verbunden und möchten da gerne wie gesagt am hyperterminal was anzeigen lassen...

reicht da nicht eine uart_putchar(char c) funktion?

also

int uart_putchar(char c) // deklarat.
{
pin_led18on
uart_putchar('K')
return 0;
}

..
und die funktion über uart_putchar(c) aufrufen oder? aber irgendwie klappt das einfach nit
vllt kann uns bei dem problem wer helfen! würden uns sehr darüber freuen! danke schonmal für euer bemühen.

mfg navyseal

SprinterSB
06.10.2005, 20:06
reicht da nicht eine uart_putchar(char c) funktion?

int uart_putchar(char c) // deklarat.
{
pin_led18on;
uart_putchar('K');
return 0;
}

und die funktion über uart_putchar(c) aufrufen oder? aber irgendwie klappt das einfach nit

mfg navyseal

Vielleicht weil sich das aufhängt in einer Endlosrekursion...? ;-)

Mit printf und Konsorten ist es natürlich viiiel bequemer, aber die fressen eben mächtig Speicher und brauchen sogar ne dynamische Speicherverwaltung. Ist schon einiges an Overhead, sowohl was Flash- RAM- und Laufzeitverbrauch angeht. Auch deshalb bietet die avr-libc keine Vollimplementierung von xprintf, wie ober schon erwähnt.
Auf nem PC sind das alles peanuts, aber auf nem kleinen AVR spielt man eben in einer anderen Liga. Was bringt einem Comfort, wenn man sonst kaum mehr was tun kann oder man ewig in den xprintf Routinen rumschnarcht?

navyseal
06.10.2005, 20:18
hm ? endlosrekursion ? die aufruffunktion is ja in ner if drinn ...

oder seh nur ich das nit


bin erst seit kurzem mit winavr unterwegs also noch newbie was das hier betrifft..... aber habe hier ein demo das aber glaub ich was die serielle schnittstelle anbelangt eh alles vorbereitet ...



#include "defs.h"
#include "sio0.h"


// **************************************************
SIGNAL (SIG_UART0_TRANS)
// **************************************************
{
}

// **************************************************
SIGNAL (SIG_UART0_RECV)
// **************************************************
{
// echo
UDR0 = UDR0+1;
}
// **************************************************
void Sio0Init (void)
// **************************************************
{
// Baud Rate: 9600
// Character Size: 8-bit
// Mode: Asynchronous
// Parity: Disabled
// Stop Bit: 1-bit

// 9600 Bd
UBRR0L = 0x33;
UBRR0H = 0x00;

UCSR0A = 0x00;

// RX-Complete Interrupt Enabled
// Receiver Enabled
// Transmitter Enabled
UCSR0B = 0x98;

UCSR0C = 0x06;
}

// sio0.c EOF

und wenn ich aber nun über das putchar was ausgebe funkt das aber nit wirklich... muss man da nun noch was mit dem fdevopen machen oder wie is das ?!

achja wir arbeiten hier mit nen atmega128 falls das was hilft :)

danke für deine schnelle antwort übrigens :)

mfg

Pascal
06.10.2005, 20:27
wo ist da ne if-Abfrage?

du musst nichts mit fdevopen() machen, nur solltest du deine uart_putchar nochmal überarbeiten, weil, wie schon gesagt, funktioniert die wegen einer Endlosrekursion nicht
also, wenn du uart_putchar aufrufst, wird erst das pin_led18on; abgearbeitet, dann aber wird wieder uart_putchar aufgerufen und wieder und wieder und wieder...