Hallo,
ich arbeite seit ein paar Tagen mit meinem Ersten PIC (16f84a). Nun bin
ich gerade dabei einen DAC0808 anzusteuern und damit verschiedene
Spannungsformen zu erzeugen. Rechteck war kein Problem ;)"Sägezahn"
auch nicht.
Mein Problem ist jetzt die Dreieckspannung.
Ich kriege es einfach nicht hin, bei b"11111111" in meiner Speicherzelle
dann rückwärts zu zählen und hin und her.
Ich habe probiert mit BTFSC/BTFSS zu arbeiten, kann man auch 8 Bit
gleichzeitig abfragen? Außerdem habe ich schon probiert mit dem CARRY
Bit im Statusregister zu arbeiten...
Bitte um unterstützung.
1
Main
2
incf 0x20,1
3
movf 0x20,0
4
movwf PORTB
5
call Wait
6
goto Main
Ich habe die Init und das Unterprogramm "Wait" hier mal raus gelassen,
funkrioniert ja alles soweit.
MfG
Ralf
Hallo,
klarer werden die Befehle decfsz,1 u.a. wenn statt der Zahl ein
Buchstabe verwendet wird: Anstatt 0 der Buchstabe W und anstatt 1, der
Buchstabe F.
DECFSZ Wert,F -> verminderte Wert um 1, wenn das Ergebnis der vorherigen
Befehlsfolge (addwf, subwf usw) = 0 ist. Schreibe dann Wert-1 in Wert
(F=File) zurück.
DECFSZ Wert,W im Prinzip wie vorstehend, nur dass Wert-1 in das
Arbeitsregister (WREG) und nicht nach "Wert" zurückgeschrieben wird.
Der Wert von W bzw. F wird im File *.INC-File des Prozessors zugewiesen
mfG GroberKlotz
Hmm...
CLRF myCounter
UpLoop: CALL Wait
INCFSC myCounter,F
GOTO UpLoop
DnLoop: CALL Wait
DECFSC myCounter,F
GOTO DnLoop
GOTO UpLoop
GroberKlotz schrieb:> incf cntUp,F ;Zähler + 1> btfss STATUS,C ;Carrybit=1? Zählerüberlauf?
Ist zwar schon zu spät für heute, aber ich glaube mich zu erinnern, daß
Carry bei INCF und DECF nicht gesetzt wird.
W.S.
GroberKlotz schrieb:> Probieres doch mit nachstehenden Unterprogrammen. Anstatt der Zähler
Idee dahinter habe ich verstanden, habe das Programm nun wie folgt:
1
COUNTUP ;zählt aufwärts
2
clrf 0x21 ;Abwärtszähler auf 0 setzen
3
CountUpLoop:
4
movf 0x20,0
5
movwf PORTB
6
call Wait
7
incf 0x20,F ;Zähler + 1
8
btfss STATUS,C ;Carrybit=1? Zählerüberlauf?
9
CALL COUNTDOWN ;JA, rückwärtszählen
10
GOTO CountUpLoop ;NEIN, weiter aufwärts zählen
11
RETURN
12
13
COUNTDOWN ;zählt abwärts
14
movlw 0xFF
15
movwf 0x21 ;Startwert zuweisen
16
CountDownLoop:
17
movf 0x21,0
18
movwf PORTB
19
call Wait
20
decfsz 0x21,F ;Zähler-1, Zerobit=1? Zähler=0?
21
CALL COUNTUP ;JA, wieder aufwärtszählen
22
GOTO CountDownLoop ;NEIN weiter abwärts zählen
23
RETURN
--> kommt wieder nur "Sägezahn"-Spannung bei raus. Zählt also nur Hoch
und fängt wieder an.
Klaus schrieb:> Irgenwann habe ich aufgehört, mir über sowas Gedanken zu machen, und>> myCounter++;>> geschrieben.
Richtig, von dem Assembler kriegt man ja Augenkrebs.
Einfach:
Das hilft mir leider nicht weiter. Ich bereite einen Kurs für unsere
Azubis vor, die in der Schule nämlich Assembler programmieren müssen...
Ich finde es auch Quatsch!
Also wenn es für sowas ist, vergiss es, mach erst selbst eine Schulung
oder
besorg dir ein Buch.
movf 0x20,0
Sowas wirst du weder in einer Schulung noch irgendwo in der Praxis nie
zu
sehen bekommen.
Schau dir mal diesen Sourcecode an, du könntest es ja inkl Quellenangabe
in deiner Schulung einbringen und an deinen uC anpassen:
http://mondo-technology.com/signal.html
Ich bin ja selbst Azubi ist das Problem :(
Wenn ich das Zero-Flag teste, dann würde er ja bei b'00000001' schon
wieder umspringen oder sehe ich das falsch?
Ralf G. schrieb:> Ich bereite einen Kurs für unsere> Azubis vor, die in der Schule nämlich Assembler programmieren müssen...
Dann bringt es aber nichts, wenn Dir ein anderer den Code schreibt.
Wenn Du anderen Assembler beibringen willst, mußt Du erstmal selber
Assembler können. Daran führt kein Weg vorbei.
Nichts gegen Dich, aber was ich bisher gesehen habe, sieht eher nach
Rumraten aus, statt nach Programmieren.
Ich habe momentan die Zeit dazu, und wie du vielleicht merkst,
beschäftige ich mich ja Intensiv damit. Ich will nicht, dass mir jemand
nen Programm schreibt, sondern meinen Fehler finden. Genug offtopic.
Mir ist da zwischen dem Dekrementieren und der dann eigentlichen Abfrage
des Zero/Carry Bits
1
decf 0x20,1 ; -1
2
movf 0x20,0 ;
3
movwf PORTB ; Ausgeben
4
call Wait ; Warten
5
btfsc STATUS,Z ; Wenn Zero-Bit=0 überspringe nächsten Befehl
einfach zu viel dazwischen. Zumal ich aus dem Bauch heraus das Gefühl
habe, dass eine Funktion die 'Wait' heisst, ihrerseits sehr
wahrscheinlich die Prozessorflags Zero bzw. Carry braucht um mittels
eigener Funktionalität Takte in Schleifen zu vertrödeln.
Eine Gefahr bei Assembler ist es immer, wenn man die Bearbeitung mit dem
Ziel einer Flag-Beeinflussung und die Auswertung dieser Flags durch
andere Anweisungen unterbricht. Denn dann muss man von ALLEN Dingen 100%
exakt und sicher wissen, wie sie sich auf die Flags auswirken. Daher ist
es oftmals programmiertaktisch besser, diese Dinge beisammen zu lassen.
Also nicht
DEkrement
mach was
Werte die Flags vom Dekrement aus
sondern
mach was
Dekrement
Werte die Flags vom Dekrement aus
Du willst, dass die beide Schleifen abwechselnd ausgeführt werde. Also
musst du sobald eine Schleife fertig ist in die nächste springen.
beim raufzählen z.B.
aufwaerts
incf counter,f
movf counter,w
movwf PORTB
call wait
incfsz counter,w
goto aufwaerts
goto abwaerts
und fürs abwärtszählen ändert sich nicht viel...
Wait ist einfach nur eine Warteschleife von 5 ms. Diese habe ich erstmal
nur rein gemacht um die Geschwindigkeit aufm Oszi zu verringern und die
"Stufen" vernünftig sehen zu können.
Ralf G. schrieb:> Ich habe momentan die Zeit dazu, und wie du vielleicht merkst,> beschäftige ich mich ja Intensiv damit. Ich will nicht, dass mir jemand> nen Programm schreibt, sondern meinen Fehler finden. Genug offtopic.
Dann schnapp dir Papier und Bleistift und spiel COmputer.
Auf deinem Papier schreibst du dir alle Register und deren Werte auf.
Und auch die ALLER Flags. Wenn du einen Befehl ausführst, dann machst du
diese Operation auf dem Papier UND du vergisst dabei auch nicht auf die
Flags! Wenn du dir nicht sicher bist, welche Flags beeinflusst werden,
dann schau in den Instruction Datenblättern des Herstellers nach.
Und auch wichtig: Du machst nicht das, was du dir denkst das passiert,
sondern du machst in deiner Papier-Simulation das was im Code steht und
was in den Instructen Set Datenblättern des Herstellers steht!
Und PS: es hilft bei derartigen Simulation ungemein, wenn man die
'großen' Zahlen erst mal kleiner macht. Es macht nicht viel Sinn eine
Schleife 255 mal durchzusimulieren. 4 oder 5 mal tuts auch. 1 mal ist
hingegen wieder relativ schlecht, denn du solltest mit der Simulation
schon wenigstens 2 Durchläufe durch eine Schleife machen um alle Effekte
zu sehen.
Wenn du anderen Assembler beibringen willst, dann musst du intime
Kenntnisse haben. Und die gibt es nur in den Datenblättern. Dort steht
exakt bei jedem Befehl drinnen, welche Flags wie verändert werden. Hört
sich jetzt schlimmer an als es ist, weil Befehle ja in Gruppen/Familien
auftauchen und normalerweise alle Befehle aus einer Familie sich gleich
verhalten. Aber anders geht es nicht - wenn du ausbilden willst.
Ralf G. schrieb:> Wait ist einfach nur eine Warteschleife von 5 ms.
'einfach' ist in Assembler gar nichts.
Verändert 'Wait' die Flags oder tut es das nicht? Das ist die Frage, der
du dich stellen musst.
Derjenige, der Wait geschrieben hat, kann darauf geachtet haben, da
nichts zu verändern. Kann ... aber muss nicht. Ergo muss man das
kontrollieren.
> Diese habe ich erstmal
Mit 'erst mal nur reingemacht' kannst du ein funktionsfähiges
Assemblerprogramm ganz schnell vom Zustand "geht" in den Zustand "geht
nicht" überführen, wenn du dir nicht absolut und 100% sicher bist,
welche Nebenbedingunen bzw. Nebenwirkungen, wie zb die Veränderung von
Zero/Carry Flag deine Änderung hat.
Ralf G. schrieb:> btfsc STATUS,C ; Wenn Carry-Bit=0 überspringe nächsten Befehl
So wird das nix.
Druck Dir
TABLE 7-2: PIC16CXXX INSTRUCTION SET
aus und lege es Dir auf den Tisch.
Und dann schau nach, welcher Befehl das C setzen kann.
Tip: keiner, den Du bisher verwendest.
Und außerdem hilft Dir das C nicht. Es würde erst gesetzt, wenn Du zu
weit zählst.
Hallo Ralf,
du fragst ein Status-Flag (ich sge mal nichts dazu ob es das richtige
ist) zu einem Zeitpunkt ab, wo es nicht den erwarteten Zustand aufweist.
Die Abfrage eines Status-Flag muss direkt nach dem Befehl erfolgen, der
es beeinflusst. Einzige Ausnahme sind Befehle, die das jeweilige
Status-Flag unbeeinflusst lassen. Ich sehe zwar die Implementierung
deiner 'wait' nicht, weis aber auch so dass darin Operationen vorkommen,
die auf die Status-Flags wirken. Du musst also umstellen.
Kommst du damit weiter?
Grüße,
Edson
Ralf G. schrieb:> Ich will nicht, dass mir jemand> nen Programm schreibt, sondern meinen Fehler finden.
Bei Microchip gibt es das PICmicro™ Mid-Range MCU Family Reference
Manual, man kann es sich dort herunter laden. Das Dokument heißt
33023a.pdf. In den Datenblättern z.B. zum PIC12F675 wird an manchen
Stellen auch dort hin verwiesen.
Auf jeden Fall wird dort der Befehlssatz noch mal etwas detaillierter
erklärt. Section 29: Instruction Set.
Vielen Dank ersteinmal!
Das mit den Status abfragen hat nicht geklappt. Habs jetzt mit incfsz
und decfsz realisiert, nachdem ich mir nochmal die genaue Funktion
angeschaut habe.
Ralf G. schrieb:> Das mit den Status abfragen hat nicht geklappt. Habs jetzt mit incfsz> und decfsz realisiert, nachdem ich mir nochmal die genaue Funktion> angeschaut habe.
Die Befehle incfsz und decfsz enthalten ebenfalls Abfragen über ein
Status-Flag, und zwar in beiden Fällen das Zero-Flag.
Semantisch ist
1
incfsz0x20,f
2
gotoanywhere
äquivalent zu
1
incf0x20,f
2
btfssSTATUS,Z
3
gotoanywhere
Du hast in deinem Code vorhin nicht Z sondern C abgefragt.
M. H. schrieb:> Kann es sein, dass incf das Carry Flag nicht beeinflusst? Probier mal> statt dem Carry beim hinaufzählen das Zero-Flag zu testen.
Nachdem hatte ich das bereits geändert. Hat aber trotzdem irgendwie
nicht richtig funktioniert, er hatte dann nurnoch heruntergezählt.
Ich frage mich jetzt nur, weshalb die "Stufen" so grob sind? Müsste doch
meinem Verständnis nach pro Bit eine Stufe, also 256 sein...
Erst habe ich vermutet es sei der Takt vom DAC0808 - Stimmt aber nicht.
Hier der Schaltplan von meiner DAC Platine. Der PIC ist auf nem fertigen
Modul, gehe also nur mit ner Flachbandleitung mit GND,VCC und den 8 Bit
zum DAC. Die externen -15V hängen natürlich an der selben Masse.
Ralf G. schrieb:> Was soll D3 sein?! Gibts weder beim PIC noch beim DAC
Nicht so verbissen sein, was könnte ich wohl meinen?
Der ADC muß doch mit dem MC verbunden sein (8 Datenleitungen = D7 ..
D0).
Ralf G. schrieb:> Ich frage mich jetzt nur, weshalb die "Stufen" so grob sind?
Ich habe etwas Probleme mit der Interpretation des Oszi-Bildes: Die
einzelnen "Stücke" sind doch schräg und keine Stufen!
Kann es sein, dass du 2-kanalig im Multiplexbetrieb arbeitest, was diese
Lücken erzeugen kann? Wenn ja, schalte mal auf 1 Kanal oder auf
"Alternate".
Woher das Doppelbild herkommt, ist auch noch komisch... Es könnte daher
durchaus ein Messfehler sein.
Gruß Dietrich
So würde es aussehen, wenn D3 immer auf low liegt (wenn D3 immer auf
high liegt ist das Signal um 8 Werte in Y-Richtung verschoben).
Mess mal mit dem Oszi ob alle Signale (besonders D3) am D/A-Wandler
ankommen. Wenn alle Signale da sind, dann ist vielleicht der Wander
defekt.
Gruß
John
Klaus schrieb:> Irgenwann habe ich aufgehört, mir über sowas Gedanken zu machen, und>> myCounter++;>> geschrieben.
Tja, reicht nicht.
Auch in C mußt du ne Schleife hinlegen und per Abbruchkriterium in den
anderen Zweig (rauf versus runter zählen) hupfen.
W.S.
Welche befehle wie welche Bit's beeinflusse lässt sich auf der sehr
aufwendigen Homepage
http://www.sprut.de/electronic/pic/assemble/befehle.html wunderbar auf
Deutsch und verständlich nachlesen. Ich arbeite mit PIC und nur in
Assembler, diese Homepage http://www.sprut.de/electronic/pic/index.htm
hat mich dabei schon oft zum Verständnis und der Lösung eines Problems
geführt.
Ein eher allgemeiner Tip zum Thema Assembler und der Arbeit damit.