Hallo, WinAVR - 20050214 gcc - 3.4.5 avrlibc - 1.4.2 stdio.h ist included Beispiel aus AVR-gcc-Tutorial zum Senden von Zeichenketten Ich bekommen beim kompilieren das Warning: main.c:54: warning: passing arg 1 of `fdevopen' from incompatible pointer type die Zeile lautet fdevopen(uart_putc,NULL); Wenn ich - wie im Tutorial-Beispiel - eintrage: fdevopen(uart_putc,NULL,0); erhalte ich: main.c:54: warning: passing arg 1 of `fdevopen' from incompatible pointer type main.c:54: error: too many arguments to function `fdevopen' Was mache ich falsch bzw. wie mache ich es richtig? Die erste Variante funktioniert im übrigen... Gruß, Axel
In die Doku schauen. Der Prototype von fdevopen sieht so aus: FILE* fdevopen ( int(* put)(char), int(* get)(void), int opts __attribute__((unused)) ) Argument 1 sollte also sein: Ein Pointer auf eine Funktion. Diese Funktion nimmt einen char und liefert einen int zurueck. Wie sieht Deine Funktion (aus dem Tutorial) aus: int uart_putc(unsigned char c) { while(!(USR & (1 << UDRE))); /* warte, bis UDR bereit */ UDR = c; /* sende Zeichen */ return 0; } Nun. Die Funktion liefert einen int wie gefordert, nimmt aber einen unsigned char und keinen char. Damit hat diese Funktion eine andere Signatur als fdevopen sie haben moechte.
Karl Heinz, du hast den Prototypen von avr-libc <= 1.2.x gezeigt, Axel benutzt offensichtlich eine 1.4.x. Axel, das wichtigste hast du vergessen uns zu sagen: den Prototypen (oder die Implementierung) deines uart_putc(). Ich vermute mal, du hast den zweiten Parameter (FILE *) vergessen, der in der avr-libc 1.4 neu hinzugekommen ist. Guck mal ins stdiodemo. Der Sinn dieses Parameters ist, dass man mittels fdev_set_udata() an den Stream user data anhängen kann und innerhalb von uart_putc() mittels fdev_get_udata() über diese verfügen kann. Damit kann man einerseits Dinge wie einen Gerätestatus über mehrere Aufrufe pro Stream abspeichern, andererseits kann man ein und dieselbe backend-Funktion (also uart_putc() in deinem Falle) für mehr als ein Gerät (z. B. zwei verschiedene UARTs) benutzen, indem man sie anhand der user data unterscheidbar macht. Wenn du diese Funktionalität nicht brauchst, deklarierst du den zweiten Parameter einfach nur als Dummy, ohne ihn zu benutzen.
> Karl Heinz, du hast den Prototypen von avr-libc <= 1.2.x gezeigt, > Axel benutzt offensichtlich eine 1.4.x. Danke fuer den Hinweis.
Hm, ich bin wohl noch viel zu weit weg mit meinen Kenntnissen, um das so richtig zu verstehen... so sieht das bei mir aus (das sollte genau dem Beispiel aus dem gcc-Tutorial entsprechen), damit erfolgt auch eine Ausgabe auf meinem ATMega32, nur gibt es halt das entsprechende oben beschrieben fdevopen-Warning: void USART_Init( void ) { UCSRB |= (1<<TXEN);//UART TX einschalten UCSRC |= (1<<URSEL)|(3<<UCSZ0);//Asynchron 8N1 UBRRH=(uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_CPU)>>8); UBRRL=(uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F_CPU); } int uart_putc(unsigned char c) { while (!(UCSRA & (1<<UDRE))); /* warten bis Senden moeglich */ UDR = c; /* sende Zeichen */ return 0; } void uart_puts (char *s) { while (*s) { /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */ uart_putc(*s); s++; } } int main(void) { USART_Init(); fdevopen(uart_putc,NULL); printf("%s: stdout erfolgreich auf UART umgeleitet\n", _FUNCTION_); sei(); return 0; } Was muss ich in die Klammern von fdevopen schreiben, damit kein warning mehr kommt? Gruß, Axel
OK. Du musst lernen wie man sowas loest. Der Compiler meckert, weil der Prototyp von fdevopen etwas andere Parameter vorschreibt also Du tatsaechlich verwendet hast. Das ist noch kein Beinbruch und das kriegt man raus indem man ganz einfach mal einen Blick auf den Prototypen wirft. Den wiederum sieht man entweder in der Doku, oder aber was meist besser ist direkt im Code. Irgendwiw muss der Compiler ja den Prototypen sehen und da Du ihn nicht selbst geschrieben hast, kann er nur ueber ein #include hineingekommen sein. Also geht man mal alle #include durch und ueberlegt in welchen dieser Files der Progtrammierer der Library sinnvollerweise den Prototyp hineingegeben haben wird. Im vorliegenden Fall ist 'stdio.h' ein heisser Kandidat. Ich hab bei mir am Rechner eine etwas aeltere Version davon (die findet sich bei mir unter c:\winavr\avr\includes) und bei mir lautet der Prototyp extern FILE *fdevopen(int (*__put)(char), int (*__get)(void), int __opts); Aber wie gesagt, ich hab eine etwas ältere Version. Deine sieht anders aus, wie Jörg weiter oben schon ausgefuehrt hat. Aus den Ausfuehrungen von Jörg schliesse ich folgendes: * fdevopen uebergibt man ja 2 Funktionspointer * diese Funktionspointer sind Zeiger auf Funktionen, die jeweils aufgerufen werden, wenn ein Zeichen entweder ausgegeben oder eingelesen werden soll. * damit das aber funktioniert, muessen Deine Funktionen so aussehen wie fdevopen sich das so vorstellt. Insbesondere muessen die Argumente in Anzahl und Type uebereinstimmen. * der erste Funktionszeiger im Aufruf von fdevopen ist ein Zeiger auf die Ausgabefunktion. In meiner Version ist das eine Funktion die einen char annimmt und einen int zurueckliefert. Jetzt hat Jörg aber gesagt, dass er diese Funktion mit einem zusaetzlichen Parameter, einem File-Pointer ausgestattet hat. d.h. Der Protoyp von fdevopen wird wahrscheinlich so aussehen (aber pruef das bitte nach!) extern FILE *fdevopen(int (*__put)(char, FILE*), int (*__get)(FILE*), int __opts); * Daraus folgt: damit Deine uart_putc Funktion dazu kompatibel ist, muss sie daher der Signatur int (*put)(char, FILE*) genuegen. int uart_putc( unsigned char c, FILE* dummy ) { .... } Dieser zusätzliche Parameter 'dummy' ist wohl der Stream, auf dem die Ausgabe tatsaechlich erfolgen soll. Da Du weist, dass die Ausgabe auf den UART gehen soll, ist sein Inhalt fuer Dich wahrscheinlich uninteressant und daher hab ich das auch 'dummy' genannt. Das muss aber nicht so sein. Warum soll eine einzige uart_putc Funktion nicht die Ausgabe auf verschiedene Geräte regeln können. Dann braucht man den zusätzlichen Parameter um die unterschiedlichen Ausgabeanfoerderungen zum richtigen Gerät zuordnen zu können. Disclaimer: Wie bereits ausgefuehrt verwende ich noch eine ältere Version der Library. Alles hier geschriebene hab ich aus Jörgs Info von oben abgeleitet bzw. 'geraten'. Ich denke aber nicht, daß ich alzuweit daneben liege. Alles beginnt damit, dass Du mal den Prototypen von fdevopen() in stdio.h ueberpreufts, wie der tatsächlich aussieht.
Uff, danke erstmal. ja, ich muss (und will) lernen, wie man sowas löst... Der Berg ist aber noch ganz schön hoch. Deine Mutmaßungen bzgl. fdevopen sind alle richtig; eigentlich hatte aber schon Dein erster Hinweis gereicht -> aus unsigned char musste char werden. -> Jedoch ist dann auch das Beispiel im avr-gcc-Tutorial falsch, dort steht 'int uart_putc(unsigned char c)... Jetzt läuft es zumindest 'warning'-frei durch; auf zum nächsten Schritt, die nächste Frage kommt bald. Gruß, Axel
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.