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.
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!
> 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.
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.
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???
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
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.
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.
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.
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.