Archiv verlassen und diese Seite im Standarddesign anzeigen : Zeitberechnung bei Schleife/Grundlegendes
Hallo
Ich habe in der Schule einen 80C535 programmiert. Da haben wir die Schleife mit dem Befehl djnz realisiert. Beim AVR hab ich die Schleife jetzt mit dem Befehl brne programmiert. Gibt es bei den AVR`s einen vergleichbaren Befehl wie der des 80C535? Wie ist das eigentlich? Brne heißt doch wörtlich übersetzt "Spring wenn nicht gleich" oder seh ich das Falsch. Also muß der Wert doch mit irgend etwas verglichen werden? Kann mir das jemand erklären?
Mein zweites Problem:
Ich habe folgende Schleife:
;Unterprogramm
warten:
ldi r16, 255
ldi r17, 100
ldi r18, 10
loop1:
dec r16
brne loop1
dec r17
brne loop1
dec r18
brne loop1
ret
Die werte mit denen die Register geladen werden habe ich durch außprobieren heraus bekommen. Schleife funktioniert. Aber wie kann ich jetzt die genaue Zeit berechnen, die der µC braucht für einen Durchlauf? Mein Board arbeitet mit 12 Mhz. Ich weiß, ist e bissel schnell, aber hab halt das gleiche genommen wie wir in der Schule hatten.
Vielen Dank schon mal für eure hoffentlich zahlreichen Versuche mir zu helfen.
MFG
Da schaut man mal bei Atmel auf der Homepage nach dem Befehlssatz des entsprechenden AVRs. Dort findet man auch Angaben dazu, wieviele Takte welcher Befehl benötigt (im Normalfall je einen, denke ich). Diese dann zusammen zu addieren, bleibt dir überlassen.
Ähnlich müsst ihr die Sache ja in der Schule auch angegangen sein.
brne = break when not equal
Gottfreak
07.10.2004, 15:59
brne = break when not equal
sowas kommt bei Rückübersetzungen 'raus!
Im Zusammenhang der Schleife stimmt das wohl, allgemeiner ist aber sicher die Originalformulierung(aus der Appnote):
brne = break if not equal
Also bei mir heißt "to branch" Springen und nicht "warten" (break). Aber naja vielleicht bin ich ja wirklich so blöd...
Mit Deiner Antwort kann ich jedenfalls was den Befehl angeht leider nicht viel anfangen....@Gast.... :-(
MFG
Gottfreak
07.10.2004, 17:16
BRNE springt tatsächlich. Wenn es auf ein CP folgt, springt es bei Ungleichheit. Ich denke mal, DEC wird das gleiche Flag setzen, um entweder die Gleichheit mit 0 oder den Überlauf anzuzeigen.
Das Warten entsteht nur dadurch, dass der nach oben springt und dann den Wert wieder verringert(und dann nochmal vergleicht). So zählt der r18 mal die beiden anderen Register(r16 natürlich damit r18*255 mal) rückwärts auf 0(oder -1). Beim ersten mal fängt er mit der Vorbelegung an, danach mit 255.
Auf der Atmel-Seite gibt's das "AVR-Instruction-Set". In dem Dokument sind alle ASM Befehle gut erklärt.
Hallo
Also diese Antwort hilft mir dann schon weiter. Seh ich das richtig, daß es für mich (rein zum ausrechnen) geschickter wäre r16 und r17 gleich mir 255 zu laden. Und die Zeit (Anzahl der durchläufe) einfach über r18 zu steuern?
Aber mal erhrlich, die realisierung der Schleife bei einem 80C535 ist doch wesentlich einfacher. Ich meine rein vom Verständniss finde ich den djnz Befehl wesentlich einfacher.
MFG
Gottfreak
07.10.2004, 20:51
In r18 hat gewissermaßen die Einheit 2^16 Durchläufe, wenn man die Rücksprünge zu Loop1 betrachtet.
Die gesamte Anzahl der Durchläufe stellt sich dann als dreistellige Zahl dar. Die Basis des Zahlensystems ist 256, die Ziffern also Bytes.
So bietet sich zur Feineinstellung r17(oder wenn so eine lange Schleife mal ganz genau sein muss, auch r16) an.
Den djnz-Befehl kenn' ich nicht. Was macht der denn?
Also erstmal vielen Dank für die Antworten. Etwas klarer sehe ich jetzt... :-) Wäre trotzdem froh, wenn ihr mir noch bei einem behilflich sein könntet: Und zwar, Ich will mit der Schleife eine Verzögerung von 1 sec erreichen. Ich verwende wie oben erwähnt einen 12 Mhz Quarz. Mit welchen Werten muß ich jetzt die Register laden? Wäre auch noch ganz hilfreich, wenn ihr mir dazu eine kleine Formel hättet. Oder eine kurze/ausführliche ;-) Erklärung.
Vielen Dank schon mal! Den Befehl djnz gibt es nur beim 80C535 Werd da bis morgen nochmal in meinen Unterlagen nachschauen. Ist mir jetzt zu spät...
MFG
Gottfreak
08.10.2004, 01:23
Dec braucht einen Taktzyklus
BRNE braucht einen Takt, wenn er nicht springt und zwei, wenn er es tut.
Die Wartezeit ist also:
(r16-1)*3 + 2 für den ersten Teil der Schleife(r16-1, weil bei r16=1 sofort nach dem dec gescipt wird. *3, weil ein DEC einen und ein BRNE mit Sprung zwei Takte dauert. +2, weil das letzte mal nicht gesprungen wird und DEC und BRNE dann jeweils einen Takt dauern)
dazu kommen dann
(r17-1)*(255*3+2)+2
255*3+2 , weil ab dem zweiten Durchlauf r16 auf 0 ist(und dann von 255 bis auf 1 'runterzählt. Dann kommen die 2 Takte für Dec auf 0 und BRNE ohne Sprung.).
+3 ,Weil das "Dec r17" und das BRNE danach 3 Takte dauern(mit Sprung). Die (r17-1) und das +2 am Ende kommen wieder daher, dass er beim letzten mal nicht springt und BRNE nur einen Takt dauert(+DEC macht dann 2).
Dann kommen noch
(r18-1)*(255*(255*3+2)+2)+2 Takte
Wenn das Ganze also 1Sekunde bei 12MHZ dauern soll, musst die Schleife 12*10^6 Takte dauern. Dabei ist zu berücksichtigen, dass der Aufruf der Schleife, wenn du sie in eine Subroutine packst, nochmal dauert.
Zum Berechnen nimmst du den größten Wert von r18, mit dem allein die Wartezeit noch zu gering ist und füllst dann auf:
(r16-1)*3+ (r17-1)*767 +(r18-1)*195587 +6
62 ist der Wert für r18
91 für r17
bei 53 für r16 ist die Schleife(ohne eventuellen Aufruf!) einen Takt zu kurz. Also schreibst du noch ein NOP dahinter(oder davor) oder "verschwendest" sonstwie noch einen Takt und die Zeit passt.
Gottfreak
08.10.2004, 01:50
Ich sehe gerade, dass ich was verplant hab:
Der Teil mit r17 dauert tatsächlich
(r17-1)*(255*3+2+3)+2
Ist in der Begründung dahinter ja auch beschrieben. Entsprechendes gilt auch für den Teil mit r18.
Du musst also mit
(r16-1)*3+(r17-1)*770 +(r18-1)*196355 +6
nochmal rechnen.
Damit ergibt sich:
immernoch r18=62
r17=30
r16=4
Das kommt dann genau hin mit 12000000 Takten.
Vielleicht hab' ich mich aber auch immernoch verrechnet(ist doch etwas hart dafür, dass ich gerade angetrunken aus 'ner Kneipe komme.).
Hallo,
ich werde gerade wahnsinnig mit einer Schleife hier, hoffe dass das hier reinpasst :)
Also, ich möchte bei meinem Atmel Mega8 mit einem 4 MHZ Osziallator eine Verzögerung von 5 Milisekunden (Befehle in der Prozedur können erstmal vernachlässigt werden) erzeugen.
Ich benutze folgenden Code:
;ldi reg1, X
ldi reg1, 113 ;1 Takt
;Dauer von Schleife 1 (abhängig von x,y):
;s1(x) = x + x + 2(x-1) + 1 + (x * s2(y)
;Zusammengefasst:
;s1(x) = 3x*(y+1)-1
schleife1:
;ldi reg2, Y
ldi reg2, 58 ;1 Takt * x
;Dauer von Schleife 2 (abhängig von y);
;ist s2(y) = 3y-1
schleife2:
dec reg2 ;1 Takt*y
brne schleife2 ;2 Takte * (y-1) + 1
dec reg1 ;1 Takt * x
brne schleife1 ;2 Takte * (x-1) + 1
Jetzt hab ich mir nen kleines Pascal-Programm geschrieben, dass mithilfe der Formel, die ich für diesen Algorithmus aufgestellt hab, alle möglichen Lösungen berechnet :)
Eregebnis waren hier (unter Anderem) für X 113 und für y 58, was auch rein rechnerisch ganz gut passt. Wenn ich das ganze jetzt aber im AVR Studio simulieren lasse, dann kommt der PC wahnwitzerweise auf eine Länge von 5004ms. Bei 4 MHZ sind 4ms immerhin 16 Taktzyklen..
Jetzt ist meine Frage: Ungenaue Simulation oder hängt da noch der Wurm drin?!
Man sollte die Software auch richtig benutzen können.. trotzdem dankeschön :)
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.