Forum: Mikrocontroller und Digitale Elektronik [avrassembler] Division Problem mit Rest


von Fabian727 (Gast)


Lesenswert?

Hi,

wie der Titel schon beschreibt, versuche ich momentan als total blutiger 
Anfänger einen Dividierer zu schreiben.

Ich habe vier Register r16, r17, r18 und r19. In diesen Registern habe 
ich eine einzige Zahl gespeichert, die durch 12 dividiert werden soll. 
Das höchstwertigste Register ist r19.

Leider konnte ich bis jetzt nur Schleifen programmieren die die 
einzelnen Register dividiert haben bis eine Zahl über geblieben ist, die 
kleiner war als der Divisor.

Mein Problem ist nun, dass diese Zahl ignoriert wird, wodurch mein 
Ergebnis zu ungenau wird. Z.B.: Ist in r19 die Zahl 11 gespeichert und 
wird durch 12 dividiert, kommt 0 raus und die 11 wird weggeschmissen.

Wie kann man das nun lösen, dass die 11 weiter verwendet wird?


Vielen Dank für deine Hilfe schon im voraus,

Fabi

von Peter D. (peda)


Lesenswert?

Fabian727 schrieb:
> Wie kann man das nun lösen, dass die 11 weiter verwendet wird?

Das kommt drauf an, wie Du möchtest, daß sie weiter verwendet wird.
Wegschmeißen tust Du sie ja.


Peter

von Fabian S. (fabian727)


Lesenswert?

ja, ich würde gerne die vier register dividieren (und als eine einzige 
Zahl verwenden), quasi wäre dann der Rest vom höheren Register dann das 
9., 10., 22. etc. bit vom niedrigereren Register, aber leider kann ich 
die ja nicht einfach anhängen :D.

von Peter D. (peda)


Lesenswert?

Deine Ausführungen werden immer konfuser.

Vielleicht willst Du ja das:
Multipliziere vorher mit 10, dann hat Dein Ergebnis eine gedachte 
Nachkommastelle.


Peter

von spess53 (Gast)


Lesenswert?

Hi

>Leider konnte ich bis jetzt nur Schleifen programmieren die die
>einzelnen Register dividiert haben bis eine Zahl über geblieben ist, die
>kleiner war als der Divisor.

Willst du jetzt aufrunden? Wenn ja, dann vergleiche den Rest einfach mit 
6.

MfG Spess

von Fabian S. (fabian727)


Lesenswert?

mein Problem ergibt sich durch folgendes:

Ich habe meine clock0 in einem attiny 2313, jedesmall wenn es einen 
clockoverflow gibt, wird r16 incrementiert. Wenn r16 voll ist wird r17 
danach r18 und dann r19 erhöht.

Irgendwann kommt dann ein Interrupt, was die clock0 anhält.

Jetzt will ich nach 1/12 der gemessenen Zeit die 1. LED anschalten, nach 
einem weiteren 12tel will ich die 2. LED anschalten und so weiter.

Dafür brauch ich die Division.

Aber mit deine Idee mit Register nach Links verschieben ist eine gute 
Idee, werde ich mal weiter nachverfolgen. Allerdings problematisch, wenn 
ich im Register 0xFF geladen habe und das dann verschiebe, weil ich dann 
die obersten 1er verliere.

von L. K. (ladde)


Lesenswert?

Brauchst du wirklich 32bit Auflösung für die zu messende Zeit? In 
welchem Bereich (von - bis) liegen denn die zu messenden Zeiten?

Für 32bit ist wohl die entsprechende Dividier-Routine von elm-chan die 
einfachste Lösung:

http://elm-chan.org/docs/avrlib/div32.txt

Die könnte man sicher noch kürzen, da dein Divisor ja in ein einzelnes 
8bit-Register passt.

Wenn es nicht absolut genau sein muss, könnte man auch mit 21 
multiplizieren und dann das niederwertigste Register verwerfen. (x * 21 
/ 256 = x / 12,19...)

von Fabian S. (fabian727)


Lesenswert?

wie kommst du auf die zahl 21?

Wie groß die zeit min und max ist, hab ich mir noch nicht so viele 
Gedanken gemacht. Aber ich habe festgestellt, wenn ich einfach so 11 / 
12 teile und den rest wegschmeis, bleibt mir als ergebnis 0 über. Im 
"obersten / höchstwertigsten" Register ist das verdammt viel Zeit die 
ich wegwerfe, wodurch meine LED's zu früh angehen.

von Fabian S. (fabian727)


Lesenswert?

ich habe mir mal die vorgeschlagene 32-bit-divison angeschaut.

Leider bin ich noch blutiger anfänger (mit maximal 30 h "erfahrung")
und kann mit meinem Wissen diese Schleife noch nicht richtig deuten.

Ich habe mir erlaubt meine Kommentare noch weiter rechts hinzuschreiben.
Die bezifferten Kommentare sind fragen meinerseits, bzw versuchte 
Interpretationen, bei denen ich mein Wissen hingeschrieben habe, bei 
denen ich aber glaube, dass sie nicht richtig sind

Die weiter rechts sind einfach nur Kommentare von mir, um den 
Programmcode soweit möglich zu verstehen.
Bitte trotzdem wieder durchlesen und korrigieren.


Bitte helft mir das zu verstehen.
Und vielen dank für eure Hilfe bis hier hin.

fabi

von Fabian S. (fabian727)


Angehängte Dateien:

Lesenswert?

achja der programmcode, als anhang

von Sascha W. (sascha-w)


Lesenswert?

(1) don't care = egal !
und lc ist der Loopcounter 32 für eine 32Bit Division

(2) siehe 1

(3) PC=Programmcounter PC+6 müsste dann zu <dec lc> springen, warum hier 
keine Marken verwendet werden ??

(4) wie 3 nur das wenn lc noch nicht 0 zu <lsl var10> gesprungen wird

Sascha

von Fabian S. (fabian727)


Lesenswert?

vielen Dank für diene ekrlärung, hilft schon einiges weiter das programm 
zu verstehen

von Karl H. (kbuchegg)


Lesenswert?

Fabian Scheidig schrieb:

> Wie groß die zeit min und max ist, hab ich mir noch nicht so viele
> Gedanken gemacht. Aber ich habe festgestellt, wenn ich einfach so 11 /
> 12 teile und den rest wegschmeis, bleibt mir als ergebnis 0 über. Im
> "obersten / höchstwertigsten" Register ist das verdammt viel Zeit die
> ich wegwerfe, wodurch meine LED's zu früh angehen.

Das kommt halt auf die Zeit drauf an.
Wenn deine Register die Zeit in Millisekunden zählen, dann sind 11 
Millisekunden nicht so wahnsinnig viel Zeit.


Im übrigen. Ja natürlich. Das Problem hast du immer. Mathematiker nennen 
das das Schubladenargument: Es ist nicht möglich n Socken in m 
Schubladen zu verstauen, so dass in allen Schubladen gleich viele Socken 
drinnen sind. Es sei denn n ist ein ganzzahliges Vielfaches von m.

So ist das nun mal, wenn man mit ganzen Zahlen hantiert. Da musst du dir 
was einfallen lassen, wie du die Situation handhaben willst.

von Fabian S. (fabian727)


Lesenswert?

soweit, ich die divisions-schleife verstanden hab, ist die einfach nur 
genial und ich werde sie verwenden.

Mir ist klar, dass ich den allerletzten rest nicht verwenden kann, aber 
ich will halt den rest vom höchstwertigsten Register noch im 
2.höchstwertigsten verwenden, weil sonst einfach irre viel zeit weg 
geht.

Ich habs ausgerechnet, was für zeiten ich hab. Meine min:0,17 sec. und 
meine max: 1,7 sec.

Jetzt muss ich sie nur noch bis zum ende durch verstehen und dann für 
mich modifizieren. Vielen Dank, weitere Proleme kommen sicher bald, 
vielen Dank noch mal an alle


p.s. wo finde ich solche Schleifen?

fab

von Jobst M. (jobstens-de)


Lesenswert?

Du kannst Deine 32-Bit Zahl mit 357913941 (auch 32 Bit) multiplizieren.
Von dem 64-Bit Ergebnis schmeisst Du die unteren 32 Bit einfach weg.
Evtl. verwendest Du von den unteren 32 Bit das MSB zum Runden.


Gruß

Jobst

von Dennis H. (t1w2i3s4t5e6r)


Lesenswert?

Jobst M. schrieb:
> Du kannst Deine 32-Bit Zahl mit 357913941 (auch 32 Bit) multiplizieren.
> Von dem 64-Bit Ergebnis schmeisst Du die unteren 32 Bit einfach weg.
> Evtl. verwendest Du von den unteren 32 Bit das MSB zum Runden.

Auch wenn ich nicht der TO bin, interessiert mich dieses Thema auch 
gerade ziemlich und würde gern mal den Sinn hinter deinem geschriebenen 
verstehen wollen. Also wie kommst du auf die 357913941?


MfG Dennis

von Jobst M. (jobstens-de)


Lesenswert?

Dennis H. schrieb:
> wie kommst du auf die 357913941?

2^32 / 12

Du Multiplizierst also mit 1/12 und schmeisst die Nachkommastellen weg.


Gruß

Jobst

von Dennis H. (t1w2i3s4t5e6r)


Lesenswert?

Jobst M. schrieb:
> Dennis H. schrieb:
>> wie kommst du auf die 357913941?
>
> 2^32 / 12
>
> Du Multiplizierst also mit 1/12 und schmeisst die Nachkommastellen weg.
>
>
> Gruß
>
> Jobst

Das leuchtet sogar mir ein, das ist ja mal ein richtig interessanter 
Ansatz.

Aber du lässt da sozusagen die Nachkommastellen einfach unter den Tisch 
fallen? Also wenn ich 2^32/12 rechne, habe ich ja nach dem Komma noch 
.33333..33 stehen.

Vielen Dank für die gute Erklärung


MfG Dennis

von Jobst M. (jobstens-de)


Lesenswert?

Eine genauere Auflösung als ein LSB hast Du eben nicht. Egal, ob Du 
teilst oder multiplizierst.
Ich hatte ja auch vorgeschlagen, das MSB der unteren 32-Bit zum runden 
zu benutzen.


Gruß

Jobst

von spess53 (Gast)


Lesenswert?

Hi

Wo ist eigentlich das Problem? Du dividierst eine Zahl durch 12 und 
bekommst einen Rest von 0..11. Was willst du jetzt machen? War schon 
meine Frage hier:

Beitrag "Re: [avrassembler] Division Problem mit Rest"

MfG Spess

von Jobst M. (jobstens-de)


Lesenswert?

spess53 schrieb:
> Was willst du jetzt machen? War schon
> meine Frage hier:

Nur, daß es nun eine andere Person ist ;-)

Dennis H. schrieb:
> Auch wenn ich nicht der TO bin

;-)



Aber stimmt schon: Entweder rundest Du, schneidest ab, behältst einen 
Rest oder fügst Nachkommastellen an.



Gruß

Jobst

von Dennis H. (t1w2i3s4t5e6r)


Lesenswert?

Jobst M. schrieb:
> Eine genauere Auflösung als ein LSB hast Du eben nicht. Egal, ob Du
> teilst oder multiplizierst.

Stimmt schon, und bei einer 32Bit Zahl sollte das nicht so ganz ins 
Gewicht fallen. Ich glaube, in den seltensten Fällen benötigt man so 
genaue Berechnungen, schwierig wirds bloß, wenn man mit dem errechneten 
Wert noch lange weiter rechnet, weil sich dann der Fehler schnell 
potenziert. Aber trotzdem vielen Dank für die ehrlich gesagt sehr 
elegante Lösung, die gefällt mir richtig gut.


MfG Dennis

von fabian727 (Gast)


Lesenswert?

Auch von mir vielen dank an alle, die mir weiter geholfen haben.

Mein Problem war, dass ich vier Register durch 12 dividiert hatte und 
somit mir 4 mal ein Rest zwischen 0 und 11 übergeblieben ist. Wobei ich 
davon die "oberen oder höherwertigeren" Reste hätte noch verwenden 
können. Ich wusste aber nicht wie.
Mit der 32-Bit-Division, die oben als Textanhang dabei ist, hat sich 
mein problem gelöst und der letzte Rest kann einfach verfallen.

Vielen Dank noch einmal an alle,


fabi

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.