Hallo, ich habe einen 10Bit Wert vom Analog-Digitalwandeler. Dieser ist in einer unsigned short integer Variable gespeichert. µC ist der ATtiny 25 Der ADC-Wert ist rechtbündig. Jetzt brauche ich für eine Berechnung das Quadrat des ADC-Wertes. Eine 10 * 10 Bit Multiplikation würde doch ein 20 Bit Ergebnis erzeugen. Also müsste ich das in einer unsigned long integer Variablen speichern. Wie kann ich das pogrammieren?
Auf einem 20-Bit-Prozessor mit dem dortigen MUL-Befehl. Ansonsten: erst mal verraten, womit du arbeitest?
Klaus Wachtler schrieb: > Auf einem 20-Bit-Prozessor mit dem dortigen MUL-Befehl. > Ich kenne keinen 20-Bit-Prozessor ;-) > Ansonsten: erst mal verraten, womit du arbeitest? AVR-Studio 4
Wenn du die ganzen 20 Bits des Ergebnisses benötigst, dann (uint32_t)x * (uint32_t)y
Einfach Produkt als uint32_t deklarieren, der Compiler kümmert sich um das Übrige. Bib zwar nicht 100% sicher :/ ev. Faktor zu uint32_t casten.
compilator schrieb: > Einfach Produkt als uint32_t deklarieren Nicht empfehlenswert. Auf einer 16-Bit Maschine ist uint32_t product = 10000 * 10000; undefiniert. Ein Operator richtet sich nur nach dem Typ der Operanden, nicht nach dem Typ links vom "=".
compilator schrieb: > Einfach Produkt als uint32_t deklarieren, der Compiler kümmert sich um > das Übrige. Bib zwar nicht 100% sicher :/ ev. Faktor zu uint32_t casten. Falls du sowas meinst:
1 | uint16_t x = ..., y = ...; |
2 | uint32_t ergebnis; |
3 | |
4 | ergebnis = x * y; |
, dann nein: Der Compiler kümmert sich nicht vor der Multiplikation um das Erweitern auf 32 Bit, sondern erst danach zur Zuweisung. Richtig wäre:
1 | uint16_t x = ..., y = ...; |
2 | uint32_t ergebnis; |
3 | |
4 | ergebnis = (uint32_t)x * y; |
oder
1 | uint16_t x = ..., y = ...; |
2 | uint32_t ergebnis; |
3 | |
4 | ergebnis = x * (uint32_t)y; |
oder die Version von A.K.
A. K. schrieb: > (uint32_t)x * (uint32_t)y Würde der Compiler bei dieser Schreibweise eine 32 * 32 Bit Multiplikation ausführen und nur die unteren 32 Bit des Ergebnisses behalten?
Bastelphilipp schrieb: > A. K. schrieb: >> (uint32_t)x * (uint32_t)y > > Würde der Compiler bei dieser Schreibweise eine 32 * 32 Bit > Multiplikation ausführen und nur die unteren 32 Bit des Ergebnisses > behalten? Ja, würde er.
Genauer gesagt: er würde aus 32Bit*32Bit nur 32 Bit berechnen (also nicht 32*32->64 und dann abschneiden).
>> Würde der Compiler bei dieser Schreibweise eine 32 * 32 Bit >> Multiplikation ausführen und nur die unteren 32 Bit des Ergebnisses >> behalten? > Ja, würde er. Nein würde er nicht: die oberen 32-Bit werden erst gar nicht berechnet (siehe Assemblertext einer 32-Bit Multiplikation).
@Klaus und @Martin Jetzt werdet ihr aber spitzfindig :-) Ausser der erhöhten Rechenzeit ist das Ergebnis nicht von dem von Bastelphillip angedachten Mechanismus zu unterscheiden. Und selbst bei dem könnte man argumentieren, dass er eigentlich das Richtige gemeint hat.
20 Bit Prozessoren kenne ich auch nicht, es gibt (bzw. gab) aber welche mit 30 Bits. In ASM könnte man auch die Multiplication gleich 10 Bit * 16 Bit -> 24 Bits programmieren. Das Ergebnis dann als 3 Bytes. Das wäre von der Ausführung einiges schneller.
Karl heinz Buchegger schrieb: > @Klaus und @Martin > Jetzt werdet ihr aber spitzfindig :-) Ich wollte dich ja auch nicht kritisieren, sondern es nur etwas klarer präzisieren (weil ich mir schon dachte, daß es sonst gleich als falsch kritisiert werden würde, was es meiner Meinung ja nicht war). Hat nur nichts geholfen :-(
ulrich schrieb: > 20 Bit Prozessoren kenne ich auch nicht, es gibt (bzw. gab) aber welche > mit 30 Bits. Ich auch nicht, aber hatte ja nicht gesagt, welchen er hat. Deshalb habe ich der Einfachheit mal 20 angenommen :-)
Bastelphilipp schrieb: > µC ist der ATtiny 25 Der ADC-Wert ist rechtbündig. Klaus Wachtler schrieb: > ulrich schrieb: >> 20 Bit Prozessoren kenne ich auch nicht, es gibt (bzw. gab) aber welche >> mit 30 Bits. > > Ich auch nicht, aber hatte ja nicht gesagt, welchen er hat. Wie meinen?
Ich kenne auch keinen Prozessor mit 20 Bit. Weil im OP aber nicht stand, welchen Rechner er hat und ich deshalb nicht wusste, ob er einen der mir bekannten mit 8, 16, 32, 40, 48 oder 64 Bit hat, hätte ich eh falsch geraten. Dann konnte ich auch genausogut einen mit 20 Bit annehmen.
Klaus Wachtler schrieb: > Weil im OP aber nicht stand, welchen Rechner er hat und ich Also nochmal: Bastelphilipp schrieb: > µC ist der ATtiny 25 Der ADC-Wert ist rechtbündig. ^^^^^^^^^
ok, jetzt wo du darauf bestehst, sehe ich es auch endlich, sorry. Ich dachte das mit dem tiny wäre erst später gekommen. "Ich bin nicht dümmer als andere, nur langsamer."
ulrich schrieb: > In ASM könnte man auch die Multiplication gleich 10 Bit * 16 Bit -> 24 > Bits programmieren. Das Ergebnis dann als 3 Bytes. Das wäre von der > Ausführung einiges schneller. In ASM könnte man Wer ist man? Könntest du eventuel die in C einbindbare ASM Funktion
1 | unsigned long int quad_10_10_20(unsigned short int) |
programmieren? Ich würde mich sehr freuen!
wozu soll sich jemand die Mühe machen, wenn der Compiler 16*16->32 kann? Siehe A.K.: Beitrag "Re: 10 * 10 Bit multiplizieren"
Klaus Wachtler schrieb: > wozu soll sich jemand die Mühe machen, wenn der Compiler 16*16->32 kann? weil der Compiler eine zeitaufwendige 32*32->64 Multiplokation macht und die oberen 32 Bit wegwirft. Das dauer auf einem 8-Bit µC (ATtiny 25) ohne MUL Befehl mindestens ein paar hundert Taktzyklen!
Hi >Könntest du eventuel die in C einbindbare ASM Funktion >unsigned long int quad_10_10_20(unsigned short int) >rogrammieren? Ich würde mich sehr freuen! Wenn du die Anbindung an C selbst machst kannst du die 10 Assemblerzeilen für eine Multiplikation 16Bit*16Bit=24Bit auf einem ATMega von mir haben. MfG Spess
Bastelphilipp schrieb: > Klaus Wachtler schrieb: >> wozu soll sich jemand die Mühe machen, wenn der Compiler 16*16->32 kann? > > weil der Compiler eine zeitaufwendige 32*32->64 Multiplokation macht und > die oberen 32 Bit wegwirft. Seit wann das? Das hatten wir doch eben schon diskutiert.
Bastelphilipp schrieb: > mindestens ein paar hundert Taktzyklen! Wie schnell hättest du es denn gerne?
Wobei sich dann ja auch noch die Frage erhebt, ob man überhaupt 10*10 Bit rechnen muss, oder obs nicht 8 * 8 Bit auch tut. Was berechnest du denn eigentlich? Irgendwie habe ich gerade das Gefühl, wir erleben gerade die µC-Version von: Mein Taschenrechner spuckt 10 Nachkommastellen aus, also geb ich die auch an, egal ob das Sinn macht oder nicht.
Immhin macht der Compiler da eine 32 Bit x 32 Bit -> 32 Bit Multiplikation. Wenn man nur die wirklich benötigten Bits berechnet kann das schon mal 5-10 mal schneller gehen. Ließe sich sicher machen. Den ASM code findet man z.B. in der Atmel Appl Note 200. Müsste man nur noch in inline ASM umsetzen. Alternativ einen µC mit MUL-Befehl nehmen, dann ist auch die 32x32 Multiplikation nicht so langsam. Ich hätte aber ein paar zweifel daran dass man wirlich das Quadrat des AD Wertes braucht. Vermutlich sollte man da vorher noch erstmal 512 oder was ähnliches von abziehen.
Hi >> Bastelphilipp schrieb: >>> mindestens ein paar hundert Taktzyklen! >> Wie schnell hättest du es denn gerne? Der Name von Bastelphilipp scheint Programm zu sein.
Assemblerroutinen gibts hier: http://www.mikrocontroller.net/articles/AVR_Arithmetik#24_Bit_.2A_24_Bit http://avr-asm.tripod.com/math32x.html -> "MUL32" Multiply Unsigned Rd64 = Rd32 * Rr32 http://elm-chan.org/cc_e.html ->AVR assembler libraries - 16bit x 16bit multiply(signed/unsigned)
Hallo, ich habe mal vor einiger Zeit mehrere Inline-Assembler Multiplikations-Funktionen geschrieben. Es sind da inbesondere spezielle Multiplikationen, wie 8x16bit und auch 16x16->32bit vorhanden. Siehe hier: Beitrag "GCC Inline Assembler Multiplikationen" Gruß Dirk
ulrich schrieb: > Ich hätte aber ein paar zweifel daran dass man wirlich das Quadrat des > AD Wertes braucht. Da ist ein doppelt isoliertes Gefäß mit einem Heizwiderstand drin. Der Heizwiderstand ist aus einer Legierung ohne Temperaturabhängigkeit. Die Spannung am Heizwiderstand wird 1800 mal pro Sekunde gemessen. Heizleistung ist U^2 / R. Dies wird aufsummiert. Wenn eine vorher eingestellte Wärmeenergie erreicht ist, wird die Heizung abgeschaltet.
Da der Widerstand ja temperaturunabhängig sein soll, würde doch eine stabilisierte Spannung mit definierter Einschaltdauer aufs selbe Ergebnis kommen?
Gregor B. schrieb: > Da der Widerstand ja temperaturunabhängig sein soll, würde doch eine > stabilisierte Spannung mit definierter Einschaltdauer aufs selbe > Ergebnis kommen? Ja, das war der Ausgangspunkt meiner Entwicklung. Aber eine Stabilisierung der Spannung auf 0,1% ist zu aufwendig und verbraucht zuviel Verlustleistung. Deshalb habe ich mich jetzt für ein "smart Concept" entschieden, das auf eine 20cm^2 Platine passt und einfach einen kleinen ATtiny ein bischen rechnen lässt.
Man benötigt dann aber auch eine gute Ref. für den AD Wandler. Die chip-interne reicht da eher nicht. Wenn man nur 2000 mal die Sekunde misst, hat der µC doch relativ viel Zeit für die Berechnungen. Mit 2-4 MHz an Takt sollte das reichen, auch mit 32 Bit Werten. Sonst halt die Inline ASM routine für 16x16 -> 32 Bits. Damit sollte es auch bei 1 MHz noch reichen. Meine Prefferenz wäre da aber eine grobe Stabilisierung und ein langsamerer aber genauerer AD Wandler. Damit es am Ende auch hinkommt dann die Zeit berechnen unter der Annahmen von wenig Drift.
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.