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 auch

    res: 
    	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 seltsamerweise

    res: 
    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,
    Danke

    Ungefä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
    Mit

    wait_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?


Anmelden zum Antworten