Forum: Mikrocontroller und Digitale Elektronik Problem mit Schleifengenerator (PIC, ASM)


von Finn J. (draddicted)


Lesenswert?

1
;1998 cycles
2
  movlw  0x8F
3
  movwf  d1
4
  movlw  0x02
5
  movwf  d2
6
Delay_0
7
  decfsz  d1, f
8
  goto  $+2
9
  decfsz  d2, f
10
  goto  Delay_0
11
12
      ;2 cycles
13
  goto  $+1
Ich habe ein Problem mit dem Piclist Schleifengenerator.
Und zwar verstehe ich nicht, wie man aus den zwei Variablen die Cyclen 
errechnet!

Ich dachte, es würde so funktionieren: (4*d1-1)*(4*d2-1)
Aber mit der Formel komme ich auf ungefähr das Doppelte an Cyclen.
Wie muss man die Formel hier für eine verschachtelte Schleife ansetzen?

: Bearbeitet durch User
von Max H. (hartl192)


Lesenswert?

So siehst aus:

decfsz  d1, f ist die innere Schleiche
decfsz  d2, f die Äußere.

Ein Durchlauf der Inneren dauert:
  decfsz  d1, f       1 Zyklus +
  goto  $+2           2 Zyklen +
  decfsz  d2, f
  goto  Delay_0       2 Zyklen = 5 Zyklen
Sobald die Innere abgelaufen ist, wird d2 dekrementiert, wenn d2 0 ist, 
ist das delay fertig.
Die innere Schleife wird also zwei Mal ausgeführt und dauert beim ersten 
Mal 143*5 Zyklen, bei 256*5 Zyklen.
Also gesamt:
143*5+255*5
+ 1 Zyklus zusätzlich für den Sprung beim "decfsz d2, f"
+ 2 Zyklen für "goto $+1"
+die 4 Zyklen für das initialisieren von d1, d2
= 1997

Da fehlt mir jetzt ein Taktzyklus. Vllt. habe ich etwas vergessen 
miteinzurechnen.

von Finn J. (draddicted)


Lesenswert?

Vielen vielen Dank! Das war sehr wichtig für mich, damit ich nicht nur 
"copy-paste" in meinem Programm mache!

von Max H. (hartl192)


Lesenswert?

Finn Jensen schrieb:
> "copy-paste"
Ich würde dir empfehlen, zu lernen wie Delay-Schleifen und somit auch 
andere Schleifen funktionieren.

von Finn J. (draddicted)


Lesenswert?

Max H. schrieb:
>[...] bei 256*5 Zyklen.[...]

Das versteh ich allerdings nicht ganz, wieso 256*5 Zyklen? wir haben 
doch nur ein mal bei d1 143, das dann zwei mal wegen der 2 in d2...
Das Ergebnis stimmt, aber ich verstehe nicht ganz wo die 256*5 Zyklen, 
bzw.
nachher die 255 in der Formel 5*143+5*255 her kommt?

> Da fehlt mir jetzt ein Taktzyklus. Vllt. habe ich etwas vergessen
> miteinzurechnen.

Ich kann mir vorstellen, dass die Wertevergabe irgendwie noch einen 
Zyklus aus macht... Vielleicht lieg ich da aber auch völlig auf dem 
Holzweg!

von Max H. (hartl192)


Lesenswert?

Finn Jensen schrieb:
> Das versteh ich allerdings nicht ganz, wieso 256*5 Zyklen? wir haben
> doch nur ein mal bei d1 143, das dann zwei mal wegen der 2 in d2...
> Das Ergebnis stimmt, aber ich verstehe nicht ganz wo die 256*5 Zyklen,
> bzw.
> nachher die 255 in der Formel 5*143+5*255 her kommt?
Ich muss mich entschuldigen, es sind 256. Dann kommen wir auf 
5*143+5*256+4+2=2001 Zyklen. Laut MPLAB SIM sind es 2000 Zyklen. Also 
haben wir jetzt einen Zyklus zu viel berechnet. Der kommt daher, dass 
das ich letzte "goto  Delay_0", das übersprungen wird, mitgerechnet 
habe.

Beim ersten Mal sind es 143 Durchläufe, da du das d0 Register mit 143 
vorlädst, beim zweiten Mal sind es 256 Durchläufe, da das d0 dann mit 
null startet, weil es beim ersten Mal bis null hinuntergezählt wird und 
nicht wieder neu auf 143 gesetzt wird.

Wenn du genau die 1998 Zyklen brauchst musst du das "goto $+1" an Ende 
löschen.

Finn Jensen schrieb:
> Ich kann mir vorstellen, dass die Wertevergabe irgendwie noch einen
> Zyklus aus macht...
Ich nir nicht. movlw und movwf sind einfach Single-Cycle-Befehle.

: Bearbeitet durch User
von Finn J. (draddicted)


Lesenswert?

Jetzt habe ich eine frage zu 2 Fach verschachtelten schleifen, die 
einfach verschachtelten kann ich jetzt ohne Probleme berechnen, aber die 
zweifachen nicht. Meine Überlegung war jetzt diese:

7*3+(7*24)*255+(7*255)*255, womit ich auch auf 498036 komme, aber laut 
piclist kommt man mit dieser schleife auf 499994. Knapp 1000 Zyklen 
mehr!
Wie genau muss ich rechnen?
1
  movlw  0x03
2
  movwf  d1
3
  movlw  0x18
4
  movwf  d2
5
  movlw  0x02
6
  movwf  d3
7
Delay_0
8
  decfsz  d1, f
9
  goto  $+2
10
  decfsz  d2, f
11
  goto  $+2
12
  decfsz  d3, f
13
  goto  Delay_0
14
15
      ;6 cycles
16
  goto  $+1
17
  goto  $+1
18
  goto  $+1
Und bei dieser Schleife, die eigentlich 999997 Zyklen haben soll, komme 
ich mit meiner Formel auf gerade ein mal 539126.
Die wäre hier dann 7*8+(7*47)*255+(7*255)*255

: Bearbeitet durch User
von Finn J. (draddicted)


Lesenswert?

Finn Jensen schrieb:
> Jetzt habe ich eine frage zu 2 Fach verschachtelten schleifen, die
> einfach verschachtelten kann ich jetzt ohne Probleme berechnen, aber die
> zweifachen nicht. Meine Überlegung war jetzt diese:
>
> 7*3+(7*24)*255+(7*255)*255, womit ich auch auf 498036 komme, aber laut
> piclist kommt man mit dieser schleife auf 499994. Knapp 1000 Zyklen
> mehr!
> Wie genau muss ich rechnen?
>
>   movlw  0x03
>   movwf  d1
>   movlw  0x18
>   movwf  d2
>   movlw  0x02
>   movwf  d3
> Delay_0
>   decfsz  d1, f
>   goto  $+2
>   decfsz  d2, f
>   goto  $+2
>   decfsz  d3, f
>   goto  Delay_0
>
>       ;6 cycles
>   goto  $+1
>   goto  $+1
>   goto  $+1
>
> Und bei dieser Schleife, die eigentlich 999997 Zyklen haben soll, komme
> ich mit meiner Formel auf gerade ein mal 539126.
> Die wäre hier dann 7*8+(7*47)*255+(7*255)*255

leider darf ich meine Posts nicht bearbeiten...
Bei dieser schleife:
1
movlw  0x08
2
  movwf  d1
3
  movlw  0x2F
4
  movwf  d2
5
  movlw  0x03
6
  movwf  d3
7
Delay_0
8
  decfsz  d1, f
9
  goto  $+2
10
  decfsz  d2, f
11
  goto  $+2
12
  decfsz  d3, f
13
  goto  Delay_0

: Bearbeitet durch User
von Max H. (hartl192)


Lesenswert?

Hast du schon versucht so eine Schleife komplett selbst zu schreiben? 
Dann wirst du auch verstehen wie du sie richtig berechnest.

von Stampede (Gast)


Lesenswert?

Hi,

meine PIC Assembler Tage sind etwas her, aber muss es nicht
1
Delay_0
2
  decfsz  d1, f
3
  goto  $-2   <----- MINUS ?
heißen? Der Controller soll ja wieder zum decfsz zurückspringen und 
nicht vorwärts...

von Finn J. (draddicted)


Lesenswert?

Stampede schrieb:
> Hi,
>
> meine PIC Assembler Tage sind etwas her, aber muss es nicht
>
>
1
> Delay_0
2
>   decfsz  d1, f
3
>   goto  $-2   <----- MINUS ?
4
>
> heißen? Der Controller soll ja wieder zum decfsz zurückspringen und
> nicht vorwärts...

Man kann auch $+2, damit springt er dann 2 Zeilen weiter auf das nächste 
goto $+2, damit springt er dann 2 Zeilen weiter auf goto Delay_0 und 
fängt dann von vorne an.

von Finn J. (draddicted)


Lesenswert?

Max H. schrieb:
> Hast du schon versucht so eine Schleife komplett selbst zu schreiben?
> Dann wirst du auch verstehen wie du sie richtig berechnest.

Hm, also wenn ich ehrlich bin, ich würde die Schleife auch so schreiben
oder vielleicht einfach immer nach jedem decrement Befehl wieder den 
Sprungbefehl an den Anfang. Letztendlich würde ich aber noch immer nicht 
wissen, wie ich mit 3 decrement Befehlen rechnen muss...

Also statt dem Aufbau
1
movlw  0x08
2
  movwf  d1
3
  movlw  0x2F
4
  movwf  d2
5
  movlw  0x03
6
  movwf  d3
7
Delay_0
8
  decfsz  d1, f
9
  goto  $+2
10
  decfsz  d2, f
11
  goto  $+2
12
  decfsz  d3, f
13
  goto  Delay_0
So:
1
movlw  0x08
2
  movwf  d1
3
  movlw  0x2F
4
  movwf  d2
5
  movlw  0x03
6
  movwf  d3
7
Delay_0
8
  decfsz  d1, f
9
  goto  Delay_0
10
  decfsz  d2, f
11
  goto  Delay_0
12
  decfsz  d3, f
13
  goto  Delay_0

von Karl H. (kbuchegg)


Lesenswert?

Finn Jensen schrieb:

> Hm, also wenn ich ehrlich bin, ich würde die Schleife auch so schreiben
> oder vielleicht einfach immer nach jedem decrement Befehl wieder den
> Sprungbefehl an den Anfang. Letztendlich würde ich aber noch immer nicht
> wissen, wie ich mit 3 decrement Befehlen rechnen muss...

Was auch oft hilft.
Sich dumm stellen, selber µc spielen und (mit kleinen Zahlen!) einfach 
selber den Code durchsimulieren, wobei man ganz einfach die Takte 
zusammenzählt, die man gerade simuliert.

Aus der Beobachtung dessen, welche Befehle in welcher Reihenfolge 
abgearbeitet werden, ergibt sich 'die Formel' recht zwangsläufig, wenn 
man sich nach erfolgter Simulation zurücklehnt und sich überlegt, wie 
die Dinge da jetzt gelaufen sind.


Zum Thema kleine Zahlen:
Damit man sich nicht dumm und dusselig simuliert, kann man ja mal 
annehmen, dass man es mit einem 3 Bit Rechner zu tun hat. D.h. der kann 
nicht von 0 bis 255 in einem Byte operieren, sondern nur von 0 bis 7 
(bzw. umgekehrt, wenn ein decrement auf 0 angewendet wird, dann ist der 
nächst kleinere Wert dann eben nicht 255 sondern 7). Letzten Endes ist 
die Bitbreite ja nur ein Zahlenwert in der Formel, ändert aber an der 
Struktur der Formel nichts.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

> wie ich mit 3 decrement Befehlen rechnen muss...

Im Prinzip nach

Die Herstellung einer Flasche Bier dauert 10 Sekunden.
Die Flaschen für eine Kiste Bier herzustellen dauert daher wie lange?
Wenn auf einer Palette 12 Kisten Bier gestapelt werden, wie lange dauert 
dann die Herstellung der Flaschen für eine Palette?
Auf einen LKW können 48 Paletten mit Bierkisten geladen werden. Wie 
lange dauert es, die dafür notwendigen Flaschen herzustellen?
Auf dem Autozug durchs Inntal, von Kufstein auf den Brenner, passen 132 
LKW mit Paletten voller Bierkisten. Wie lange dauert es, die dabei 
beförderten Flaschen herzustellen?


Aber letzten Endes hängt es davon ab, wie genau die einzelnen Schleifen 
ineinander geschachtelt werden. Wenn man das im Code nicht sieht, dann 
muss man das eben durch simulieren rauskriegen.

: Bearbeitet durch User
von Finn J. (draddicted)


Lesenswert?

Leider komme ich immer noch nicht weiter...
Ich frage mich selbst schon wieso.
Gerechnet habe ich so:
d1 = 8, d2 = 47, d3 = 3
Wenn d1 das erste mal durchläuft, haben wir 7*8 = 56.
Beim zweiten mal ist d1 = 255
und wird mit 7*d2*d1 berechnet, das sind dann 83895.
Beim dritten mal (da liegt jetzt mein Problem!) müsste d1 = 255, d2 = 
255 und d3 = 3 sein.
Und dieses mal müsste man 7*d2*d1*d3 sein, dann kommt man aber schon auf 
1365525. Und dann muss man die ja auch noch addieren, womit man auf 
1449476.

Aber das macht ja keinen Sinn. Laut Piclist kommt man mit den Variablen 
auf ~1000000

von Karl H. (kbuchegg)


Lesenswert?

Finn Jensen schrieb:

> Wenn d1 das erste mal durchläuft, haben wir 7*8 = 56.
> Beim zweiten mal ist d1 = 255
> und wird mit 7*d2*d1 berechnet, das sind dann 83895.

wieso 7?
Wieso d2?

Du hast das vorgegebene d2 ja aufgeteilt. In den ersten Durchlauf und in 
die restlichen Durchläufe. D.h. die Anzahl der restlichen Durchläufe ist 
ja d2-1, weil ja der erste Durchlauf anders zu bewerten ist.


Simulier es dir mit kleinen Zahlen durch! Dir ist scheinbar noch nicht 
wirklich klar, wie da die Abläufe sind.

: Bearbeitet durch User
von Finn J. (draddicted)


Lesenswert?

Karl Heinz schrieb:
> Finn Jensen schrieb:
>
>> Wenn d1 das erste mal durchläuft, haben wir 7*8 = 56.
>> Beim zweiten mal ist d1 = 255
>> und wird mit 7*d2*d1 berechnet, das sind dann 83895.
>
> wieso 7?
> Wieso d2?
>
> Du hast das vorgegebene d2 ja aufgeteilt. In den ersten Durchlauf und in
> die restlichen Durchläufe. D.h. die Anzahl der restlichen Durchläufe ist
> ja d2-1, weil ja der erste Durchlauf anders zu bewerten ist.
>
>
> Simulier es dir mit kleinen Zahlen durch! Dir ist scheinbar noch nicht
> wirklich klar, wie da die Abläufe sind.

Ich habe das ganze so verstanden:

  movlw  0x08
  movwf  d1
  movlw  0x2F
  movwf  d2
  movlw  0x03
  movwf  d3
Delay_0
  decfsz  d1, f ;Erster Durchlauf: 7 * 8(d1)
  goto  $+2     ;(7 wegen 1x decfsz, dann 3x goto = 7
  decfsz  d2, f ;Zweiter Durchlauf: 7 * 255(d1) * 2F(d2)
  goto  $+2     ;(7 wegen 1x decfsz, dann 3x goto = 7
  decfsz  d3, f ;Dritter Durchlauf: 7 * 255(d1) * 255(d2) * 3(d3)
  goto  Delay_0

Also, ja, mir sind die Abläufe noch nicht ganz klar, ich weiß nicht, wie 
oft decfsz für d1 und für d2 durchgeführt wird. d3 wird ja genau 3 mal 
durchgeführt.

von Max H. (hartl192)


Lesenswert?

Jetzt eine einfacher zu verstehende Art von Schleife. Du musst doch 
nicht genau diese verwenden?

Ich hache meine Schleifen immer so:
1
Delay:
2
movlw 0x09         ;
3
movwf d3           ;
4
del_2:          ;
5
movlw 0x08      ;
6
movwf d2        ;
7
del_1:       ; Innerste Schleife
8
movlw 0x07   ; Dauert immer 2+3*0x07 Zyklen
9
movwf d1     ;
10
decfsz d1,f  ;
11
goto $-1     ;
12
decfsz d2,f     ; 2. Innerste Schleife.
13
goto del_1      ; Dauert immer 2+0x08*(3+Innerste)
14
decfsz d3,f        ; Außere Schleife
15
goto del_2         ; Dauert immer 2+0x09*(3+2.Innerste)
Abgesehen von 2 Labels mehr ist der Code gleich lang.

Welchen PIC verwendest du?
Bei PIC18 muss man bedenken, dass das Überspringen eines GOTOs 3 Zyklen 
dauert.

: Bearbeitet durch User
von Finn J. (draddicted)


Lesenswert?

Ich verwende den PIC16F628A.

Gibt es eine Möglichkeit in MPLAB einzustellen, dass der PIC nur 8 bit 
hat?
Das würde mir das Schleifen austesten sehr erleichtern, da ich im Moment 
eine Schleife mit 3 Variablen, je mit 0x02 gefüllt durchlaufe und beim 
zweiten durchlauf 255 mal den Befehl durchgehen muss.

von Max H. (hartl192)


Lesenswert?

Finn Jensen schrieb:
> Ich verwende den PIC16F628A.
>
> Gibt es eine Möglichkeit in MPLAB einzustellen, dass der PIC nur 8 bit
> hat?

Der PIC16 hat genau 8bit und das kann man auch nicht ändern.

: Bearbeitet durch User
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.