Hi! Zuerst möchte ich allen hier Frohe Weihnachten und schöne Feiertage wünschen! Ich bastle seit längerer Zeit an einem Programm, um max. 16Stück DS18B20 welche an 2 analog Multiplexer(CD4051BE) hängen, auslesen zu können. Die analogen Multiplexer besitzen 8 Kanäle und werden über jeweils 3 Adressleitungen angesprochen. Die Adressleitungen der beiden Multiplexer hängen parallel. So ergeben sich 5 benötigte Leitungen bzw. Pins am Controller. Der momentane Testaufbau: ------------------------- Der Sensor hängt DIREKT am Controller. Also ohne Multiplexer als "Vermittler". Pin 1: GND Pin 2: DQ mittles 4k7 auf +5V und an Pin PC6 Pin 3: +5V (keine parasitäre Versorgung) PC7 hängt mittels 4k7 ohne Sensor auf +5V. Das Problem: ------------ Es wird definitif fehlerhaft vom Sensor gelesen. Weder die Temparatur noch das Config-Byte werden richtig gelesen. Die 9 Byte des Scratchpad´s werden per UART ausgegeben (HTerm) und können kontroliert werden. Ich find einfach keinen Fehler mehr? Kann es sein, daß die paar Zentimeter ungeschirmter Draht eine Kommunikation unmöglich machen? Ich wäre sehr dankbar, wenn jemand von euch meinen Code anschauen könnte, vielleicht findet ja wer doch noch einen Fehler. Die 2 Versionen der Datenblätter, das App.Note 162 den Code von Peter unter anderen hab ich mir schon angeschaut. Grüsse Rick
Naja, die CD4000-er sind bei 5V nicht gerade der Renner. Ich glaub, die haben so etwa 1kOhm, das ist schon heftig. Die sollte man daher nur wirklich bei 12..18V nehmen. Bei 5V nimm besser den 74HC4051. Peter
Peter Dannegger wrote: > Naja, die CD4000-er sind bei 5V nicht gerade der Renner. > Ich glaub, die haben so etwa 1kOhm, das ist schon heftig. > Die sollte man daher nur wirklich bei 12..18V nehmen. lt. Datenblatt 100 bis 500 ohm, aber daß sich der Widerstand bei sinkender Betreibsspannung ändert? hab ich nicht gewußt. Danke für den Tipp! > > Bei 5V nimm besser den 74HC4051. Ich lese mir das Datenblatt durch. Aber beim Testaufbau habe ich die Multiplexer vorerst weggelassen, denn wenns ohne Multiplexer ned funktioniert, dann mit ihnen schon gar nicht. Bin mittlerweile mit dem Ding echt kurz vor dem Explodieren. Gestern in der Nacht, wäre der ganze Krempl fast aus dem Fenster geflogen. Gruß Rick
@ Erik M. (rick00) >Aber beim Testaufbau habe ich die Multiplexer vorerst weggelassen, denn >wenns ohne Multiplexer ned funktioniert, dann mit ihnen schon gar nicht. Wozu überhaut der MUX? Das ist doch ein 1-Wire Bus. >Bin mittlerweile mit dem Ding echt kurz vor dem Explodieren. >Gestern in der Nacht, wäre der ganze Krempl fast aus dem Fenster >geflogen. Ich schmeiss die Scheisse ausm Fenster naus! 200 Buls hab isch. BALD! Duuuuuu! ;-) http://www.jokenet.de/sw_detail.asp?id=2049 MFG Falk
Falk Brunner wrote: > @ Erik M. (rick00) > >>Aber beim Testaufbau habe ich die Multiplexer vorerst weggelassen, denn >>wenns ohne Multiplexer ned funktioniert, dann mit ihnen schon gar nicht. > > Wozu überhaut der MUX? Das ist doch ein 1-Wire Bus. > 1.) sehr einfache Zuordnung Temperatur <-> Mess-Stelle 2.) Bei Kurzschluß oder Sensordefekt, fällt nur 1 Sensor aus und nicht der ganze Bus. 3.) Länge der Zuleitungen addieren sich nicht, da ja immer nur 1 Sensor dran hängt (beiläufiger Vorteil) >>Bin mittlerweile mit dem Ding echt kurz vor dem Explodieren. >>Gestern in der Nacht, wäre der ganze Krempl fast aus dem Fenster >>geflogen. > > Ich schmeiss die Scheisse ausm Fenster naus! > 200 Buls hab isch. BALD! Duuuuuu! > > ;-) > > http://www.jokenet.de/sw_detail.asp?id=2049 jo genau so isches ....ich hau die Scheisse ausn Fenster....ich find auch nicht den ON-Knopf...und zurückgebn kaun ih des blede Ding ah nimma mehr ;-) MFG Rick
Hi! Ich verstehe die Funktionen zum Senden und Empfangen von Peter Dannegger einfach nicht. Die sind für mich einfach zu komplex verschachtelt. Ich habe Peters Code getestet und er funktioniert tadellos. Mein Code hingegen streikt? Könnte mir jemand sagen, ob ich die Sende- und Empfangsfkt. von Peter in meinem Programm richtig interpretiert habe. Grüsse Rick
Hi! Ich lese immer nur 1sen aus und weiß einfach nicht warum. meine Fkt. reset_1wire() funktioniert und den Presence Puls empfange ich auch. Wenn es aber darum geht, die Temparatur aus zu lesen, empfange ich immer nur für jedes Byte 255??? Ich halt mich genau an die Timings im Datenblatt, aber diese Sensoren reden anscheinend nicht mit jeden :-( Hat jemand vielleicht debugging Tips für mich? Gruß Rick
Ich bin jetzt nicht der 1wire Experte. Aber mir fällt auf, das du für das Timing des Reset eine andere Delay Funktion nimmst als für die schreib und lese Funktionen (delay_ms() vs. delay_us() ). Eventuell liegt hier ja ein Fehler vor ? - Hast Du mal deine Timings mit einem Osci kontrolliert ? - lässt dein Multiplexer (leider geht nicht genau hervor ob Du Ihn jetzt schon in Betrieb hast) überhaupt den "lesepuls" durch ? mehr sehe ich auf Anhieb leider auch nicht. Und meine DS18S20 sind nicht rechtzeitig zum Fest geliefert worden :-( Gruss Juergen
Hi Jürgen! Jürgen Sachs wrote: > Ich bin jetzt nicht der 1wire Experte. > Aber mir fällt auf, das du für das Timing des Reset eine andere Delay > Funktion nimmst als für die schreib und lese Funktionen (delay_ms() vs. > delay_us() ). Eventuell liegt hier ja ein Fehler vor ? _delay_us() ist genauer als _delay_ms() weshalb der Fehler, so glaub ich hier nicht liegt. Aber ich werd es probieren. Mittlerweile bin ich wirklich für jeden Tipp dankbar, denn ich weiß echt nicht mehr weiter. Entweder hab ich ein Compilerproblem, oder ich schau schon zum 1000sten Mal über den Fehler drüber. > - Hast Du mal deine Timings mit einem Osci kontrolliert ? Oszi, nein. Ich hab ein altes analoges Oszi, welches ich aber zuerst reparieren müsste. > - lässt dein Multiplexer (leider geht nicht genau hervor ob Du Ihn jetzt > schon in Betrieb hast) überhaupt den "lesepuls" durch ? Nein, der Multiplexer liegt noch in der Schublade. Den hol ich erst hervor, wenns mit der Direktverbindung klappt. > > mehr sehe ich auf Anhieb leider auch nicht. Und meine DS18S20 sind nicht > rechtzeitig zum Fest geliefert worden :-( Meine DS18B20 sind zum Glück noch im letzten Augenblick vor Weihnachten gekommen. Gruß Rick
Hi! Also die Delay-Routinen sind es nicht. Gruß Rick
Hi! Konnte mein Oszi wieder zusammenflicken :-) ..zum Glück wars nur ne Kleinigkeit. Habe nun folgende Fkt.en gemessen: 1.) reset_1wire(); 2.) write_byte_1wire(0x00); 3.) write_byte_1wire(0xFF); ---------------------------------------- ad 1: gemessen programmiert ------------------------------------------------------------------------ --- reset pulse: 500usec 500usec DS18B20 waits: 30usec 65usec warten anschl Presence Puls abfragen Presence Puls: 115usec Rest: 360 usec 435 usec warten ---------------- ------------------------------ ges.: 1005usec 1000usec Hier ist alles in Ordnung. Hat auch von Anfang an funktioniert. ______________________________________________________________________ _ ad 2: gemessen programmiert ------------------------------------------------------------------------ -- 68usec low 66usec ca. 5usec bis 7usec high 1usec recovery time (starkes Nachleuchten am Oszi) Hier ergibt sich doch eine relativ große Abweichung? Bei 16Mhz sollte das eigentlich schneller gehen. ______________________________________________________________________ _ ad 3: gemessen programmiert ------------------------------------------------------------------------ -- 5 bis 7usec low 1usec low 68usec high 65usec high 1usec recovery time Hier ergibt sich ebenfalls eine relativ große Abweichung. Ist aber noch in der Toleranz von 15usec. Wie ich die Sensorantworten lesen soll, weiß ich nicht. Hat jemand einen Tipp? Anzeige immer noch 0,0°C da ich immer noch nur 1sen lese? Gruß Rick
Erik M. wrote: > > Hier ergibt sich ebenfalls eine relativ große Abweichung. > Ist aber noch in der Toleranz von 15usec. > Da würde ich mir mal keine Gedanken machen, mehr Recovery Zeit wirkt sich ja nur auf die Datenübertragung aus, macht Sie langsammer. Bei 16 MHz sind eben nur Max. 16 Befehle pro us Möglich. Funktionsaufruf, Rücksprung usw... Ich würde sagen ein Blick ins lss sollte sagen was da solangen Dauert (Stichwort Taktzyklen zählen). Aber wie Du shcon sagtest ist ja unkritisch. > > Wie ich die Sensorantworten lesen soll, weiß ich nicht. Hat jemand einen > Tipp? > > Anzeige immer noch 0,0°C da ich immer noch nur 1sen lese? > > Gruß Rick Also ich würde meine Funktionen (read_bit_1wire) als nächstes testen, ob die Fehlerhaft sind. Dazu würde ich den 1 Wire mit einem Widerstand von ca 100-200 Ohm (Schutz des Pin vor Zerstörung), Kurzschließen. Dann MUSS deine lesefunktion lauter Nullen lesen. Funktioniert das, würde ich vermuten das es nur noch ein Timingproblem sein kann, oder Du bekommst keine Antwort. Wodurch auch die ganzen Einsen entstehen durch den 1wire Aufbau. So weis man ob es am Code oder an der Hardware liegt. Den Fehler eben in kontrollierten Häppchen eingrenzen. Mehr fällt mir dazu erst mal nicht mehr ein. Eventuell hat ein 1Wire Experte hier im Forum noch eine Idee. Gruss Juergen
Hi Jürgen! Also ich hab mal weitere Messungen vorgenommen: Messung 1: ------------ Fkt. write_bit_1wire(1); programmiert / gemessen DQ low 2usec warten / gut 2usec DQ high / Widerstand braucht ca 4usec für pull-up 67usec warte / 67usec ______________________________________________________________________ __ Messung 2: ---------- Fkt. write_bit_1wire(0); programmiert / gemessen DQ low 67 usec warten / 67,4usec DQ high 2usec recovery / 2,6usec ______________________________________________________________________ __ Messung 3: ---------- Fkt. read_bit_1wire('a'); programmiert / gemessen DQ low 2usec warten / 2usec low DQ high / Wiederstand braucht 2,8usec für pull-up 11 usec warten abfragen 54 usec warten / 66usec (soll = 11+54=65usec) ______________________________________________________________________ __ Wenn ich aber die Fkt.en write_byte_1wire messen möchte, bei denen 8bit hintereinander folgen, so streikt mein Osci. Ich kann keine klaren Zeiten mehr ablesen, weil ich nur noch Mehrfacherscheinungen habe und auch die fallenden Flanken nicht mehr richtig erkennen kann. Die Bit-Funktionen stimmen von den Zeiten her aber tadellos! Ich probier jetz noch den pull-down, nach Deinem Vorschlag und schau mal, ob ich 0en lese. Gruß Rick
Hi! Wenn ich mit einem 560 Ohm widerstand einen pull-down mache so lese ich lauter nullen => jedes Byte hat den Wert null. Jetzt kann ich noch einen Fehler in der Fkt. write_byte_1wire haben und/oder ein Timing-Problem, weil mir der Sensor nicht antwortet. Grüsse Rick
@ Erik M. (rick00) >Wenn ich mit einem 560 Ohm widerstand einen pull-down mache so lese ich >lauter nullen => jedes Byte hat den Wert null. ??? Was soll denn der Unsinn? 1-Wire ist ein OpenDrain Bus, ähnlich I2C. Da hat ein Pull Down nichts zu suchen. MFG Falk
Hi Falk! Falk Brunner wrote: > @ Erik M. (rick00) > >>Wenn ich mit einem 560 Ohm widerstand einen pull-down mache so lese ich >>lauter nullen => jedes Byte hat den Wert null. > > ??? > Was soll denn der Unsinn? 1-Wire ist ein OpenDrain Bus, ähnlich I2C. Da > hat ein Pull Down nichts zu suchen. Das stimmt schon so! Ich wollte ja nur testen, ob meine Lesefunktion überhaupt 0en lesen kann und habe einen Sensor-Pull-Down simuliert. ______________________________________________________________________ __ Bin jetzt einen Schritt weiter gekommen und kann wenigstens vom Sensor, welcher statt Multiplexer A am Controller hängt korrekt das Scratchpad auslesen. Die Wertigkeiten der Bytes sind wie folgt: 119 LSB Temp 1 MSB Temp 0 0 127 Config Register 255 9 16 151 CRC Temp zusammengesetzt: 375 ________________________________________________ alles richtig. jetzt rechne ich: int16_t temp=0, temp1=0; // temp ist die zusammengesetzte Temparatur (LSB + MSB) temp1 = ((temp * 325) / 1000); return temp1; temp1 ist vollkommen falsch berechnet (-27)? Hat der Controller da einen Overflow? Was ist an meiner Rechnung falsch? Rauskommen müsste: (375*625) /1000 = 234 was einer Temparatur von 23,4°C entspricht. Grüsse Rick
Erik M. wrote: >> ??? >> Was soll denn der Unsinn? 1-Wire ist ein OpenDrain Bus, ähnlich I2C. Da >> hat ein Pull Down nichts zu suchen. > > Das stimmt schon so! Ich wollte ja nur testen, ob meine Lesefunktion > überhaupt 0en lesen kann und habe einen Sensor-Pull-Down simuliert. Richtig, das war nur ein Test ob die Funktion Funktioniert. Hätte er jetzt wieder nur 1en gelesen wäre die Funktion fehlerhaft. Jetzt weis man das Sie Funktioniert. ______________________________________________________________________ __ > > Bin jetzt einen Schritt weiter gekommen und kann wenigstens vom Sensor, > welcher statt Multiplexer A am Controller hängt korrekt das Scratchpad > auslesen. > Ahja, woran lag es ? Dann wüsste ich welchen Fehler ich nicht machen darf :-) > jetzt rechne ich: > > int16_t temp=0, temp1=0; > > // temp ist die zusammengesetzte Temparatur (LSB + MSB) > temp1 = ((temp * 325) / 1000); > return temp1; > > temp1 ist vollkommen falsch berechnet (-27)? Hat der Controller da einen > Overflow? > > Was ist an meiner Rechnung falsch? Rauskommen müsste: (375*625) /1000 = > 234 > was einer Temperatur von 23,4°C entspricht. Vielleicht ist es nur ein Tippfehler, aber in deiner Formel oben steht 325, unten rechnest du mit 375 ? Gruss Juergen
Erik M. wrote: > int16_t temp=0, temp1=0; > > // temp ist die zusammengesetzte Temparatur (LSB + MSB) > temp1 = ((temp * 325) / 1000); > return temp1; > > temp1 ist vollkommen falsch berechnet (-27)? Hat der Controller da einen > Overflow? > > Was ist an meiner Rechnung falsch? Rauskommen müsste: (375*625) /1000 = > 234 > was einer Temparatur von 23,4°C entspricht. Ja, du bekommst einen Überlauf. 375*625 = 121875. in einen in16 passen aber max 32768. Also für temp1 eine uint32 nehmen oder die Berechnung auf uint32 casten und das Ergebnis wieder uint16. etwa so: temp1 = (uint16_t)((uint32_t)((temp * 325) / 1000)); ich habe aber keine Ahnung ob das geht und ob das der gcc weg optimiert ! Juergen
> temp1 = ((temp * 325) / 1000);
Mach mal folgendes
temp1 = ((temp * 325UL) / 1000);
Jürgen Sachs wrote: > Erik M. wrote: >>> ??? >>> Was soll denn der Unsinn? 1-Wire ist ein OpenDrain Bus, ähnlich I2C. Da >>> hat ein Pull Down nichts zu suchen. >> >> Das stimmt schon so! Ich wollte ja nur testen, ob meine Lesefunktion >> überhaupt 0en lesen kann und habe einen Sensor-Pull-Down simuliert. > Richtig, das war nur ein Test ob die Funktion Funktioniert. Hätte er > jetzt wieder nur 1en gelesen wäre die Funktion fehlerhaft. Jetzt weis > man das Sie Funktioniert. > ______________________________________________________________________ ____ >> >> Bin jetzt einen Schritt weiter gekommen und kann wenigstens vom Sensor, >> welcher statt Multiplexer A am Controller hängt korrekt das Scratchpad >> auslesen. >> > > Ahja, woran lag es ? Dann wüsste ich welchen Fehler ich nicht machen > darf :-) Ich benutze jetzt eine Hilfsvariable (sende_bit) in der Fkt. write_byte_1wire. > >> jetzt rechne ich: >> >> int16_t temp=0, temp1=0; >> >> // temp ist die zusammengesetzte Temparatur (LSB + MSB) >> temp1 = ((temp * 325) / 1000); >> return temp1; >> >> temp1 ist vollkommen falsch berechnet (-27)? Hat der Controller da einen >> Overflow? >> >> Was ist an meiner Rechnung falsch? Rauskommen müsste: (375*625) /1000 = >> 234 >> was einer Temperatur von 23,4°C entspricht. > > Vielleicht ist es nur ein Tippfehler, aber in deiner Formel oben steht > 325, unten rechnest du mit 375 ? Sorry ist ein Tippfehler! temp1 = ((temp * 625) / 1000); !!! ist richtig !!! Wenn ich temp mit 625 multipliziere so überschreite ich den int16_t Zahlenbereich. Kann man dem Controller ihrgenwie sagen, daß er zum Berechnen temporär eine 32bit Variable benutzen soll und das Ergebnis in die 16bit Varible temp1 schreibt. Ich habs folgendermaßen probiert, was in die Hose ging: int16_t temp=0, temp1=0; int32_t temp3; // temp ist die zusammengesetzte Temparatur (LSB + MSB) temp3 = (temp * 625); temp1 = (temp3 / 1000); Grüsse Rick
Hi! Habs nun endlich geschafft! Jetzt funktionierts endlich mal OHNE Multiplexer. 2 Sensoren direkt an den Controller angeschlossen. Die Berechnung der Temparatur mag einem am Anfang erschrecken, ist aber getestet und funktioniert. (auch bei neg. Temparatur!) Ist an das Beispiel von Karl Heinz Buchegger angelehnt. Wie ich die Berechnung per Festkommaarithmetik hinbekomme ohne einen Overflow zu verursachen weiß ich nicht. Gruß Rick
Hast Du die Lösung von Holger probiert ? temp1 = ((temp * 325UL) / 1000); durch das "UL" wird der Compiler angewiesen den Wert als 32 Bit unsigned zu betrachten und führt daher die Berechnung als solche durch. Die Negativen Werte werden dadurch vermutlich nicht abgedeckt. Gruss Juergen PS: Ich hoffe meine DS18S20 kommen bald. Wieso müssen die auch ausgerechnet bei mir falsch geliefert werden :-(
Jürgen Sachs wrote: > Hast Du die Lösung von Holger probiert ? > temp1 = ((temp * 325UL) / 1000); > > durch das "UL" wird der Compiler angewiesen den Wert als 32 Bit unsigned > zu betrachten und führt daher die Berechnung als solche durch. > Die Negativen Werte werden dadurch vermutlich nicht abgedeckt. Sorry hab ich total übersehen! UL heißt ja unsigned long und passt daher nicht. Ich kann LONG nehmen? .... 325 ist falsch 625 ist richtig!!! >temp1 = (uint16_t)((uint32_t)((temp * 325) / 1000)); uint kann ich nicht nehmen, ich rechne ja Vorzeichenbehaftet! Ich probiers mal so: temp1 = (int16_t)((int32_t)((temp * 325) / 1000)); Grüsse Rick
>UL heißt ja unsigned long und passt daher nicht. >Ich kann LONG nehmen? Ja, lass das 'U' weg. temp1 = ((temp * 625L) / 1000);
holger wrote: >>UL heißt ja unsigned long und passt daher nicht. >>Ich kann LONG nehmen? > > Ja, lass das 'U' weg. > > temp1 = ((temp * 625L) / 1000); funktioniert ! ______________________________________________________________________ temp1 = (int16_t) ((int32_t)(temp * 625) / 1000); funktioniert nicht ______________________________________________________________________ temp1 = ((int32_t)(temp * 625) / 1000); funktioniert nicht ______________________________________________________________________ temp1 = (int32_t) ((temp * 625) / 1000); funktioniert nicht ____________________________________________________________________ Hab alles mal durchprobiert, auch im neg. Zahlenbereich. Warum der Compiler die "Anweisung" (int32_t) ignoriert weiß ich nicht. Mit temp1 = ((temp * 625L) / 1000); funktionierts aber. ThanX Holger Grüsse Rick
Erik M. wrote: > ________________________________________________________________________ > temp1 = (int16_t) ((int32_t)(temp * 625) / 1000); > > funktioniert nicht > ________________________________________________________________________ > > temp1 = ((int32_t)(temp * 625) / 1000); > > funktioniert nicht > ________________________________________________________________________ > > temp1 = (int32_t) ((temp * 625) / 1000); > > funktioniert nicht > ______________________________________________________________________ Ja, natürlich nicht. Schließlich castest du ja erst nach der Multiplikation..
Simon K. wrote: > Erik M. wrote: >> ________________________________________________________________________ >> temp1 = (int16_t) ((int32_t)(temp * 625) / 1000); >> >> funktioniert nicht >> ________________________________________________________________________ >> >> temp1 = ((int32_t)(temp * 625) / 1000); >> >> funktioniert nicht >> ________________________________________________________________________ >> >> temp1 = (int32_t) ((temp * 625) / 1000); >> >> funktioniert nicht >> ______________________________________________________________________ > > Ja, natürlich nicht. Schließlich castest du ja erst nach der > Multiplikation.. Könntest Du bitte ein paar mehr Worte darüber verlieren....ggg.... Eine Richtigstellung mit ein paar Infos vielleicht? Grüsse Rick
Ich kann mal drauf eingehen: > temp1 = (int16_t) ((int32_t)(temp * 625) / 1000); das int32_t castet das Ergebnis von temp*625 in einen 32 bit integer, aber eben erst das Ergebnis, nachdem in 16 bit gerechnet wurde... Die / 1000 Division wird also mit 32 Bit variablen durchgeführt :-) Das 625L wandelt die 625 halt in ein long (long = 32 bit auf dem AVR) um, sodass die komplette Rechnung in 32 Bit durchgeführt wird. Der korrekte Typecast würde temp1 = ((int16_t)((int32_t)temp * 625) / 1000); lauten. Das (int16_t) ist überflüssig, dürfte aber zu einem Performancegewinn führen, da die Division somit nur als 16 und nicht als 32 Bit Rechnung durchgeführt wird. Es gibt allerdings keine Gründe, die gegen den Einsatz von temp * 625L sprechen, außer eventuell eine leicht verlorene Übersicht, da ein int32_t besser ins Auge springt als ein L. Matthias
@ Erik M. (rick00) >Könntest Du bitte ein paar mehr Worte darüber verlieren....ggg.... >Eine Richtigstellung mit ein paar Infos vielleicht? [c] temp1 = ((temp * 625L) / 1000); // funktioniert ! [c] Hier wird der Compiler angewiesen, 625 als 32 Bit (L = long) Konstante aufzufassen (ohne Endung ist es eine INT Konstante, welche je nach Compiler 16 oder 32 Bit sein kann). Die Multiplikation mit temp muss also als 32x32 Bit Multiplikation durchgeführt werden, weil eine Operation IMMER nur mit Operatoren gleichen Typs ausgeführt werden kann. Kleine Operatoren werden auf grosse erweitert. Die Division ist dann auch eine 32 / 32 Bit Division. Alles paletti. [c] temp1 = (int16_t) ((int32_t)(temp * 625) / 1000); [c] Hier wirds komplizierter. zunächst wird temp*625 bearbeitet, sethe ja in Klammern. 625 wir hier als INT aufgefasst (keine Endung) und ist bei WINAVR 16 Bit. temp ist ebenfalls als 16 Bit Variable definiert, somit wird die Multiplikation als 16x16 Bit durchgeführt und erzeugt einen Überlauf. Mööööp! Das Casten nach 32 Bit erfolgt DANACH. Zu spät. [c] temp1 = ((int32_t)(temp * 625) / 1000); [c] Das selbe in Grün. [c] temp1 = (int32_t) ((temp * 625) / 1000); [c] Dito. [c] temp1 = ((int32_t)temp * 625) / 1000; [c] So sollte es auch gehen. 32 Bit Cast VOR der Multiplikation. MfG Falk
Hi! Danke für eure Antworten, jetzt wird mir einiges klar. temp1 = ( ( (int32_t) temp * 625 ) / 1000 ); funktioniert bestens temp1 = ( (int16_t) ((int32_t)temp * 625) / 1000 ); bringt keinen Performancegewinn sondern funzt NICHT. Grüsse Rick
Erik M. wrote: > Hi! > > Danke für eure Antworten, jetzt wird mir einiges klar. > > temp1 = ( ( (int32_t) temp * 625 ) / 1000 ); > > funktioniert bestens > > > temp1 = ( (int16_t) ((int32_t)temp * 625) / 1000 ); > > bringt keinen Performancegewinn sondern funzt NICHT. > Was für mich relativ klar ist. Der Compiler macht die Berechnung mit 32 Bit, "(int32_t)temp * 625)" und das Ergenbnis wird dann als 16 Bit gecastet . Hierdurch gehen ja wieder Informationen über 32768 verloren. Die weitere Berechnung erfolgt ja wieder mit 16 Bit, da alle Zahlen 16Bit sind. Ein Verschieben der ersten Klammer sollte das lösen: temp1 = (int16_t)(((int32_t)temp * 625) / 1000 ); Hier wird jetzt erst das Ergebnis gecastet, sofern ich richtig liege. Funktioniert die Berechnung so auch für den Negativen Bereich ? Dann bräuchte ich mir keinen Kopf mehr drüber zu zerbrechen und könnte das so übernehmen :-) Ich danke im Übrigen Matthias Larisch und Falk Brunner für die Richtigstellung meines Castfehlers. Manchmal hat man einfach ein Brett vor dem Kopf. Ich glaube mit Java ruiniere ich mir langsam meine C-Kenntnisse :-) Gruss Juergen
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.