Forum: Mikrocontroller und Digitale Elektronik printf Atmega 32


von Christian P. (peterfrosta)


Angehängte Dateien:

Lesenswert?

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 :))

von Wilhelm F. (Gast)


Lesenswert?

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.

von cskulkw (Gast)


Lesenswert?

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.

von Christian P. (peterfrosta)


Lesenswert?

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

von XMEGA (Gast)


Lesenswert?

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

von Christian P. (peterfrosta)


Lesenswert?

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öö

von Christian P. (peterfrosta)


Lesenswert?

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"

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

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.

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

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.

von Christian P. (peterfrosta)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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

von Christian P. (peterfrosta)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Christian P. (peterfrosta)


Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?


von Christian P. (peterfrosta)


Lesenswert?

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?

von Klaus W. (mfgkw)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Christian P. (peterfrosta)


Lesenswert?

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

von Haushaltsgerätetechniker (Gast)


Lesenswert?

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)

von Christian P. (peterfrosta)


Lesenswert?

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
Noch kein Account? Hier anmelden.