mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Kopmlizierte Rechnung in Assembler (auf Bitebene)


Autor: Jürgen Hems (misteret)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

ich habe noch nicht so viel Erfahrung mit Assamblerprogrammierung. 
Leider gibt es keine Zahlentypen wie float oder int. Rechnen muss ich 
jetzt auf Bitebene. Ich habe hier eine Formel:

T sind Temperaturwerte also ich denke so 0 bis 30 Celsius. Es soll nur 
Raumtemperatur gemessen werden, fürs erste.

Wieviel Speicher muss ich denn für T_neu reservieren, wenn ich durch 
diese Rechnung zum Beispiel einen Wert von 20,5 Grad errechnen will. Ich 
habe mir überlegt, dass ich 16 Bit benötige. Dann Rechne ich z.B einen 
Wert von 305 Grad aus und teile diesen durch 10? Hmm mit diesem auf 
Bitebende rechnen komme ich grad nicht so zurecht.

Autor: Gast0815 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi
ich denke, man müsste zuerst mal wissen, welche
Größe deine Register haben(8, 16, 32 Bit?).
Nenn am besten den Controller.

Außerdem muss man wissen, welche Werte deine T's
annehmen können und wie genau, also wieviele
Stellen vor und hinter dem Komma benötigt werden.

Erst dann kann man konkretere Aussagen machen.

Gruß

Autor: Jürgen Hems (misteret)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es handelt sich um einen 8 Bit Mikrocontroller. Um den SAB 80C517A.

Also wie man Variablen in den Registerbänken definiert, habe ich schon 
verstanden. Ich muss jetzt an der Uni einen Temeratursensor auswerten. 
Ich bekomme von einem Treiber Werte Ti und Tp geliefert, daraus lässt 
sich
 berechnen. Das ist einfach nur ein Wert, den ich vom Sensor bekomme. 
Daraus lässt sich nach untenstehender Formel T_neu berechnen.

Ich benötige 256 Werte und soll daraus dann den Mittelwert bilden. Wie 
das mit den Interrupts funktioniert, ist alles kein Problem. Ich habe 
schon bisschen Erfahrung in Mikrocontrollerprogrammierung mit C.

So, jedenfalls habe ich dann die Formel für die Temperatur

Die Temperatur soll mit einer Nachkommastelle ausgegeben werden.


Hoffe das war jetzt etwas ausführlicher und ich bekomme Hilfe :-) Ich 
brauche nur paar Anreize, wie ich an die Rechnung auf Bitebene 
herangehe.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie wär's mit

evtl noch Erweitern, also

wenn's Nachkommastellen braucht.

Johann

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jürgen Hems schrieb:
> Hallo
>
> ich habe noch nicht so viel Erfahrung mit Assamblerprogrammierung.
> Leider gibt es keine Zahlentypen wie float oder int. Rechnen muss ich
> jetzt auf Bitebene.

Du rechnest in Register (wie breit sind die?)
Konzeptionell sind das nach wie vor Integer.

> Wert von 305 Grad aus und teile diesen durch 10?

Ein Skalierfaktor von 10 wird dir nicht reichen.
Probieren wirs einfach mal durch

Du hast ein Tv von 27

Jetzt nehmen wir alle Werte einfach mal 10
Aus den 27 werden so 270
Weiters wird aus den 0.32 -> 3.2 also 3
Aus den 0.0047 werden 0.047, also 0

Du rechnest daher   ( 270 - 3 ) / 0     Bumm! geht nicht

Alles mal 100

27 -> 2700;  0.32 -> 32;  0.0047 -> 0.47, also 0

    ( 2700 - 32 ) / 0    Bumm! geht immer noch nicht

Alles mal 1000

27 -> 27000;  0.32 -> 320; 0.0047 -> 4.7, also 4

    ( 27000 - 320 ) / 4     Das geht.
raus kommt 6670. Rechnest du deine ursprüngliche Formel mal mit 27 und 
dem Taschenrechner durch, so kriegst du  ( 27 - 0.32 ) / 0.0047 = 5676

Das Ergebnis ist also noch nicht besonders genau. Da fällt noch zuviel 
unter den Tisch.

Alles mal 10000

27 -> 270000; 0.32 -> 3200; 0.0047 -> 47

     ( 270000 - 3200 ) / 47  = 5676

Bingo. Das wars. Blöd ist (wahrscheinlich) nur, dass 270000 zu gross für 
eine 16 Bit Zahl ist. Da müsste man auf 32 Bit Arithmetik ausweichen.

Autor: Jürgen Hems (misteret)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Idee von Johann L. finde ich gut.

Wenn ich durch 2^8 teile, kann ich ja einfach die Bits 3 mal nach rechts 
schieben. Klingt gut.

Hm in dem Controller gibt es glaube ich 2 Zusatzregister mit 16 Bits. 
Okay, ich werde dann mal los machen zum Praktikum ;-) Mal sehen wie weit 
ich komme.
Habe aber noch 2 Wochen Zeit, es fertig zu bekommen. Denke, dass ich 
mich nochmal melden werde, wenn es Probleme gibt.


Aber eine Frage habe ich noch:

Da bekomme ich ja einen Kommawert für T_neu heraus. Wie berechne ich 
diesen auf Bitebene? Das ist noch mein größtes Problem
Also Tv ist auch ein Kommawert, variiert zwischen 0 und 1.

Danke!!

Autor: PJ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wenn ich durch 2^8 teile, kann ich ja einfach die Bits 3 mal nach rechts
schieben.

Nee, so nur, wenn Du durch 8 teilst.

Bei 2^8 einfach das niegrigstwertige Byte weglassen.

Autor: Andreas W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nur so als tipp:
achte mal auf das was Johann L. (gjlayde) geschrieben hat.

1/0.0047 ist 212.765957
Damit kann man super multiplizieren. und du lässt schonmal diese doofe 
division in ASM weg.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Es handelt sich um einen 8 Bit Mikrocontroller. Um den SAB 80C517A.

Das scheißteil hatten wir im Praktikum auch. Man hab ich mir die AVRs da 
immer gewünscht..


>enn ich durch 2^8 teile, kann ich ja einfach die Bits 3 mal nach rechts
>schieben. Klingt gut.

Nein. Wenn du durch 2^8=256 teilst, kannst du einfach das Lowbyte 
ignorieren.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jürgen Hems schrieb:

> Da bekomme ich ja einen Kommawert für T_neu heraus. Wie berechne ich
> diesen auf Bitebene? Das ist noch mein größtes Problem
> Also Tv ist auch ein Kommawert, variiert zwischen 0 und 1.

Indem du dich entscheidest wieviele Kommastellen du haben willst und 
entsprechend alle Zahlen mal 10 oder mal 100 oder auch mal 8 oder mal 16 
oder mal 64 oder 256 nimmst.

Musst halt probieren, welcher Faktor sich noch ausgeht, dass die 
komplette Berechnung im 16 Bit Zahlenraum bleibt.

Wenn du beispielweise 2.12 Euro plus 3.58 Euro rechnen willst und du 
willst das ganze ohne Kommazahlen berechnen, dann rechnest du nicht in 
Euro sondern in Cent
   2.12 Euro sind 212 Cent
   3.58 Euro sind 358 Cent

Zusammen macht as 570 Cent oder, wenn man zu Anzeigezwecke an die 2.te 
Stelle ein Komma einschmuggelt 5.70 Euro

Wenn du alle Zahlen mal 10 oder 100 oder 1000 nimmst hast du den 
Vorteil, dass du bei der Anzeige nur an der richtigen Stelle ein Komma 
einschmuggeln musst. Aber unter Umständen kann man sich mit einem Faktor 
der eine 2-er Potenz ist einiges an Rechenarbeit in der eigentlichen 
Berechnung ersparen (wie zb oben, wo durch 2^8 dividiert wird. Durch 2^8 
zu dividieren ist simpel, einfach das Low-Byte weglassen)

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Aber unter Umständen kann man sich mit einem Faktor
>der eine 2-er Potenz ist einiges an Rechenarbeit in der eigentlichen
>Berechnung ersparen


Genau. Und vor allen auch diese Modulo 10 Rechnung beim Umwandeln der 
Zahl in einen Anzeigestring:


Beitrag "Re: Problem mit ADC an mega128"

Autor: Jens G. (jensig)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei Division mußt Du immer damit rechnen, das bis zu unendlich viele 
Nachkommastellen rauskommen (1/3=0.3333333..... . .  .  .    .     .)
Du mußt dich also entscheiden, wieviele Du davon noch behalten willst, 
sprich welche Genauigkeit Du brauchst. Entsprechend mußt Du deine 
Bit-Breite im Ziel einrichten.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier mal eine SMT160-Auswertung mit Festkommaarithmetik:
/*
  DC = 0.32 + 0.0047 * t

  t = high / 0.047 / period - 0.32 / 0.0047
*/

#define TEMP_RESOLUTION 0.01                    // 0.01°C
#define TEMP_SHIFT      4                       // avoid 32 bit overflow

#define TEMP_GAIN       (u32)(1/0.0047 / (1<<TEMP_SHIFT) / TEMP_RESOLUTION + 0.5)
#define TEMP_OFFSET     (u32)(0.32 / 0.0047 / TEMP_RESOLUTION)

    temp = smt160.hi * TEMP_GAIN / (smt160.period>>TEMP_SHIFT) - TEMP_OFFSET;

Dazu brauchst Du die Grundrechenarten in 32Bit.
Irgendwo hab ich was für den 8051 rumliegen.


Peter

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jürgen Hems schrieb:

> Da bekomme ich ja einen Kommawert für T_neu heraus. Wie berechne ich
> diesen auf Bitebene? Das ist noch mein größtes Problem

Wie berechnest di 1.3*1.1?

Richtig: Du berechnest 143=13*11 und schiebst im Ergebnis das Komma um 2 
Stellen nach Links: 1.3*1.1=1.43. Ganze Zahlen multiplizieren kannst du, 
und Komma verschieben ist Magie...

Johann

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.