Forum: Mikrocontroller und Digitale Elektronik 10 * 10 Bit multiplizieren


von Bastelphilipp (Gast)


Lesenswert?

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?

von Klaus W. (mfgkw)


Lesenswert?

Auf einem 20-Bit-Prozessor mit dem dortigen MUL-Befehl.

Ansonsten: erst mal verraten, womit du arbeitest?

von Bastelphilipp (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

Wenn du die ganzen 20 Bits des Ergebnisses benötigst, dann
  (uint32_t)x * (uint32_t)y

von compilator (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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 "=".

von Klaus W. (mfgkw)


Lesenswert?

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.

von Bastelphilipp (Gast)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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.

von Klaus W. (mfgkw)


Lesenswert?

Genauer gesagt: er würde aus 32Bit*32Bit nur 32 Bit berechnen
(also nicht 32*32->64 und dann abschneiden).

von Martin (Gast)


Lesenswert?

>> 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).

von Karl H. (kbuchegg)


Lesenswert?

@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.

von ulrich (Gast)


Lesenswert?

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.

von Klaus W. (mfgkw)


Lesenswert?

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 :-(

von Klaus W. (mfgkw)


Lesenswert?

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 :-)

von Rolf Magnus (Gast)


Lesenswert?

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?

von Klaus W. (mfgkw)


Lesenswert?

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.

von Rolf Magnus (Gast)


Lesenswert?

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.
             ^^^^^^^^^

von Klaus W. (mfgkw)


Lesenswert?

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."

von Bastelphilipp (Gast)


Lesenswert?

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!

von Klaus W. (mfgkw)


Lesenswert?

wozu soll sich jemand die Mühe machen, wenn der Compiler 16*16->32 kann?
Siehe A.K.: Beitrag "Re: 10 * 10 Bit multiplizieren"

von Bastelphilipp (Gast)


Lesenswert?

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!

von Spess53 (Gast)


Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?

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.

von Assembler Amateur (Gast)


Lesenswert?

Bastelphilipp schrieb:
> mindestens ein paar hundert Taktzyklen!

Wie schnell hättest du es denn gerne?

von Karl H. (kbuchegg)


Lesenswert?

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.

von ulrich (Gast)


Lesenswert?

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.

von Spess53 (Gast)


Lesenswert?

Hi

>> Bastelphilipp schrieb:
>>> mindestens ein paar hundert Taktzyklen!
>> Wie schnell hättest du es denn gerne?

Der Name von Bastelphilipp scheint Programm zu sein.

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

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)

von Dirk S. (disc)


Lesenswert?

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

von Bastelphilipp (Gast)


Lesenswert?

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.

von Gregor B. (gregor54321)


Lesenswert?

Da der Widerstand ja temperaturunabhängig sein soll, würde doch eine 
stabilisierte Spannung mit definierter Einschaltdauer aufs selbe 
Ergebnis kommen?

von Bastelphilipp (Gast)


Lesenswert?

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.

von ulrich (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.