Forum: Mikrocontroller und Digitale Elektronik Assembler Verständnisproblem


von wdt1 (Gast)


Lesenswert?

Hallo,

derzeit versuche ich mich etwas in die PIC Assembler Sprache 
einzuarbeiten. Nur komme ich im Moment leider nicht von alleine weiter.

Zuerst einmal mein Beispielcode, an dem es bei mir mit dem Verständnis 
ein bisschen hakt.

Es handelt sich um einen PIC16c620  mit 4Mhz
Der Übersicht halber, poste ich nur die relevanten Auszüge aus dem 
gesamt Beispielcode. Zumindest denke ich, dass sie relevant sind.

Auszug 1:
1
tmpw            equ             h'0028'         ; temp.Variable fuer W-Reg
2
IOPTION         equ             b'01000101'     ;Option-Register

Auszug 2:  Die Main Funktion, über die dann weitere aufgerufen werden
1
START
2
        call    INIT                    ; System initialisieren

Von dort aus wird ja in die Subroutine INIT gesprungen von der ich nun 
den nächsten Auszug vorstelle.
1
INIT:
2
3
4
      movlw       IOPTION         ;Option-Register initial.
5
          option      ;TMR0-Prescaler 1:64
6
7
8
      movlw  b'10010000'  ;Intcon-Register initial.
9
      movwf  INTCON
10
11
            call        WAIT_2          ;PAUSE

Soweit denke ich, dass ich den Code verstanden habe. Mit Call WAIT_2 wir 
eine Funktion aufgerufen, die nichts beinhaltet, außer zweimal 
hintereinander die Funktion PAUSE aufruft.
Also  call PAUSE
      call PAUSE

Nur leider verstehe ich in folgendem Beispielcode nun nicht, wie man auf 
die 3,1ms Pause kommt. Bzw. was die 9600 zu bedeuten haben.

So wie ich das verstanden habe, benötigt der PIC16  für einen Zyklus 4 
Takte. Bei 4 MHZ wären das ja dann 1uS pro Zyklus.
Man zählt von h'F0'  was ja Dez. 240 entspricht jeweils einen Schritt 
herunter und springt dann mit GOTO wieder hinauf, bis man bei 0 landet.
Ich meine gelesen zu haben, dass ein GOTO Befehl 2 Zyklen benötigt.

Mit folgender Formel habe ich dann versucht auf die 3,1ms zu kommen, bin 
aber in allen möglichen Varianten daran gescheitert.

Formel siehe folgenden Link : 
http://home.arcor.de/tobias-herke/01_E-TECH/Kurse/Zeitschleifen.html

Ich verstehe einfach nicht, wie man durch diese Funktion 3,1 ms Pause 
realisiert ...
1
      movlw       h'F0'          ;Warteschleife einstellen 3.1 ms (9600)
2
      movwf       tmpw           ;einstellen
3
4
      clrwdt                     ;WDOG triggern
5
6
W1_LOOPBIT
7
      decfsz      tmpw,1         ;Pruefen ob innere Schleife
8
      goto        W1_LOOPBIT     ;noch durchlaufen werden muss
9
10
      movlw       h'F0'          ;Warteschleife einstellen 3.1 ms (9600)
11
      movwf       tmpw           ;einstellen
12
13
      clrwdt                     ;WDOG triggern
14
15
W2_LOOPBIT
16
      decfsz      tmpw,1         ;Pruefen ob innere Schleife
17
      goto        W2_LOOPBIT     ;noch durchlaufen werden muss
18
19
      clrwdt                     ;WDOG triggern
20
21
      movlw       h'47'          ;Warteschleife einstellen 3.1 ms (9600)
22
      movwf       tmpw           ;einstellen
23
24
W3_LOOPBIT
25
      decfsz      tmpw,1         ;Pruefen ob innere Schleife
26
      goto        W3_LOOPBIT     ;noch durchlaufen werden muss
27
28
      return

Die Funktion wird zweimal hintereinander aufgerufen.

Vielen Dank für eure Hilfe.

von Peter D. (peda)


Lesenswert?

Bei Assemblerfragen wäre es immer schön, auch den Typ im Betreff mit 
anzugeben.
Assembler ist nämlich Maschinen abhängig.

wdt1 schrieb:
> Der Übersicht halber, poste ich nur die relevanten Auszüge aus dem
> gesamt Beispielcode.

Du weißt aber schon, daß man Anhänge benutzen darf.

wdt1 schrieb:
> Zumindest denke ich, dass sie relevant sind.

Genau das ist nämlich der Knackpunkt.

wdt1 schrieb:
> Nur leider verstehe ich in folgendem Beispielcode nun nicht, wie man auf
> die 3,1ms Pause kommt. Bzw. was die 9600 zu bedeuten haben.

Ich auch nicht. Bei mir ist:
1µs * 240 * 3 = 720µs

9600 klingt nach Baudrate, wären dann aber:
1 / 9600 = 104µs

Die Kommentare haben offenbar mit dem Code nicht das geringste zu tun.


Was ich Dir aber dringend empfehlen würde, schmeiß erstmal das clrwdt 
raus.
Der Watchdog hat wärend der Entwicklung im Programm nichts verloren, 
disable ihn!
Das einzige was er bewirkt, er erschwert Dir massiv die Fehlersuche.

Und besonders das exzessive Verwenden führt ihn ad absurdum. In einem 
fertigen Programm darf er nur an einer einzigen Stelle resettet werden!

von wdt1 (Gast)


Lesenswert?

Danke schonmal für die Hilfe.

In meinem Post oben habe ich geschrieben, dass es sich um einen 
PIC16C620 mit 4Mhz handelt.

von Karl H. (kbuchegg)


Lesenswert?

>  Ich meine gelesen zu haben, dass ein GOTO Befehl 2 Zyklen benötigt.

Das ist der erste Knackpunkt.

'Meine' ist zu wenig.
Wenn du Zyklen zählen willst, dann musst du von jedem Befehl exakt 
wissen, wieviele Zyklen er braucht.

von wdt1 (Gast)


Lesenswert?

Hmmmm ok.  Aber gibt es für diese Art der Pausenprogrammierung nicht 
eine Art Guide oder Kochrezept ? Denn der Entwickler von diesem Code hat 
ja auch nur das Datenblatt vom PIC16C620 zur Hand gehabt.
Über die decfsz Befehle eine Pause zu generieren habe ich nun schon des 
öfteren gesehen. Ich meine, das muss vom Prinzip her ja immer gleich 
sein.... vielleicht kann mir da ein "alter" Assembler Fuchs ja auf die 
Sprünge helfen.

von deKatz (Gast)


Lesenswert?

Die 3 Befehle zur Initialiserung von W1_LOOPBIT benötigen 3µsec.
"decfsz temp,W und GOTO benötigen 3 Befehlszyklen * 240 (+1 Extracyclus 
wenn decfsz Wahr ist) sind 721µs + 3µs Initialisierung = 724µs.

W2_LOOPBIT ist eingach ne Kopie von W1_LOOPBIT also auch 724µs.

W3_LOOPBIT wir 0x47 (= 71) mal durchlaufen, also (3 * 71) + 1 = 213µs.

Macht in Summe 1661µs , bei 2 Aufrufen 3322µs.
Hmmmm eigentlich sogar ein paar µs länger weil CALL & RETURN nicht 
miteingerechnet.

Wie man zur Angabe von 3100µs kommt ??? keine Ahnung

Schein mir irgendwie zusammenkopiert zu sein...siehe Kommentar "9600" - 
sollte wohl auf eine Baudrate hinweisen und dann noch der Kommentar 
"innere Schleife"....gibt es wo eine äussere Schleife???

von Joe (Gast)


Lesenswert?

Wenn du Assembler lernen willst, dann schreibe dir selbst eine 
WAIT-Routine.
Wenn du diese verstehst, dann hast du was gelernt.

joe

von Ottmar K. (wil1)


Lesenswert?

wdt1 schrieb:
> Aber gibt es für diese Art der Pausenprogrammierung nicht
> eine Art Guide oder Kochrezept
Schon mal auf die Idee gekommen, dass der Code von vorne herein 
fehlerhaft ist?
Dieser Code tatsächlich gar nicht die angeblichen 3,1ms Delay 
realisieren kann? Womöglich wurde da nur Pi mal Daumen geschätzt, weil 
es ja sowieso nicht so genau zu sein braucht...?

Delay einfach erzeugt:
Schau mal hier [http://www.piclist.com/cgi-bin/delay.exe]. Dort machst 
Du diese Eingaben:
        a) die Oszillatorfrequenz
        b) die gewünschte Zeitdauer
und erhältst den fertigen Code!

mfG Ottmar

von W.S. (Gast)


Lesenswert?

wdt1 schrieb:
> W1_LOOPBIT
>       decfsz      tmpw,1         ;Pruefen ob innere Schleife
>       goto        W1_LOOPBIT     ;noch durchlaufen werden muss

Erstmal eines: schreib bitte NIE als Befehlsqualifier ,0 oder ,1 denn 
das kann sich keiner merken, auch du nicht (ähem.. ich erst recht 
nicht).

Wenn dein Assembler es nicht anders hergibt, dann mach dir mit 
irgendeiner Definition (#define oder EQU) zwei passende Bezeichner F und 
W (für Ziel F für File oder W für W-Register), so daß du im Programm

waitloop:  DECFSZ tmpw,F
           GOTO   waitloop

schreiben kannst. Du wirst das bei der Denkfehlersuche schon bald zu 
schätzen wissen. Ansonsten mußt du bei solchen Trampelschleifen eben 
Takte zählen. Hier haben wir
 239 mal  1 (für den DECFSZ) + 2 (für den GOTO)
 1   mal  2 (für den DECFSZ) + 0 für den GOTO
macht 719 Takte (wenn ich mich nicht verrechnet habe)
das Ganze dann 3x macht 2157 Takte plus die paar für deine Befehle 
zwischendurch. Auf 3100 takte kommt man da nicht.

Ach.. gut Nacht für Heute

W.S.

von wdt1 (Gast)


Lesenswert?

Joe schrieb:
> Wenn du Assembler lernen willst, dann schreibe dir selbst eine
> WAIT-Routine.
> Wenn du diese verstehst, dann hast du was gelernt.

Das habe ich bereits getan und denke auch, dass mir das Prinzip klar 
ist. Allerdings handelt es sich bei dem Code um ein fertiges Produkt, 
dass auch eingesetzt wird.
Soweit muss der Code ja auch "richtig" funktionieren.
Deshalb bin ich verunsichert, wenn ich bei einem fertigen/funktionellen 
Code nicht auf das gleiche Ergebniss komme. Da zweifle ich meistens eher 
meine Überlegungen an :/

deKatz schrieb:
> Die 3 Befehle zur Initialiserung von W1_LOOPBIT benötigen 3µsec.
> "decfsz temp,W und GOTO benötigen 3 Befehlszyklen * 240 (+1 Extracyclus
> wenn decfsz Wahr ist) sind 721µs + 3µs Initialisierung = 724µs.
>
> W2_LOOPBIT ist eingach ne Kopie von W1_LOOPBIT also auch 724µs.
>
> W3_LOOPBIT wir 0x47 (= 71) mal durchlaufen, also (3 * 71) + 1 = 213µs.
>
> Macht in Summe 1661µs , bei 2 Aufrufen 3322µs.
> Hmmmm eigentlich sogar ein paar µs länger weil CALL & RETURN nicht
> miteingerechnet.
>
> Wie man zur Angabe von 3100µs kommt ??? keine Ahnung
>
> Schein mir irgendwie zusammenkopiert zu sein...siehe Kommentar "9600" -
> sollte wohl auf eine Baudrate hinweisen und dann noch der Kommentar
> "innere Schleife"....gibt es wo eine äussere Schleife???

Vielen Dank für deine Hilfe. Genau das hat mir gefehlt und hilft mir das 
ganze besser zu verstehen.

von wdt1 (Gast)


Lesenswert?

Könnt ihr mir bitte nochmal eine Frage beantworten ?
Ich habe eben in das Datenblatt des PIC16c62x  reingeschaut und im 
Unterpunkt 10.2 PIC16C62x  eine Tabelle mit Assembler Befehlen gefunden. 
In einer der Spalten stehen auch die benötigten Zyklen für jeden Befehl.
Dort sind allerdings für :

GOTO : 2    Zyklus
DECFSZ :  1(2)   Zyklus
MOVF : 1    Zyklus      angegeben.

Habe ich noch etwas vergessen zu beachten ? Weil deKatz zum Beispiel ein 
GOTO mit 3 Zyklen angibt.

von wdt1 (Gast)


Lesenswert?

Oh tut mir Leid. Ich habe mich verlesen. Mein letzter Post kann bitte 
entfernt werden oder beachtet ihn einfach nicht.

von Peter D. (peda)


Lesenswert?

wdt1 schrieb:
> Soweit muss der Code ja auch "richtig" funktionieren.

Das kann er ja. Nur der Kommentar ist falsch. Ein Kommentar beeinflußt 
nicht den Code. Da kann also ruhig der größte Blödsinn drin stehen. 
Sollte natürlich nicht.

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.