Próbuję wymyślić, jak używać funkcji printf do drukowania na porcie szeregowym.
Moja obecna konfiguracja to kod wygenerowany przez STM32CubeMX i SystemWorkbench32 z płytą wykrywającą STM32F407 .
Widzę w stdio.h, że prototyp printf jest zdefiniowany jako:
int _EXFUN(printf, (const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 1, 2))));
Co to znaczy? Gdzie jest dokładna lokalizacja tej definicji funkcji? Jaki byłby ogólny sens odkrywania, jak używać tego rodzaju funkcji do generowania wyników?
microcontroller
c
stm32
stm32f4
stm32cubemx
użytkownik505160
źródło
źródło
_write()
funkcja jest tym, co zrobiłem. Szczegóły w mojej odpowiedzi poniżej.Odpowiedzi:
Pierwsza metoda z tej strony działa na moim STM32F072.
http://www.openstm32.org/forumthread1055
Jak tam powiedziano
Użyłem STM32CubeMX do skonfigurowania USART1 (
huart1
) jako portu szeregowego. Ponieważ chciałem tylkoprintf()
, potrzebowałem tylko wypełnić_write()
funkcję, co zrobiłem w następujący sposób. Jest to konwencjonalnie zawarte wsyscalls.c
.źródło
_EXFUN jest makrem, prawdopodobnie zawierającym kilka interesujących dyrektyw, które mówią kompilatorowi, że powinien sprawdzić ciąg formatu pod kątem zgodności z printf i upewnić się, że argumenty printf są zgodne z ciągiem formatu.
Aby dowiedzieć się, jak korzystać z printf, sugeruję stronę podręcznika i trochę więcej googlowania. Napisz kilka prostych programów C korzystających z printf i uruchom je na komputerze, zanim spróbujesz przejść na korzystanie z niego na mikro.
Interesującym pytaniem będzie „gdzie idzie wydrukowany tekst?”. W systemie uniksowym idzie na „standardowe wyjście”, ale mikrokontroler nie ma czegoś takiego. Biblioteki debugowania CMSIS mogą wysyłać tekst printf do portu debugowania semihosting ramienia, tj. Do sesji gdb lub openocd, ale nie mam pojęcia, co zrobi SystemWorkbench32.
Jeśli nie pracujesz w debuggerze, bardziej sensowne może być użycie sprintf do sformatowania ciągów, które chcesz wydrukować, a następnie wysłanie tych ciągów przez port szeregowy lub na inny ekran, który mógł zostać podłączony.
Uwaga: printf i powiązany z nim kod są bardzo duże. To prawdopodobnie nie ma większego znaczenia na 32F407, ale jest to prawdziwy problem na urządzeniach z małą ilością flasha.
źródło
__cdecl
aby uniknąć błędów. Przynajmniej na newlib / cygwin, _EXFUN służy tylko do ustawienia__cdecl
.@ AdamHaun to wszystko, czego potrzebujesz, dzięki
sprintf()
czemu łatwo jest utworzyć ciąg, a następnie wysłać go. Ale jeśli naprawdę chcesz mieć własnąprintf()
funkcję, to Variable Argument Functions (va_list) jest właściwą drogą.Z
va_list
niestandardową funkcją drukowania wygląda następująco:Przykład użycia:
Zwróć uwagę, że chociaż to rozwiązanie zapewnia wygodną funkcję, ale jest wolniejsze niż wysyłanie surowych danych lub używanie parzystości
sprintf()
. Myślę, że w przypadku dużych danych nie będzie to wystarczające.Inną opcją i prawdopodobnie lepszą opcją jest użycie ST-Link, debuggera SWD wraz z narzędziem ST-Link. I użyj Printf za pośrednictwem przeglądarki SWO , oto instrukcja ST-Link Utility , odpowiednia część zaczyna się na stronie 31.
źródło
printf () jest (zwykle) częścią standardowej biblioteki C. Jeśli twoja wersja biblioteki zawiera kod źródłowy, możesz tam znaleźć implementację.
Prawdopodobnie łatwiej byłoby użyć sprintf () do wygenerowania ciągu, a następnie użyć innej funkcji do wysłania ciągu przez port szeregowy. W ten sposób całe trudne formatowanie jest zrobione dla Ciebie i nie musisz hakować standardowej biblioteki.
źródło
Dla tych, którzy mają trudności, dodaj następujące informacje do syscalls.c:
Podłącz do portu COM za pomocą szpachli i powinieneś być dobry.
źródło
Jeśli chcesz mieć inne podejście i nie chcesz nadpisywać funkcji ani zadeklarować własnych, możesz po prostu użyć
snprintf
do osiągnięcia tego samego celu. Ale to nie jest tak eleganckie.źródło