Hallo zusammen, ich möchte von PIC Controllern zum MSP430 umsteigen und habe mir die notwendigen Tools (FET149, mspgcc,...) beschafft. Nach anfänglichen Schwierigkeiten wurde das LED Beispiel übersetzt und ich konnte das Ganze mit Insight auch laden und debuggen. Nun folgte der nächste Schritt, das berühmte 'Hello World' auszugeben. Mit den IAR Tools kein Problem, mit dem MSPGCC jedoch scheinbar eine sehr große Hürde?!? Was ist daran falsch??? #include <stdio.h> int main(void) { // ..do anything.. printf("Hello World\n\r"); return 0; } 1. Warning des Compilers "implicit declaration of function 'printf'" 2. Fehlermeldung des Linkers "undefined reference to 'printf'" Es sieht so aus als ob die Include-Datei 'stdio.h' nicht erkannt wird. Hat jemand einen Tip, auch nach eingehender Internet-Recherche habe ich nichts über die Verwendung 'printf' beim MSP430 mit dem MSPGCC gefunden? Muss man sich diese Funktion selber schreiben? Gruß Ralf
Deine Schlußfolgerung ist geringfügig falsch. Wenn <stdio.h> nicht erkannt werden würde, hättest Du eine entsprechende Compilermeldung erhalten. Sie existiert also ganz offensichtlich. Wenn er sich über eine implicit declaration beschwert, heißt das aber, daß <stdio.h> kein printf() enthält. Nun, durch nachsehen in der Datei stdio.h kannst Du das sicher auch verifizieren. Wenn Dir der Linker dann sagt, daß es eine undefined reference to printf gibt, dann gibt es offensichtlich nicht nur in den header files kein print(), sondern auch in der Bibliothek. Fazit: printf() ist einfach nicht implementiert. Das ``Helloworld''-Examples eines Microcontrollers ist übrigens nicht die Ausgabe von "Hello, world!\n" auf einer UART, sondern eher die blinkende LED oder sowas. Erstens ist printf() eine recht komplexe Funktion (die folglich auch sehr viel Code mit sich in den ROM schleppt), zweitens braucht man noch die Pegelwandler für die RS232. Drittens hat ein Controller im Gegensatz zu einem hosted environment eben von Haus aus erstmal gar nichts wie stdin und stdout zur Verfügung. Für die avr-libc haben wir vor einiger Zeit eine komplette printf() Familie implementiert, die müßte eigentlich portabel sein auf andere Controller gleichen Kalibers, sofern Deine Bibliothek ein malloc() besitzt. Das könntest Du Dir ja als Ausgangsbasis ja mal ansehen. Aber nicht erschrecken, wie ich bereits schrob: printf() ist komplex.
Hallo Joerg, danke für Deine rasche Antwort. Ich war schon am Verzweifeln. Die LED blinkt ja schon mal. Und die RS232-Hardware kommuniziert mit dem PC durch Beschreiben des TX-Buffers (getestet mit den IAR-Tools). Beispiel-Routine: void SendHello(void) { TXBUF0='H'; // transmit "H" while ((UTCTL0&0x01)==0); TXBUF0='e'; // transmit "e" while ((UTCTL0&0x01)==0); TXBUF0='l'; // transmit "l" while ((UTCTL0&0x01)==0); TXBUF0='l'; // transmit "l" while ((UTCTL0&0x01)==0); TXBUF0='o'; // transmit "o" while ((UTCTL0&0x01)==0); TXBUF0=13; // send carriage return while ((UTCTL0&0x01)==0); } Da ich aber später Messwerte über die serielle Schnittstelle übertragen will, sowie 'printf' auch ausgiebig zu Debug-Zwecken nutzte, vermisse ich diese Funktion sehr. Mir ist bewußt, dass 'printf' sehr komplex ist. Mal sehen ob ich mir eine Portierung antue. Fürs erste muss eine einfache Ausgabe reichen. Eventuell hat hier jemand eine Idee wie man elegant Text über die serielle Schnittstelle sendet ohne 'printf' zu benützen. Gruß Ralf
Hi C-String ausgeben: void rs232_print(unsigned char *s) { while(*s) { rs232_putc(*s); s++; } } Matthias
Nicht vergessen, aus \n noch ein \r\n zu machen. Ich empfehle die folgende uart_putchar() Funktion als minimale Funktion für meine stdio-Implementierung in der Doku der avr-libc: int uart_putchar(char c) { if (c == '\n') uart_putchar('\r'); loop_until_bit_is_set(UCSRA, UDRE); UDR = c; return 0; } Diese Funktion ist dort als Parameter an fdevopen() zu übergeben. Ralf, wenn Du schon ein malloc() hast, dann ist die Portierung dieser printf-Familie wahrscheinlich nur wenig mehr als das Zimmern des entsprechenden Makefiles. Habe gerade mal ein fgrep '#include <avr/' dort gemacht, das sollte die benutzten AVR-spezifischen Features einigermaßen zutage fördern. Da ist nur <avr/pgmspace.h> benutzt, der Zugriff auf die ROM-Konstanten (hier ROM-Strings) im AVR. Das mußt Du Dir für den MSP430 sicher wirklich ändern, manches wird vielleicht auch einfacher aufgrund dessen von-Neumann-Architektur, mit der der gcc ja besser klarkommt. Einige wenige Funktionen sind auch als Assembler-Stubs geschrieben: getc() und putc(), da steht nur ein Sprung nach fgetc() und fputc() drin. Sicher auch einfach zu portieren.
Hi warum sollte man aus '\n' "\r\n" machen? Ein einzelnes '\n' kann auch durchaus mal beabsichtig sein um eine entsprechende Ausgabe zu erreichen. Wenn man diese Art des Zeilenumbruchs will sollte man das im String auch explizit angeben. Just my 2 Cent Matthias
Unix kann seit 25 Jahren damit leben, daß das so gemacht wird. ;-) Ich habe noch keinen einzigen ernsthaften Anwendungsfall gesehen, wo man wirklich einen einzelnen Zeilenvorschub benötigen würde. Den umgekehrten Fall, ein einzelnes \r, braucht man gelegentlich mal. Klar, man kann das auch im String angeben, aber erstens ist es C-Konvention, nur \n zu nehmen, zweitens spart es paar Bytes.
Hi Geschmackssache. Ich geb es eben lieber expliziet an. Matthias
Hallo, ich habe die Funktion von Mathias implementiert und es funktioniert. Für die Datenkonvertierung sowie der Ausgabe der Messwerte muss ich mir noch ein paar Gedanken machen. @ Matthias Vielen Dank für die Routine, ich wäre wahrscheinlich zuerst mit der Kirche ums Dorf gegangen. @ Joerg Da ich noch einiges an anderer Hardware austesten will und mit der Entwicklungsumgebung (make file, macros,...) nicht so vertraut bin, werde ich mit der Portierung von 'printf' noch etwas warten. Ansonsten vielen Dank für Deinen Beitrag bei meinem Problem. An alle anderen, die in der gleichen Lage sind oder glauben zu sein, hier mein Beitrag zur seriellen Ausgabe von Text: --------------------------------------------------------------- void rs232_print(unsigned char *s); // string is sent via RS232 int main(void) { unsigned int i,k; unsigned char *my_string="Hello World\r\n"; Init_OSC(); // Initialization of oscillator Init_UART(); // Initialization of UART P1DIR = BIT0; // P1.0 output while (1) { P1OUT |= BIT0; // Set P1.0 rs232_print(&my_string[0]); // send string over rs232 for (i=0;i<=20000;i++) // wait loop k++; P1OUT &= ~BIT0; // Clear P1.0 for (i=0;i<=20000;i++); // wait loop k--; } return 0; } void rs232_print(unsigned char *s) { while(*s) { TXBUF0 = *s; while ((UTCTL0&0x01)==0); s++; } } -------------------------------------------------------- Gruß Ralf
Spar dir die Portierung: http://mspgcc.sourceforge.net/manual/x1108.html: The function uprintf(void (*func)(char c), const char *fmt,...); is similar to "sprintf()", except that caller provides an output function for printing, rather than an output buffer. This function must accept a single "char" parameter, and return "void" (for example to send a character to a UART). The user function is responsible for mutexes, slow interfaces, etc. "uprintf()" will not return until all characters have been printed.
Macht die eigentlich auch floating point? Dann würde mich mal interessieren, wie groß das Resultat ist. Mir war es auf dem AVR zu groß, als daß ich FP immer dabei haben möchte, so daß es zwei Alternativen gibt: mit und ohne FP. (Noch eine dritte, die fast nichts mehr kann und noch ein wenig kleiner ist, wenn man mal arg knapp dran ist mit dem Platz und es für ein paar Debug-Ausgaben braucht.)
Float ist nicht drin, die Funktion ist ca. 1450 Byte groß (wenn man sie mit AVR-GCC kompiliert sind es sogar 30 Bytes mehr). http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/mspgcc/msp430-libc/src/stdlib/uprintf.c?rev=1.5&content-type=text/vnd.viewcvs-markup Das Schöne am MSP430 ist, dass man sich die Verrenkungen beim ROM-Zugriff sparen kann.
Ah, diese Version hat er als Basis genommen. Alexander Popov hatte dann eine neuere Variante daraus gezimmert, die für den AVR besser optimiert war. Das war dann meine Basis für das jetztige vfprintf().
Hallo Andreas, danke für den Tipp! Nach einigen Versuchen läuft nun auch die Textausgabe mit 'uprintf'. :-) Gruß Ralf
Hallo ich hab ein problem ich möchte eine float zahl über die serielle schnittstelle senden, nun bekomme ich immer den fehler float NOFLOAT option kann man mit dem befehl printf("Hallo" , float_zahl) das nicht realisieren?
Erstens hast du einen uralten Thread gekapert und zweitens redest du mit an Sicherheit grenzender Wahrscheinlichkeit nicht über {AVR,ARM,MSP430}-GCC.
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.