Zeitschleifen, Zeit berechen
-
Hallo, ich arbeite mit einem A51-Simulator, der auf 12mhz Takt läuft.
Ich habe vor Zeitpausen zu programmieren,
soweit klappt es auchres: MOV R0,#0Fh MOV R1,#0Fh start: MOV P1,#0FFH LCALL count1 MOV P1,#00H LJMP RES count1: DJNZ R0,count2 RET count2: DJNZ R1,count2 LJMP count1
mit DJNZ kann ich das Ding Runterzählen lassen, der Befehl braucht 2 Taktzyklen,
wie kann ich berechnen wieviel befehle dieser Sorte ich für genau 10 sec bei 12mhz brauche?
-
mit DJNZ kann ich das Ding Runterzählen lassen, der Befehl braucht 2 Taktzyklen,
wie kann ich berechnen wieviel befehle dieser Sorte ich für genau 10 sec bei 12mhz brauche?12MHz heißt 12000000 Takte pro Sekunde.
Ein DJNZ braucht 2 Takte.
Also 12MHz heißt 12000000/2 = 6000000 DJNZ pro Sekunde.
In 10 Sekunden also 60000000 DJNZ.
-
So, hab ich anfangs auch gerechnet!
Aber seltsamerweiseres: 0000| MOV R0,#0FFh 0002| MOV R1,#0FFh start: 0004| MOV P1,#0FFH 0007| LCALL count1 000A| MOV P1,#00H 000D| LJMP RES 0010| count1: DJNZ R0,count2 0012| RET 0013| count2: DJNZ R1,count2 0015| LJMP count1
hab ich jetzt in R0 und R1 0FFh reingeschrieben, d.h ansich müsste meine
Schleife 255(*2) * 255(*2) ergo 250.000 Taktzyklen lang sein.
Sollte also in ein paar ms zu schaffen sein.
Aber anscheinen bekommt P1 bei 500ms nicht sein 00H
-
Meine Rechnung sagt
255*256*2.
255*256*2=130560
130560/12000000=10ms
Ja, es sollten 10 Millisekunden sein sein.Was da mit dem P1 los ist, keine Ahnung.
-
Irgendwie mag ich res nicht. Kann die Zeitschleife, dei 10ms wartet, nicht so heißen und genau nur das machen?
wait10ms: 0010| MOV R0,234 //ungefähr 10ms, man kanns auch genauer rechnen oder messen 0012| MOV R1,#00h wait10ms_outerloop: //MOV R1,#00h hier nicht nötig, da das das Ergebnis der innerloop auch ist wait10ms_innerloop: 0014| DJNZ R1,wait10ms_innerloop 0016| DJNZ R0,wait10ms_outerloop 0018| RET
12000000/100/2/256=234
-
So, vllt klappts nun
ich hab jetzt das ASM Programm:res: MOV R0,#0FFh MOV R1,#0FFh MOV R2,#0FFh start: LCALL count1 MOV P1,#0FFH LCALL count1 MOV P1,#00H LCALL count1 LJMP RES count1: DJNZ R0,count2 RET count2: DJNZ R1,count3 RET count3: DJNZ R2,count3 LJMP count1
also ich habe jetzt 255*255*255 *2 = 33162750/12*10^6 ~ 3Sec und ich habe sie 2 mal sollte dann also 5 sec dauern?
ist meine Rechnung nun korrekt?
-
könntest du mir sowas evtl. noch für eine 10sec schleife schreib mit genauer kommentierung und Rechnung mit Beschreibunng das wäre echt genial und ich könnte mich gut für eine Klausur vorbereiten,
Danke
-
sero1991 schrieb:
könntest du mir sowas evtl. noch für eine 10sec schleife schreib mit genauer kommentierung und Rechnung mit Beschreibunng das wäre echt genial und ich könnte mich gut für eine Klausur vorbereiten,
DankeUngefähr 10s oder haargenau 10s?
Für haargenau müßte ich auch wissen, wieviel jeder Befehl kostet.
Ich mache mal nur ungefähr. Der Quartz hat vermutlich eh 1% Abweichung.Und ich zerlege in Teilprobleme.
Ich rate mal, daß so ein MOV 3 Takte braucht.
MOV R0,#00 wait_r0_loop: DJNZ R0,wait_r0_loop
Braucht wie lange?
3+2*256 Takte = 515 Takte
MOV R1,#00 wait_r1_loop: MOV R0,#00 wait_r0_loop: DJNZ R0,wait_r0_loop DJNZ R1,wait_r1_loop
braucht wieviele Takte?
3+((3+2*256)+2)*256 Takte = 132355 Takte.Falls soweit alles klar ist, schaffste auch den ganzen Rest.
Zum Beispiel wäre dann
MOV R1,#00 MOV R0,#00 wait_r1_loop: wait_r0_loop: DJNZ R0,wait_r0_loop DJNZ R1,wait_r1_loop
3+3+(2*256+2)*256 Takte = 131590 Takte.
(Sowas nennt man "Zeitschleifen optimieren" und dafür wird man normalerweise gesteinigt.)
Ich mach mit der unoptimierten Schleife weiter.
MOV R1,#00 wait_r1_loop: MOV R0,#00 wait_r0_loop: DJNZ R0,wait_r0_loop DJNZ R1,wait_r1_loop
braucht wieviele Takte?
3+((3+2*256)+2)*256 Takte = 132355 Takte.Ich will 120000000 Takte abfackeln.
120000000/132355=906,65256318235049677005024366288
Jetzt kann ich die nächste Schleife nicht einfach auch 256-mal laufen lassen.
906/4=226. Ich könnte die R2-Schleife 226 mal laufen lassen und die R3-Schleife 4-mal.
Oder ich bin saucool und mache die R3-Schleife so, daß sie ungefähr was glattes ist. 1s geht doch.12000000/132355=90,665256318235049677005024366288
Runden wir mal nicht auf 91, sondern lassen 90.MOV R2,90 //ka, wie man Dezimalzahlen reinschreibt. wait_r2_loop: MOV R1,#00 wait_r1_loop: MOV R0,#00 wait_r0_loop: DJNZ R0,wait_r0_loop DJNZ R1,wait_r1_loop DJNZ R2,wait_r2_loop
braucht wieviele Takte?
3+(3+((3+2*256)+2)*256+2)*90 Takte = 11912133 Takte. Fast 1s.Das wird jetzt gehübscht.
wait_1sekunde: MOV R2,90 //ka, wie man Dezimalzahlen reinschreibt. wait_r2_loop: MOV R1,#00 wait_r1_loop: MOV R0,#00 wait_r0_loop: DJNZ R0,wait_r0_loop DJNZ R1,wait_r1_loop DJNZ R2,wait_r2_loop RET
Hahaha, ich bin so geil!
Jetzt kann jeder eine Sekunde warten, wenn er Bock hat. Aber R0, R1 und R2 darf er nicht selber verwenden, wenn er wait_1sekunde aufruft.
wait_1sekunde: MOV R2,90 //ka, wie man Dezimalzahlen reinschreibt. wait_r2_loop: MOV R1,#00 wait_r1_loop: MOV R0,#00 wait_r0_loop: DJNZ R0,wait_r0_loop DJNZ R1,wait_r1_loop DJNZ R2,wait_r2_loop RET wait_10sekunden: MOV R3,10 wait_10sekunden_loop: LCALL wait_1sekunde DJNZ R3,wait_10sekunden_loop RET
Ich habe die 60 deswegen abgrunden, damit man wenn man Lust hat, noch Zusatzzeit dabeifummeln kann (nicht Klausurrelevant):
wait_1sekunde: MOV R2,90 //ka, wie man Dezimalzahlen reinschreibt. wait_r2_loop: MOV R1,#00 wait_r1_loop: MOV R0,#00 fummelpummel1: AND R0,R0,R0 //Annahme, ein AND kostet einen Takt AND R0,R0,R0 //Annahme, ein AND kostet einen Takt AND R0,R0,R0 //Annahme, ein AND kostet einen Takt AND R0,R0,R0 //Annahme, ein AND kostet einen Takt AND R0,R0,R0 //Annahme, ein AND kostet einen Takt wait_r0_loop: DJNZ R0,wait_r0_loop DJNZ R1,wait_r1_loop DJNZ R2,wait_r2_loop RET wait_10sekunden: MOV R3,10 wait_10sekunden_loop: LCALL wait_1sekunde DJNZ R3,wait_10sekunden_loop RET
3+(3+((3+1+1+1+1+1+2*256))*256+2)*90 = 11981253
Ok, schon recht genau.Ich mache was viel genaueres gleich.
-
Tja, in C++ bin ich schneller.
#include <iostream> #include <cmath> using namespace::std; int main() { int ziel=12000000-13;//Annahme, FCALL und RET braucht 13 Takte int best=ziel; for(int a=0; a<=256; ++a) { for(int b=0; b<=256; ++b) { for(int c=0; c<=256; ++c) { int takte=3+(3+((3+2*c)+2)*b+2)*a; int fehler=abs(takte-ziel); if(fehler<best){ best=fehler; cout<<a<<' '<<b<<' '<<c<<' '<<fehler<<'\n'; } } } } }
179 242 136 3
Mitwait_1sekunde: MOV R2,179 //ka, wie man Dezimalzahlen reinschreibt. wait_r2_loop: MOV R1,242 wait_r1_loop: MOV R0,136 wait_r0_loop: DJNZ R0,wait_r0_loop DJNZ R1,wait_r1_loop DJNZ R2,wait_r2_loop RET
kommt man inclusive Aufruf auf 3 Takte genau an eine Sekunde ran. Also viel genauer als der Quartz. Mit drei Fummelpummel-ANDs auch glatt. Gibt es eigentlich außer dem C-64 weitere Rechner mit atomuhrgenauem Takt?
Außerdem sind das von mir nur theoretische Überlegungen, ich habe noch nie von dem A51 gehört. Wie plausibel das ist, mußt Du selber rausfinden.
-
Hallo,
start: wait_1sekunde: 0000| MOV R2,#179 ;ka, wie man Dezimalzahlen reinschreibt. wait_rzwo_loop: 0002| MOV R1,#242 wait_reins_loop: 0004| MOV R0,#136 wait_rO_loop: 0006| DJNZ R0,wait_rO_loop 0008| DJNZ R1,wait_reins_loop 000A| DJNZ R2,wait_rzwo_loop 000C| MOV P1,#00H
Die Hier passt fast Perfekt(braucht 12sec) , leider komm ic nicht drauf, wie man diese Werte berechnet
-
dasklappt schrieb:
Hallo,
start: wait_1sekunde: 0000| MOV R2,#179 ;ka, wie man Dezimalzahlen reinschreibt. wait_rzwo_loop: 0002| MOV R1,#242 wait_reins_loop: 0004| MOV R0,#136 wait_rO_loop: 0006| DJNZ R0,wait_rO_loop 0008| DJNZ R1,wait_reins_loop 000A| DJNZ R2,wait_rzwo_loop 000C| MOV P1,#00H
Die Hier passt fast Perfekt(braucht 12sec) , leider komm ic nicht drauf, wie man diese Werte berechnet
Du meinst, Du kommst nicht mathematisch drauf, wie man a, b und c berechnet, wenn man
12000000=3+(3+((3+2*c)+2)*b+2)*a
bereits hat?Oder kannste die Formel nicht aufstellen?
Und warum genau 12 Sekunden? Das müßte eine Sekunde sein. Oder läuft dein Simulator gerade auf 1MHz?