Hi,
ich bin gerade dabei einen USART von meinem STM32 als
Debug-Schnittstelle in Betrieb zu nehmen. Kann eigentlich keine große
Sache sein, aber irgendwie stehe ich auf dem Schlauch und weiß nicht
mehr weiter. Die printf-Ausgaben laufen auch schon wunderbar, nur
scheint es noch Probleme mit dem Einlesen bzw. mit der anschließenden
Ausgabe zu geben. Ich gebe nach einer printf-Anweisung testweise eine
Zahl mit Hyperterminal oder Putty ein (scanf Aufruf) und speicher diese
in einer Variablen. Der Inhalt wird wieder mittels printf ausgegeben.
Jedoch wird dabei die erste eingegebene Ziffer verschluckt. Beim
Debuggen habe ich festgestellt, dass die Variable die erste Ziffer nicht
enthält. Von fputc wird die Ziffer jedoch empfangen!
Du nutzt das IAR interne Terminal I/O? Vorsicht, das hält dir
streckenweise den µC an und zerwürfelt das Timing kolossal. Wir nehmen
es nicht mehr, weil das Voodoo Zeugs Seiteneffekte produziert, die man
erstmal nicht mit dem Terminal I/O in Verbindung bringt.
Ich habe es einfach mal testweise aktiviert, mir war das ganze auch
nicht geheuer. Trotzdem bleibt das Problem, dass meine Funktionen
irgendwie eine Ziffer verschlucken. Beispiel:
Eingabe: "Geben Sie eine Zahl ein: " 1234
Ausgabe: "Zahl: 234" <- tja wo ist die 1 ? fgetc hat sie erhalten.
Ich werde nochmal nach Arnes Hinweise die ganzen ITM Sachen
deaktivieren...
Bist Du Dir sicher, dass DEINE fputc() aufgerufen wird und nicht
irgendeine aus einer IAR Lib? Setz mal einen Breakpoint auf das Befüllen
des USART2->DR und schließe ein Terminalprg an. Wenn Du dann eine Zeile
drüberstepst muss das Zeichen im Terminalprg. angekommen sein.
BTW: nutzt Du USB<->RS232 Wandler am PC?
Hmm, also reingesprungen wird auf jeden Fall in beide Funktionen (fputc,
fgetc). Beim Weitersteppen kann ich bei meiner fputc auch sehen, dass
sich das DR ändert (mit der entsprechenden Ziffer befüllt), so konnte
ich auch feststellen, dass alle im Terminal eingegeben Zeichen wirklich
empfangen werden (zumindest von fgetc). Bei der fputc kann ich jedoch
keine Änderung des DR sehen, es bleibt auf 0x00. Trotzdem erscheint im
Terminalprogramm (putty) das entsprechende Zeichen (wird auch richtig
übergeben). Das hört sich komisch an. Es ist aber auf jeden Fall so,
dass die erste Ziffer gar nicht in meiner Variablen ankommt, da habe ich
auch schon nachgeschaut.
Nutze ein Olimex STM32-P103 (ti max3232c ist auf dem Board) ohne
USB-RS232 Wandler, der PC hat einen COM-Port (und der hängt an einem
Q57 Express Chipset LPC Interface Controller - 3B0A).
Dass beim Senden 0 im TransmitRegister steht ist klar - der UART schiebt
es gleich ins Schieberegister.
> Trotzdem erscheint im Terminalprogramm (putty) das entsprechende Zeichen> (wird auch richtig übergeben). Das hört sich komisch an. Es ist aber auf> jeden Fall so, dass die erste Ziffer gar nicht in meiner Variablen> ankommt, da habe ich auch schon nachgeschaut.
Ähhh... wie jetzt? Kommt alles an oder doch nicht? Welche Variable
(iChar)?
Du nimmst Teile aus einer Lib (printf), die dann sukzessive Dein fputc()
aufruft?
Oder andersrum: Du hast Teile drin, die Du nicht kontrollieren kannst.
Warum schreibst Du nicht erstmal den String mit sprintf/snprintf in
einen Puffer und haust den dann byteweise mit fputc() raus?
So, dass das DR beim Senden 0 ist, ist mir dann auch gekommen.
Ich nutze in meiner main() die printf. Diese ruft dann meine überladene
fputc auf und schreibt dann auf den USART. Wenn ich eine Abfrage mit
scanf mache erhält meine fgetc zwar alle eingegeben Zeichen, leitet
diese wohl aber nicht richtig/vollständig an scanf weiter. Die erste
eingegeben Ziffer einer Zahl wird nicht der Variablen (iNumb)
gespeichert:
int iNumb=0;
scanf("%d", &iNumb); // Bspw. Eingabe von 1234
printf("Zahl %d \r\n", iNumb); // Ausgabe nur noch 234
Die Lösung mit sprintf/snprintf hört sich auch interessant werde ich
jetzt mal ausprobieren. Thx
Also es scheint so als ob ich ein Problem mit scanf habe. Mit meiner
eigenen Funktion zur Ein- und Ausgabe funktioniert es offenbar. Ich kann
auch einen empfangenen String mit printf wieder rausschicken ohne
verlorene Zeichen. Wäre trotzdem interessant woran das liegen könnte...
Etwas praktikabler wäre es auch noch mit scanf.
> Also es scheint so als ob ich ein Problem mit scanf habe.
Bytes in Puffer empfangen.
Wenn fertig, dann mit sscanf() parsen.
Das sind GRUNDLAGEN! Nur mal so am Rande!
Arne schrieb:> Bytes in Puffer empfangen.> Wenn fertig, dann mit sscanf() parsen.> Das sind GRUNDLAGEN! Nur mal so am Rande!
Und diese Geschichte mit sscanf wollte ich mir ersparen. Ich wollte eher
das Problem lösen (warum mir ein Zeichen verloren geht), anstelle einen
zusätzlichen Workaround zu basteln.
So ich denke ich habe eine Lösung für das Problem gefunden. Die IAR
Workbench 6.21 kann zwei Versionen der C-Libs nutzen (CLib und DLib). Je
nachdem welche Version man einsetzt müssen unterschiedliche Routinen
überschrieben werden! Habe online zu den Libs das hier gefunden:
● The IAR DLIB Library, which supports ISO/ANSI C and C++. This library
also supports floating-point numbers in IEEE 754 format and it can be
configured to include different levels of support for locale, file
descriptors, multibytes, et cetera.
● The IAR CLIB Library is a light-weight library, which is not fully
compliant with ISO/ANSI C. Neither does it fully support floating-point
numbers in IEEE 754 format or does it support Embedded C++. (This
library is used by default).
Quelle:
http://supp.iar.com/FilesPublic/UPDINFO/004350/EWM32C_CompilerReferenceAddendum.pdf
Leider findet man in der Workbench selber und in den dort enthaltenen
Dokumenten kaum Infos über DLib/Clib deshalb dieses etwas ältere pdf.
Und nun zum interessanten Teil:
Migration from CLIB to DLIB
There are some considerations to have in mind if you want to migrate
from the CLIB
library, the legacy C library, to the modern DLIB C/C++ library:
● The CLIB exp10() function defined in iccext.h is not available in
DLIB.
● The DLIB library uses the low-level I/O routines __write and __read
instead of putchar and getchar.
● If the heap size in your old compiler version using CLIB was defined
in a file named heap.c, you must now set the heap size either in the
extended linker command file (*.xcl) or in the Embedded Workbench to use
the DLIB library.
Da ich die DLib nutze (eine Wechselmöglichkeit zu CLib konnte ich
übrigens nicht finden), muss ich __write und __read überschreiben. Dort
habe ich nun meine USART-Routinen eingefügt und es funktioniert ohne
Probleme.