Assembler Verständnisproblem

Gast #3210320
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.
#3210369
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!
Gast #3210437
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.
Gast #3210551
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???
#3210567
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
Gast #3210906
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.
Gast #3210984
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.
Gast #3210996
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren