Forum: Mikrocontroller und Digitale Elektronik PIC Assembler auf- abzählen


von Ralf G. (Gast)


Lesenswert?

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

von chris (Gast)


Lesenswert?

1
Main
2
  clrf 0x20
3
  decf 0x20
4
Loop1
5
  incf  0x20,1
6
  movf  0x20,0
7
  movwf  PORTB
8
  call  Wait
9
  btfss 3,0
10
  goto  Loop1
11
Loop0
12
  decf  0x20,1
13
  movf  0x20,0
14
  movwf  PORTB
15
  call  Wait
16
  btfss 3,0
17
  goto  Loop0
18
  goto  Loop1

von chris (Gast)


Lesenswert?

Sorry, falsch geht, nicht. so sollte es gehen
1
Main
2
  clrf 0x20
3
Loop1
4
  movf  0x20,0
5
  movwf  PORTB
6
  call  Wait
7
  incfsz  0x20,1
8
  goto  Loop1
9
  decfsz  0x20,1
10
Loop0
11
  movf  0x20,0
12
  movwf  PORTB
13
  call  Wait
14
  decfsz 0x20,0
15
  goto  Loop0
16
  goto  Loop1

von chris (Gast)


Lesenswert?

decfsz  0x20,1
Loop0

sollte sein:

  decfsz  0x20,1
  decfsz  0x20,1
Loop0

von Ralf G. (Gast)


Lesenswert?

Also so?
1
Main
2
  clrf 0x20
3
Loop1
4
  movf  0x20,0
5
  movwf  PORTB
6
  call  Wait
7
  incfsz  0x20,1
8
  goto  Loop1
9
  decfsz  0x20,1
10
  decfsz  0x20,1
11
12
Loop0
13
  movf  0x20,0
14
  movwf  PORTB
15
  call  Wait
16
  decfsz 0x20,0
17
  goto  Loop0
18
  goto  Loop1
Tut mir leid, aber ich kann dir nicht ganz folgen.

von Ralf G. (Gast)


Lesenswert?

Was genau heißt beim DECFSZ/INCFSZ befehl die Zahl hinterm Komma? In der 
übersicht die ich hier im Buch habe ist das sehr unschön erklärt..

von GroberKlotz (Gast)


Lesenswert?

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

von GroberKlotz (Gast)


Lesenswert?

Hallo,
Habe erst jetzt den ganzen Threat gelesen...

Probieres doch mit nachstehenden Unterprogrammen. Anstatt der Zähler 
cntUp bzw. cntDWN, kanst Du ja jedes andere 8bit-Register oder eine 
Variable Deiner Wahl (z.B. PORTB)  verwenden. Zwischen den Schleifen 
Loop-Goto fügst Du Deine Wartezeiten ein.

COUNT_UP                   ;zählt aufwärts
    clrf    cntDWN         ;Abwärtszähler auf 0 setzen
CountUp_Loop:
    incf    cntUp,F        ;Zähler + 1
    btfss   STATUS,C       ;Carrybit=1? Zählerüberlauf?
    CALL    CountDOWN      ;JA, rückwärtszählen
    GOTO    CountUp_Loop   ;NEIN, weiter aufwärts zählen
RETURN

COUNT_DOWN                 ;zählt abwärts
    movlw   0xFF
    movwf   cntDWN         ;Startwert zuweisen
CountDown_Loop:
    decfsz  cntDWN,F       ;Zähler-1, Zerobit=1? Zähler=0?
    CALL    CounterUP      ;JA, wieder aufwärtszählen
    GOTO    CountDown_Loop ;NEIN weiter abwärts zählen
RETURN

mfG GroberKlotz

von W.S. (Gast)


Lesenswert?

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.

von Klaus (Gast)


Lesenswert?

Irgenwann habe ich aufgehört, mir über sowas Gedanken zu machen, und

myCounter++;

geschrieben.

MfG Klaus

von Ralf G. (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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:
1
int main()
2
{
3
  uint8_t val = 0, step = 1;
4
  for(;;){
5
    PORTB = val;
6
    wait();
7
    val += step;
8
    switch( val ){
9
      case 0:
10
      case 255: step = -step;
11
    }
12
  }
13
}

und gut is.

von Ralf G. (Gast)


Lesenswert?

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!

von Chris (Gast)


Lesenswert?

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

von Max H. (hartl192)


Lesenswert?

Kann es sein, dass incf das Carry Flag nicht beeinflusst? Probier mal 
statt dem Carry beim hinaufzählen das Zero-Flag zu testen.

von Ralf G. (Gast)


Lesenswert?

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?

von Max H. (hartl192)


Lesenswert?

Wenn du Eins addierst und du hast einen Überlauf, geht das Register auf 
null.

von Peter D. (peda)


Lesenswert?

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.

von Ralf G. (Gast)


Lesenswert?

Bringt mir bei meinem momentanen Stand nichts, weil ich dann ja direkt 
wenn ich aus der schleife raus komme, wieder zurück springen würde oder?

1
Main
2
  btfsc  STATUS,Z    ; Wenn Zero-Bit=0 überspringe nächsten Befehl
3
  goto  hoch    ; Wenn Ergebnis = 0 (Z=1)
4
  goto  runter    ; Wenn Ergebnis!= 0 (Z=0)
5
6
7
hoch
8
  incf    0x20,1    ; + 1
9
    movf    0x20,0    ; 
10
    movwf    PORTB    ; Ausgeben
11
    call    Wait    ; Warten
12
  btfsc  STATUS,C    ; Wenn Carry-Bit=0 überspringe nächsten Befehl
13
  goto  hoch    ; Wenn Kein Überlauf
14
  goto  Main    ; Wenn Überlauf
15
16
runter
17
  movlw  0xFF    ; 
18
  movwf  0x20    ; 0x20 --> 11111111
19
  goto  runterzähler  
20
21
runterzähler
22
  decf  0x20,1    ; -1
23
  movf    0x20,0    ;
24
    movwf    PORTB    ; Ausgeben
25
    call    Wait    ; Warten
26
  btfsc  STATUS,Z    ; Wenn Zero-Bit=0 überspringe nächsten Befehl
27
  goto  Main    ; Wenn Ergebnis = 0 (Z=1)
28
  goto  runterzähler  ; Wenn Ergebnis!= 0 (Z=0)

von Ralf G. (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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

von Max H. (hartl192)


Lesenswert?

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

von Ralf G. (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

von Meister E. (edson)


Lesenswert?

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

von Wilhelm F. (Gast)


Lesenswert?

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.

von Ralf G. (Gast)


Lesenswert?

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.

von Meister E. (edson)


Lesenswert?

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
   incfsz   0x20, f
2
      goto   anywhere

äquivalent zu
1
   incf   0x20, f
2
   btfss  STATUS, Z
3
      goto   anywhere

Du hast in deinem Code vorhin nicht Z sondern C abgefragt.

von Ralf G. (Gast)


Lesenswert?

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.

von Ralf G. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

D3 ist unterbrochen oder hat Kurzschluß zu VCC/GND.

von Ralf G. (Gast)


Lesenswert?

Was soll D3 sein?! Gibts weder beim PIC noch beim DAC

von Max H. (hartl192)


Lesenswert?

Er will dir damit sagen, dass du den Schaltplan posten sollst.

von Ralf G. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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).

von Ralf G. (Gast)


Lesenswert?

Sorry war etwas verwirrt xD und die Datenleitungen hab ich alle nochmal 
nachgeschaut.. nichts

von Dietrich L. (dietrichl)


Lesenswert?

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

von John (Gast)


Angehängte Dateien:

Lesenswert?

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

von Max H. (hartl192)


Lesenswert?

Wird das Sägezahn signal bei der selben Schaltung richtig ausgegeben? 
Wenn ja , dann ist es kein oHardware problem

von Dietrich L. (dietrichl)


Lesenswert?

John schrieb:
> So würde es aussehen,

Sehr gut! Das erklärt das Oszi-Bild ja vollständig.
Ich nehme meinen Interpretationsversuch hiermit zurück ...

von W.S. (Gast)


Lesenswert?

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.

von Ralf G. (Gast)


Lesenswert?

Fehler gefunden!
Flachbandkabel hatte an einer Leitung keinen Kontakt zum 
Steckverbinder..
Somit stimmte das mit D3.
Herzlichen Dank an alle!

von Assemblerbenutzer (Gast)


Lesenswert?

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.

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.