Ich versuche herauszufinden, wie die printf-Funktion zum Drucken über die serielle Schnittstelle verwendet wird.
Mein aktuelles Setup ist STM32CubeMX- generierter Code und SystemWorkbench32 mit der STM32F407-Erkennungskarte .
Ich sehe in stdio.h, dass der printf-Prototyp wie folgt definiert ist:
int _EXFUN(printf, (const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 1, 2))));
Was bedeutet es? Wo genau befindet sich diese Funktionsdefinition? Was wäre ein allgemeiner Punkt, um herauszufinden, wie diese Art von Funktion zur Ausgabe verwendet werden kann?
microcontroller
c
stm32
stm32f4
stm32cubemx
user505160
quelle
quelle
_write()
Funktion das, was ich getan habe. Details in meiner Antwort unten.Antworten:
Ich habe die erste Methode von dieser Seite erhalten, die an meinem STM32F072 arbeitet.
http://www.openstm32.org/forumthread1055
Wie dort angegeben,
Ich habe STM32CubeMX verwendet, um USART1 (
huart1
) als serielle Schnittstelle einzurichten . Da ich nur wollteprintf()
, musste ich nur die_write()
Funktion füllen, was ich wie folgt tat. Dies ist herkömmlicherweise in enthaltensyscalls.c
.quelle
_EXFUN ist ein Makro, das wahrscheinlich einige interessante Anweisungen enthält, die dem Compiler mitteilen, dass er die Formatzeichenfolge auf PrintF-Kompatibilität prüfen und sicherstellen soll, dass die Argumente für PrintF mit der Formatzeichenfolge übereinstimmen.
Um zu lernen, wie man printf benutzt, schlage ich die Manpage und etwas mehr Googeln vor. Schreiben Sie einige einfache C-Programme, die printf verwenden, und führen Sie sie auf Ihrem Computer aus, bevor Sie versuchen, es auf dem Mikro zu verwenden.
Die interessante Frage lautet: "Wohin geht der gedruckte Text?". Auf einem Unix-ähnlichen System geht es nach "Standard Out", aber ein Mikrocontroller hat so etwas nicht. Die CMSIS-Debug-Bibliotheken können printf-Text an den Debug-Port von arm semihosting senden, dh in Ihre GDB- oder OpenOCD-Sitzung, aber ich habe keine Ahnung, was SystemWorkbench32 tun wird.
Wenn Sie nicht in einem Debugger arbeiten, ist es möglicherweise sinnvoller, sprintf zum Formatieren der zu druckenden Zeichenfolgen zu verwenden und diese Zeichenfolgen dann über eine serielle Schnittstelle oder an eine von Ihnen angehängte Anzeige zu senden.
Achtung: printf und der zugehörige Code sind sehr groß. Auf einem 32F407 spielt das wahrscheinlich keine große Rolle, aber auf Geräten mit wenig Blitz ist es ein echtes Problem.
quelle
__cdecl
, um Fehler zu vermeiden. Zumindest auf newlib / cygwin wird _EXFUN nur zum Setzen verwendet__cdecl
.@ AdamHauns Antwort ist alles, was Sie brauchen.
sprintf()
Es ist einfach, einen String zu erstellen und ihn dann zu senden. Aber wenn Sie wirklich eine eigeneprintf()
Funktion wollen , dann sind variable Argumentfunktionen (va_list) der richtige Weg.Mit
va_list
einer benutzerdefinierten Druckfunktion sieht das folgendermaßen aus:Anwendungsbeispiel:
Beachten Sie, dass Sie mit dieser Lösung zwar bequeme Funktionen verwenden können, diese jedoch langsamer sind als das Senden von Rohdaten oder die Verwendung von Even
sprintf()
. Mit hohen Datenraten denke ich, wird es nicht ausreichen.Eine weitere und wahrscheinlich bessere Option ist die Verwendung von ST-Link, dem SWD-Debugger, zusammen mit dem ST-Link-Dienstprogramm. Verwenden Sie Printf über den SWO-Viewer . Hier finden Sie das Handbuch des ST-Link-Dienstprogramms . Der entsprechende Teil beginnt auf Seite 31.
quelle
printf () ist (normalerweise) Teil der C-Standardbibliothek. Wenn Ihre Version der Bibliothek mit Quellcode geliefert wird, finden Sie dort möglicherweise eine Implementierung.
Es wäre wahrscheinlich einfacher, mit sprintf () eine Zeichenfolge zu generieren und dann mit einer anderen Funktion die Zeichenfolge über den seriellen Anschluss zu senden. Auf diese Weise wird die gesamte schwierige Formatierung für Sie erledigt und Sie müssen die Standardbibliothek nicht hacken.
quelle
Fügen Sie für diejenigen, die Probleme haben, Folgendes zu syscalls.c hinzu:
Verbinden Sie sich mit Ihrem COM-Port über Kitt und Sie sollten gut sein.
quelle
Wenn Sie einen anderen Ansatz
snprintf
verfolgen und keine Funktionen überschreiben oder eigene deklarieren möchten, können Sie einfach verwenden , um dasselbe Ziel zu erreichen. Aber es ist nicht so elegant.quelle