Guten Abend! ihr seid wieder die letzte hoffnung... //vorab: ich nutze avrstudio4, Atega32, winavr ich möchte gerne printf für eine formatierte Ausgabe über die serielle Schnittstelle nutzen. die Ausgabe über meine usart_putc funktioniert! wenn ich mit printf versuche zu compilieren (siehe Datei: Atmelboard1.c) bekomme ich folgende Warnungen: ../Atmelboard1.c:19: warning: implicit declaration of function 'printf' ../Atmelboard1.c:19: warning: incompatible implicit declaration of built-in function 'printf' Wenn ich diese ignoriere, wird im Terminalprogram der printf-befehl NICHT ausgegeben! Ich las natürlich u.a. hier im Tutorial, dass ich diese Standartausgabe (stdout) umleiten muss und eine printf-funktion declarieren muss, welche irgendwie auf die usart_putc zurückgreift. also 1) versteh ich diese geamte prozedur nicht und 2) sieht die usart_putc im bsp anders aus als meine! bei meiner wird nur eine Variable erwartet/verarbeitet //___Ein Byte senden void usart_putc(unsigned char byte) { //___warten auf Datenregister "frei" while(bit_is_clear(UCSRA,UDRE)); UDR=byte; } im tutorial-beispiel: int uart_putchar( char c, FILE *stream ) { if( c == '\n' ) uart_putchar( '\r', stream ); loop_until_bit_is_set( UCSRA, UDRE ); UDR = c; return 0; } meine putc kann ich ja offensichtlich nicht verwenden... würd diese usart_putchar meine usart_putc denn ersetzen? ich hätte auch nocht eine usart_puts im angebot: //___String senden auf USART - Ohne Autolinefeed void usart_puts(char *s) { while(*s!=0) { usart_putc(*s); s++; } } diese sieht der Usart_putchar ausm tutorial ja schon mal ähnlicher. und was mir im tutorial noch auffällt ist: in dem sprintf/printf-kapitel wird sprintf bzw printf einfach verwendet. Ich seh nirgens die declaration der Funktionen! Und was ist überhaupt der unterschied zwischen den beiden. Sorry für diese Fragenflut aber ich hab jetzt so viel Tabs und seiten aufgehabt und wurd einfach aus keinem code richtig schlau. wäre happy wenn mir einer sagen kann was bei dem angehängten Programmcode fehlt damit printf genutzt werden kann!! Danke euch im voraus und ich bau auf euch :))
Christian Peskov schrieb: > ../Atmelboard1.c:19: warning: implicit declaration of function 'printf' > ../Atmelboard1.c:19: warning: incompatible implicit declaration of > built-in function 'printf' Kann es sein, daß du
1 | #include stdio.h
|
vergessen hast? printf ist ja einfach nur eine Library-Funktion vom C-Compiler, die relativ vom verwendeten µC unabhängig sein sollte. Auf der untersten Ebene greift dann printf wieder auf die Ausgabe eines einzelnen Zeichens zu, nennt sich oft z.B. putchar. Dort geht es dann an die Hardware, nämlich die entsprechenden Register eines konkreten µC. Irgendwo in der Doku zum Compiler muß es stehen, wie die Funktion genau heißen muß, worauf printf zugreift. Ob putchar, putc, uart_putchar, wie auch immer. In der Nacht ist wohl außer mir kaum noch jemand auf. Aber das sind mal wenigstens meine Anmerkungen dazu. Ich habe zwar den SDCC für 8051, nicht einen Atmega32, aber könnte noch mal nachschauen, wie es dort ist.
Die Funktion printf ist in stdio.h deklariert. Wenn Du stdio.h weder im Studio unter header-files noch als Include im Code einbindest, müßtest Du Deine eigene printf verwenden dürfen. Nur mußt Du einen eigenen Funktionsrumpf erstellen, der dann das macht, was Du willst. warning: implicit declaration of function 'printf' -> bedeutet, dass an der Stelle im Code eine Funktion aufgerufen werden soll, zu der kein Prototyp besteht. Entweder erstellst Du eine Funkton printf vor deinem main() oder Du erstellst einen Prototyp, der anzeigt, dass eine Funktions mit dieser Syntax noch folgt. Der Funktionskörper liegt dann hinter der Main-Fkt. Was spräche dagegen, eine uart_prinft zu programmieren? Dann wäre der Namenskonflikt hinfällig.
hey.. danke aber in der selben nacht hab ich GARKEINE antwort mehr erwartet, sonst wäre ich bestimmt noch wach geblieben ;) also... ja die stdio.h hab ich in der tat nicht included.... da ich sie vor der printf anweisung schlicht noch nicht brauchte! also wenn ich die include, kann ich direkt mit printf loslegen?^^ das wäre natürlich hammer! oder muss ich dann, doch noch so sachen wie standartstream umleiten und weiteren quark machen? kann es leider nicht jetzt ausprobieren...
Hallo, Christian Peskov schrieb: > oder muss ich dann, doch noch so sachen wie standartstream umleiten und > weiteren quark machen? ganz klar einbinden! Zum Beispiel: static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); stdout = &mystdout; int uart_putchar(char c, FILE *stream) // // bindet printf() ein { uart_putc(c); //UART return 0; } Gruß XMEGA
oki doki... aber warum verstehe ich das nicht? >>static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, >>_FDEV_SETUP_WRITE); definiert ein staitsche FILe names mystdout, welches mittels der Funktion FDEV_Setup_... befüllt wird??? >>stdout = &mystdout; stdout, muss die von mir definiert werden??? und warum das "&" vor mystdout??? >>int uart_putchar(char c, FILE *stream) // // bindet printf() ein >>{ >> uart_putc(c); //UART >> return 0; >>} warum bindet diese Funktion "uart_putchar" "printf" ein????? die uart_putc in der uart_putchar... kann ich da meine normale usart_putc verwenden (siehe threaderöffnung) dankeöö
Also hinbekommen habe ich das ganze nun... habs einfach stupide von
XMEGA übernommen.
getestet und funktioniert! DANKE!
dann habe ich das ganze in eine headerdateigesteckt.
trotzdem frag ich mich, warum ich
>>stdout = &mystdout;
nicht mit in die header schreiben kann, sonder dieses in der main stehen
muss?!
den rest könnt ich einfach so hinnehmen ;)
wiedereinmal besten dank!
"gefällt mir"
Christian Peskov schrieb: >>>static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, >>>_FDEV_SETUP_WRITE); > > definiert ein staitsche FILe names mystdout, welches mittels der > Funktion FDEV_Setup_... befüllt wird??? FDEV_SETUP_STREAM ist ein Makro und keine Funktion. FILE ist eine Struktur, die durch FDEV_SETUP_STREAM befüllt wird. >>>stdout = &mystdout; > > stdout, muss die von mir definiert werden??? Nein, das passiert bereits in stdio.h. > und warum das "&" vor mystdout??? Weil Du einen Zeiger auf mystdout nach stdout schreiben willst. > warum bindet diese Funktion "uart_putchar" "printf" ein????? Tut sie nicht. printf verwendet stdout. Und stdout ist nun deine Ausgabefunktion. > die uart_putc in der uart_putchar... kann ich da meine normale > usart_putc verwenden (siehe threaderöffnung) Die Funktionn auf die stdout zeigt, muss die Argumente char c und FILE *stream haben, wenn Deine das auch hat, ja, sonst nein.
Christian Peskov schrieb: > trotzdem frag ich mich, warum ich >>>stdout = &mystdout; > > nicht mit in die header schreiben kann, sonder dieses in der main stehen > muss?! Weil es eine Zuweisung zur Laufzeit ist.
aha danke!!
kann ich das
>>>stdout = &mystdout;
denn irgendwie aus der main bekommen?
vllt durch ein .c-inlcude?
also statt headerfile ne sourcedatei einbinden?
mich würd mal fragen woher ihr das alle wisst?
in meinem e studium war microcontroller nur eine randerscheinung.
habt ihr alle informatik studiert oder einfach nur erfahrung im hobby?
mfg
Christian Peskov schrieb: > aha danke!! > > kann ich das >>>>stdout = &mystdout; > denn irgendwie aus der main bekommen? Du kannst es in einer Funktion verstecken. Aber letzten Endes ändert es nichts daran, dass du die Operation an sich erst zur Laufzeit machen kannst. Die Funktion kannst du dann natürlich in eine andere C-Datei stecken, so wie man eben Funktionen in mehreren COmpilation Units aufteilt. > mich würd mal fragen woher ihr das alle wisst? Doku lesen (ja, das ist alles dokumentiert) Üben, üben, üben. Lesen. Über die Dinge nachdenken. Kernighan&Ritchie lesen. Grübeln. Üben, üben. Lesen. Ausprobieren. Fehlschläge verkraften. Daraus Schlüsse ziehen. üben, üben, üben ...
ob hier noch mal wer nachschaut? ohr wart alle so weiße ;) ich habe printf mittlerweile fleißig verwendet und auch schon dafür lehrgeld bezahlt! ^^ aber mich interessiert zu diesem thema noch mal folgendes: 1) wenn ich mir beispielcode von anderen oder von büchern anschaue, sehe ich nie dieses "stdout= &mystdout;" 2) warum muss ich überhaupt solche sachen wie usart_putc(..) und co declarien/definieren. wenn die stdio.h doch die prototypen alle hat. oder anders. warum sind in den libs NUR die prototypen und nicht die nutzbaren funktionen?? 3) das gehört jetzt nur halb zu diesem thema! Ich habe probleme mit der dateneingabe über die tastatur! scanf() und gets() oder aber auch nur getc()/getchar() funktionieren nicht. das prgramm läuft durch als wäre keiner dieser anweisung im code vorhanden! es wird nicht auf eine eingabe gewartet und es wird auch keine übernommen! Daher hab ich mich gefragt ob ich vllt etwas analoges zu printf() und stdout=&mystdout machen muss? das wisst ihr doch mit links ;) Frage 1 und 2) ist rein interessehalber. antwort zu frage 3) würde mir sehr helfen! :) bis dahin danke
Die Antwort auf deine ersten Fragen lautet im wesentlichen: Weil du es hier mit einem µC zu tun hast. Hier ist das I/O System nicht per Default so initialisiert, dass die Ausgabe auf einem Monitor erscheint. Die meisten µC haben noch nicht einmal einen Monitor. Programmierst du hingegen auf einem PC bzw. auf einem Computer ab Desktopsystem aufwärst, dann ist das I/O System schon so konfiguriert, dass alle Ausgaben auf stdout am Monitor landet. Das ist aber der Normalfall und daher wird das in den Büchern nicht extra erwähnt. Erst dann, wenn man von diesem Normalfall abweichen muss, wie hier auf einem AVR, muss man spezielle Vorkerhungen treffen und bestimmte Dinge tun, die auf einem Desktop System nicht notwendig sind. Wie zb das I/O System mit der UART verbinden. Denn woher soll denn stdout wissen, ob die Ausgabe jetzt auf die UART oder dann vielleicht doch aufs LCD gehen soll? > warum muss ich überhaupt solche sachen wie usart_putc(..) und co declarien/definieren. Weil das eben keine Standardfunktionen sind. Daher musst du die schreiben. Als Faustregel kannst du dir merken: Alles was irgendwie mit spezieller Hardware zu tun hat, kann niemals Standard-C sein. D.h. da gibt es immer spezielle massgeschneiderte Lösungen, die nur auf deinem Compiler, deiner Hardware funktionieren. Nichts davon ist standadisiert.
danke für diesen überblick! 1) jedoch nutze ich ja das avrstudio und einen atmel Programmer. dem avrstudio ist bewusst welcher controller für das projekt verwendet wird. so finde ich, dass diese dinge wie usart fertig zur nutzung bereit liegen können. schließlich ändern sich bei den atmelcontrollern doch nur(wenn überhaupt) die registeradressen und oder portadressen/-pins?! und das wird ja für jeden unterstützten controller per #define vom avrstudio ausgemerzt?! oder sehe ich das falsch? 2) das mit dem standartout kann ich nachvollziehen, wobei ich das mit dem standartout nicht kapier! usart ist klar, die befehle landen an den usartpins. printf hat keine eigene hardware?! deshalb ist der stdout was? für die serielle ausgabe zum terminal muss ich des stdout ja ändern, was ist dann das default von stdout? ist der stdout explizit für printf-frunktionen oder greifen da noch andere sauchen drauf? 3) wie siehts mit scanf aus?? mfg peter
Christian Peskov schrieb: > danke für diesen überblick! > > 1) > jedoch nutze ich ja das avrstudio und einen atmel Programmer. dem > avrstudio ist bewusst welcher controller für das projekt verwendet wird. > so finde ich, dass diese dinge wie usart fertig zur nutzung bereit > liegen können. Die Meinung darfst du haben. Das ändert aber nichts an den Tatsachen. > schließlich ändern sich bei den atmelcontrollern doch nur(wenn > überhaupt) die registeradressen und oder portadressen/-pins?! und das > wird ja für jeden unterstützten controller per #define vom avrstudio > ausgemerzt?! > oder sehe ich das falsch? Ja. Daß die Register mehr oder weniger gleich sind, ist ja nur die halbe Miete. Viele AVR haben in ihrer Schaltung keine U(S)ART angeschlossen, manche haben zwei, andere wollen gar nicht auf einer seriellen ausgeben, sondern auf einem LCD, das ganz anders angesteuert wird (4 oder 8 Datenpin für HD44780, oder T6963, oder über I2C...). Wie soll da etwas vordefiniert sein? > > 2) > das mit dem standartout kann ich nachvollziehen, wobei ich das mit dem > standartout nicht kapier! Das wiederum kapier ich nicht. Wo ist der Unterschied zwischen standartout und standartout? (Falsch geschrieben ist beides :-) > > usart ist klar, die befehle landen an den usartpins. > printf hat keine eigene hardware?! deshalb ist der stdout was? Eben deshalb genau das, was du als stdout definierst. > für die serielle ausgabe zum terminal muss ich des stdout ja ändern, was > ist dann das default von stdout? Nichts. Nirwana. Njente. Null. > ist der stdout explizit für printf-frunktionen oder greifen da noch > andere sauchen drauf? puts(), putchar() > > 3) > wie siehts mit scanf aus?? Genauso. Du definierst eine Funktion, die Zeichen holt, und verknüpfst sie mit stdin. Siehe http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#gaf41f158c022cbb6203ccd87d27301226
PS: den wollte ich schicken: http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#gab599ddf60819df4cc993c724a83cb1a4
naja.. also ob mein atmega 2 oder kein u(s)art hat sollte avrstudio allerdings trotzdem wissen und so könnten diese ja nur verfügbar sein wenn der uC diese peripherieeinheit inne hat. aber gut daran will ich mich jetzt nicht aufhalten. das mit dem stdout und stdin muss ich dann noch mal versuchen nachvollzuziehen. aber erstmal ist eine terminal ausgabe für die entwicklung doch sehr hilfreich?! daher gehe ich davon aus, dass ihr zum entwickeln auch textausgaben(/-eingaben) auf terminals habt. kann ich dann davon ausgehen, das ihr auch in der main immer ein stdout=&mystdout; stdin=&mystdin; habt? den link welchen du mir schickst macht mich irgendwie nicht schlauer. da steht eigentlich das selbe wie in der stdio.h oder? für printf ist ein preogramm-beispiel welches mir bekannt war und mir auch damals das printf ermöglicht hatte. aber ich weiß nciht wie ich scanf realisieren soll :-/ ich brauche, nehme ich an eine gets()-funktion die ich dann irgendwie in scanf() einbaue und leite dann den stdin-stream irgendwie um und dann gehts?
Christian Peskov schrieb: > aber erstmal ist eine terminal ausgabe für die entwicklung doch sehr > hilfreich?! ja > daher gehe ich davon aus, dass ihr zum entwickeln auch > textausgaben(/-eingaben) auf terminals habt. nicht unbedingt. Ich meistens auf einem LCD. > kann ich dann davon ausgehen, das ihr auch in der main immer ein > > stdout=&mystdout; > stdin=&mystdin; > > habt? Nein, ich nicht. Das printf-Zeug ist eh nicht immer angesagt, weil es viel Code produziert. > > den link welchen du mir schickst macht mich irgendwie nicht schlauer. > da steht eigentlich das selbe wie in der stdio.h oder? ja, aber an der Stelle, die die automatische Verbindung mit stdin, stdout und stderr beschreibt. > für printf ist ein preogramm-beispiel welches mir bekannt war und mir > auch damals das printf ermöglicht hatte. > > aber ich weiß nciht wie ich scanf realisieren soll :-/ > ich brauche, nehme ich an eine gets()-funktion die ich dann irgendwie in > scanf() einbaue und leite dann den stdin-stream irgendwie um und dann > gehts? Du brauchst eine Funktion, die ein Zeichen liefert liefert (oder -1 im Fehlerfall). Diese Funktion wird an fdevopen übergeben, und ab dann kannst du mit scanf() lesen. scanf selbst ist schon in der Lib. Du musst nur noch sagen, wie ein Zeichen geholt werden soll.
Christian Peskov schrieb: > aber erstmal ist eine terminal ausgabe für die entwicklung doch sehr > hilfreich?! Ja. Kann man nichts dagegen sagen > daher gehe ich davon aus, dass ihr zum entwickeln auch > textausgaben(/-eingaben) auf terminals habt. > kann ich dann davon ausgehen, das ihr auch in der main immer ein > > stdout=&mystdout; > stdin=&mystdin; > > habt? eigentlich nicht. Zuviel Aufwand für zuwenig Effekt. Letzten Endes braucht man lediglich eine Textausgabe, wo auch immer diese dann erfolgt. printf mit dem ganzen stdout Unterbau ist da mit Kanonen auf Spatzen geschossen. Wenn ich den 'printf' Komfort haben will, dann nehm ich einfach sprintf. Das befüllt mir einen String und damit hab ich schon wieder alles was ich brauche um damit besagte Textausgabe zu benutzen. und stdin schon gar nicht. Die meisten Eingaben erfolgen durch das Drücken einer Taste direkt am µC. Da kommst du mit stdin sowieso nicht weiter. Da ist eine 100% zuverlässige Tastenerkennung und Entprellung viel wichtiger. Und sooooo toll ist scanf dann auch wieder nicht. Wenn es in die Fehlererkennung und Korrektur reingeht, ist scanf mehr ein Klotz am Bein, als eine echte Hilfe.
ja dann erstmal vielen dank... da muss ich noch mal drüber denken.. das mit scanf hab ich vllt kapiert.. werde ich sehen wenn später zeit finde. das mit dem entprellen stimmt. damit hab ich nämlich noch probleme. benutze ja das pollin funk evaluierungsboard. da funktion niert der taster jetzt meistens. es kommt aber bei ca. jeden 10-15 tastendruck zu einem reset des controllers! das fchst mich auch noch! mfg peter
Christian Peskov schrieb: > es kommt aber bei ca. jeden > 10-15 tastendruck zu einem reset des controllers C17 entfernen. Siehe auch hier: Beitrag "Pollin AVR Board Fehler beim drücken der Taster / Qualität der Bauteile" (anderes Board, gleicher Designfehler)
geil! das werde ich testen :)) danke ich und ein kollege hatten sogar schon mal laut überlegt ob es vllt was mit dem kondensator zutun hat - hätten ihn aber nie rausgelötet^^
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.