Hallo zusammen,
ich übertragen via USART an einen Atmega16 Daten. Diese kommen dort in
einem char array an. Nun möchte ich diesen char Array in einen Integer
umwandeln.
ich habs mit folgendem versucht:
ich habe vom PC aus 72000 an den µC gesendet angekommen is aber: 64640.
Dannach habe ich testweise die mit 1 kommentierte Zeile auskommentiert,
jetzt kam 2000 an. Das würde passen. Irgendwie scheint ihm also die
Multiplikation mit 10000 nicht zu gefallen.
Kann mir wer einen Tipp geben?
Gruß
> Irgendwie scheint ihm also die Multiplikation mit 10000 nicht zu gefallen.> Kann mir wer einen Tipp geben?
Die Multiplikation in 32 Bit ausführen, sonst gibts bei 16 Bits einen
Überlauf.
Ist doch schon 32 Bit,
uint32_t recived_time_ticks;
kann aber auch sein, dass durch ein 5732te Sonderregel von C das bei der
verkürzten Schreibweise nicht erkannt wird. Dann kann man das aber auch
ohne Monster-Panik-Cast(ing) machen. Einfach ein L an die 10000 anfügen,
damit wird das eine 32 Bit Konstante.
recived_time_ticks += ((usart_string[0] - '0') * 10000L); //1
MFG
Falk
Falk Brunner schrieb:> Ist doch schon 32 Bit,
Nein.
> uint32_t recived_time_ticks;
Das hat aber absolut nichts damit zu tun, mit welcher Bitbreite die
Multiplikation durchgeführt wird.
> kann aber auch sein, dass durch ein 5732te Sonderregel von C das bei der> verkürzten Schreibweise nicht erkannt wird.
Das hat nichts mit Sonderregeln oder einer verkürzten Schreibweise zu
tun, sondern liegt schlicht daran, daß der Typ, mit dem eine Operation
durchgeführt wird, immer nur von den Operanden abhängt und nie davon,
was später mit dem Ergebnis gemacht wird.
Bei
1
((usart_string[0]-'0')*10000)
sind beide Operanden der Multiplikation vom Typ int, also wird die
Multiplikation in int durchgeführt.
@ Rolf Magnus (Gast)
>Das hat nichts mit Sonderregeln oder einer verkürzten Schreibweise zu>tun, sondern liegt schlicht daran, daß der Typ, mit dem eine Operation>durchgeführt wird, immer nur von den Operanden abhängt und nie davon,>was später mit dem Ergebnis gemacht wird.
Schon klar, aber
>((usart_string[0] - '0') * 10000)>sind beide Operanden der Multiplikation vom Typ int, also wird die>Multiplikation in int durchgeführt.
Falsch, dein "Zitat" ist ausserdem unvollständig.
1
recived_time_ticks+=((usart_string[0]-'0')*10000);// Original
Somit steht jetzt eine 32 Bit Zahl auf der rechten Seite, womit ALLE
anderen Zahlen erstmal in 32 Bit konvertiert werden, bevor gerechnet
wird. Oder nicht?
MfG
Falk
Falk Brunner schrieb:> Schon klar, aber>>>((usart_string[0] - '0') * 10000)>>>sind beide Operanden der Multiplikation vom Typ int, also wird die>>Multiplikation in int durchgeführt.>> Falsch, dein "Zitat" ist ausserdem unvollständig.
Nein, das ist nicht falsch, und das Zitat enthält alles, was für die
Beantwortung der Frage, mit welchem Typ die Multiplikation durchgeführt
wird, notwendig ist.
> recived_time_ticks += ((usart_string[0] - '0') * 10000); // Original> recived_time_ticks = recived_time_ticks + ((usart_string[0] - '0') * 10000); //
Äquivalent
>> Somit steht jetzt eine 32 Bit Zahl auf der rechten Seite, womit ALLE> anderen Zahlen erstmal in 32 Bit konvertiert werden, bevor gerechnet> wird. Oder nicht?
Nein. Du mußt jede Operation einzeln betrachten. Deshalb: Es ist egal,
was später mit dem Ergebnis passiert, es zählen ausschließlich die
Operanden. Das heißt, es spielt keine Rolle, daß du das Ergebnis der
Multiplikation später einer 32-Bit-Variablen zuweist.
Die Berechnung läuft in dieser Reihenfolge ab:
Durch die Klammerung kommt zuerst:
(ich führe mal für das Zwischenergebnis eine Variable 'tmp' ein)
1
tmp=usart_string[0]-'0'
Der linke Operand ist vom Typ char, der rechte vom Typ int, also wird
zuerst der linke nach int konvertiert ("integer promotion"), dann wird
die Subtraktion in int durchgeführt. tmp wäre also auch vom Typ int.
Jetz kommt
1
tmp2=tmp*10000;
tmp ist vom Typ int, 10000 auch, also wird die Multiplikation auch mit
dem Typ int durchgeführt, und tmp2 ist ebenfalls vom Typ int. Jetzt
kommt
1
received_time_ticks+=tmp2;
received_time_ticks it vom typ uint32_t, tmp2 ist vom Typ int, also wird
jetzt tmp2 nach uint32_t konvertiert und dann die Additon durchgeführt.
Das heißt, daß nur diese eine Addition in 32 Bit abläuft, der Rest aber
in 16 Bit.
@ Rolf Magnus (Gast)
>Nein. Du mußt jede Operation einzeln betrachten. Deshalb: Es ist egal,>was später mit dem Ergebnis passiert, es zählen ausschließlich die>Operanden.
Ok, das ist dann wohl der Knackpunkt, der mir bisher nicht bekannt war.
Ich dachte das wird auf die gesamte Rechnung auf einmal bezogen. Danke
für die Aufklärung.
>Das heißt, daß nur diese eine Addition in 32 Bit abläuft, der Rest aber>in 16 Bit.
Dann sollte aber mein Tip mit 10000L funktionieren. Oder der Fehler
steckt woanders, wahrscheinlich in einem Pufferüberlauf und einem
verschluckten ersten Zeichen. ;-)
@ OP
Um die Routine zu prüfen solltest du mal explizit im Programm den Puffer
füllen und nicht per UART.
MfG
Falk
zb wäre es schon von Vorteil, recived_time_ticks zunächt mit 0 zu
initialisieren. Oder aber in der ersten Rechnung kein += sondern ein
simples = zu machen.
Ansonsten:
Den String zum Sender zurücksenden oder sonst irgendwo ausgeben um
nachzusehen, ob auch tatsächlich das angekommen ist, was du denkst das
angekommen sein sollte. In der Kette
Eingange -> Verarbeitung -> Ausgabe
kann der Fehler überall stecken. Auch im Schritt Eingabe. Ist die schon
falsch, kannst du hinten nach suchen so viel du willst. Eine viel zu oft
vergessene Regel sagt schliesslich "garbage in - garbage out". Wenn
vorne schon Müll hineingesteckt wird, wird hinten auch immer Müll
rauskommen.
leider ohne Erfolg. Hat jemand noch nen Tipp oder kennt wer ne
unproblematischere Lösung um den char array in einen integer zu
bekommen? Oder evtl. sogar ne einfachere Möglichkeit die 72000 über
USART in den µC zu bekommen?
Gruß
@ Michael O. (michi26206)
>habe folgendes ohne Erfolg versucht:
Das ist reine Panik, bringt aber rein gar nichts. Dein Problem liegt
woanders. So reicht es.
Abend,
so ich bin jetzt alles nochmal durchgegagen.
Es war wie Ihr gesagt habt, die Rechnung war in Ordnung, aber die
Ausgabe des Ergebnisses hat nicht gepasst, ich habe den Integer beim
Ausgeben wieder in einen String umgewandelt, hierfür habe ich allerdings
nicht die 32Bit (utoa) Methode verwendert sondern die 16 Bit (itoa).
Gruß & Danke @ all
Michael O. schrieb:> Abend,>> so ich bin jetzt alles nochmal durchgegagen.> Es war wie Ihr gesagt habt, die Rechnung war in Ordnung, aber die> Ausgabe des Ergebnisses hat nicht gepasst, ich habe den Integer beim> Ausgeben wieder in einen String umgewandelt, hierfür habe ich allerdings> nicht die 32Bit (utoa) Methode verwendert sondern die 16 Bit (itoa).
Immer noch falsch
itoa int 16 Bit mit Vorzeichen
utoa unsigned int 16 Bit ohne Vorzeichen
ltoa long 32 Bit mit Vorzeichen
ultoa unsigned long 32 Bit ohne Vorzeichen