10 * 10 Bit multiplizieren

Gast #1947846
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?
#1947883
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.
Gast #1948114
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).
Gast #1948255
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.
#1948403
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.
Gast #1948477
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!
Gast #1948503
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
#1948684
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.
Gast #1948686
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.
Gast #1949231
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.
Gast #1949563
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.
Gast #1949950
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren