Hallo zusammen,
ich habe da mal wieder eine kleine Frage ;-)
Ich zerlege Strings mit dem Befehl strtok, um sie danach mit anderen
Strings vergleichen zu können.
So sieht das in meinem Code aus:
1
volatilecharuart_string0[];
2
char*pointer;
3
pointer=strtok(uart_string0,delimiter1);
Beim Compilieren bekomme ich dann eine Warnung:
passing argument 1 of 'strtok' discards 'volatile' qualifier from
pointer target type [enabled by default]
Was genau ist das Problem und wie löse ich es?
Ich habe schon danach gesucht, aber keine Lösung gefunden und für dieses
Problem reichen meine C-Kenntnisse leider noch nicht.
Bisher funktioniert es, aber ich möchte die Warnung gerne beseitigen.
Danke :-)
Das Probem ist halt, daß du einen Zeiger auf volatile char übergibst,
strok() aber einen Zeiger auf nicht-volatile char erwartet.
Die Warnung alleine beseitigen kannst du, indem du das Argument an
strtok castest, sodaß das volatile seitens der Funktion verschwindet.
Generell ist es aber keine gute Idee, einfach mit cast eine Warnung zu
umgehen - die Warnung hat manchmal Sinn.
Deshalb: wieso ist dein Feld volatile? Kann sich tatsächlich zur
Laufzeit etwas darin ändern? Falls ja, ist es kein geeignetes Argument
für strtok.
Falls nein, ist das volatile überflüssig.
Danke,
die Variable ist volatile, weil das der String ist, der den Puffer für
UART darstellt.
Ich verwende das UART Beispiel für den Interruptempfang aus dem
GCC-Tutorial:
Nun ja. Volatile ist nützlich, kann aber auch Gehirnrindenverbiegung mit
sich bringen.
Ich komme gleich auf dein konkretes Problem, möchte aber die dringende
Empfehlung vorausschicken, sich im Internet und Büchern nochmal
ausführlich über das Thema volatile zu informieren.
Nun aber:
Kurz und bündig verhindert volatile, das der Compiler bei Optimierungen
annimmt, das der schon mal z.B. in ein Register aus einer Variablen
geladene Wert nach einigen anderen Schritten immer noch gültig ist.
In Deinem Code wird aber genau genommen, durch die Variable
uart_str_complete verhindert, dass sich die Werte in dem Buffer
unerwartet verändern.
Daraus folgt, dass, solange Du das Flag uart_str_complete wirklich
konsequent verwendest, ein volatile des Buffers nicht notwendig ist.
Andererseits könntest Du in diesem Fall tatsächlich das volatile in dem
Aufruf von strok weg-casten, sprich: durch explizite Typumwandlung
entfernen, ohne das es zu negativen Effekten kommt.
Erstere Lösung ist aber vorzuziehen, weil es klar besser ist, volatile
wegzulassen, wenn es nicht nötig ist.
Ganz schlaue übrigens, wozu ich z.B. Peter Danegger zähle, machen es
ganz anders. Sie machen eine explizite Typumwandlung in volatile an
den Stellen der Zugriffe. Aber das nur nebenbei.
Ist das soweit klar, oder bleiben noch Fragen offen?
Vielen Dank für die ausführliche Antwort.
Das Flag wird konsequent verwendet.
Ich habe das volatile weggestrichen und nun funktioniert es wie es soll.
Nun sehe ich auch, dass an dieser Stelle das volatile eigentlich
überflüssig ist. Ich dachte nur, dass es schon so seine Richtigkeit
haben wird, wenn es hier im Tutorial steht.
Ich hätte noch eine ganz andere Frage, wo ich jetzt gerade die
Spezialisten hier habe. ;-)
Gibt es eine Möglichkeit bei einem Connect durch einen PC ohne das
dieser nachfragt, eine Statusmeldung einmalig abzugeben?
Sprich ich klicke im Terminalprogramm auf Connect und nachdem die
Verbindung hergestellt ist, kommt sofort ohne Nachfrage "Hallo ich bin
xy" oder so ähnlich.
Danke :-)
Wenn du RTS/CTS machst, geht das - der Einfachheit halber lässt man das
bei Controllern aber gehrne weg und nimmt nur 3 Drähte.
Was man aber bei den meisten Terminalprogrammen machen kann, ist daß sie
beim Aufbau erstmal irgendwas schicken (gedacht, um an ein Modem
irgendwelche AT...-Kommandos zu schicken.
Das könntest du im Controller abfragen, und dann deine Statusmeldung
schicken.
Das würde dann auch mit drei Leitungen ohne irgendwelche Steuerleitungen
gehen.
Vielen Dank :-)
Ich denke RTS/CTS ist mir zu kompliziert.
Dafür sehe ich auch nicht so wirklich die Notwendigleit.
Ich überprüfe den Empfang bei mir einfach durch Rückmeldungen und bleibe
bei den drei Leitungen.
Wenn sich das von Terminalprogramm zu Terminalprogramm unterscheidet,
lasse ich das lieber gleich. Dann gibts eben kein Hallo Welt zu Beginn
;)
R. B. schrieb:> Wie kann ich nun das Problem lösen, so dass es ordentlich gelöst ist?
Wiel viele Strings direkt nacheinander erwartest du denn über die
Schnittstelle?
Bei deiner Lösung kann die UART nichts empfangen, solange die
Strngbearbeitung noch nicht fertig ist.
Dagenen hilft ein zweiter Empfangsbuffer, in den der komplette String
nach empfang hineinkopiert wird. Über Flags zwischen ISR und
Hauptprogramm synchronisiert, brauchen beide Puffer nicht volatile zu
sein.
Damit kann die UART schon den nächsten String empfangen, während du den
ersten bearbeitest. Der Nachteil ist der zusätzliche Speicherbedarf für
den zweiten Buffer. Ob das noch passt, und ob du das überhaupt
benötigtst, musst du selber rausfinden.
Oliver
Oliver S. schrieb:> Dagenen hilft ein zweiter Empfangsbuffer, in den der komplette String> nach empfang hineinkopiert wird. Über Flags zwischen ISR und> Hauptprogramm synchronisiert, brauchen beide Puffer nicht volatile zu> sein.
Das stimmt nicht ganz, denn ob volatile oder nicht, hängt nicht davon
ob, ob irgend eine andere Variable volatile ist und als 'Zugriffsschutz'
fungiert. Der Compiler kann deswegen immer nocht entscheiden, dass er
die fragliche Variable in einem Register hält. Obwohl das bei einem
Array natürlich recht unwahrscheinlich ist. So viele Register hat der
Compiler nicht zur Verfügung.
Unabhängig davon ist natürlich die Betrachtungsweise für ...
> Damit kann die UART schon den nächsten String empfangen,