Forum: Mikrocontroller und Digitale Elektronik Verständnisfrage PIC-Stack


von Jens P. (Gast)


Angehängte Dateien:

Lesenswert?

Hi Leute, mal ne frage: Ich darf ja nur max 8 unterprogramme schachteln.

Ist ein Unterprogramm nun nur etwas, was ich per call aufrufe oder auch 
durch goto bedignte sprünge?

falls gotos auch als unterprogramme zählen, wie könnte ich denn dann so 
eine abfrage wie im angehängten programm ansonsten gestalten?

falls jemand zufällig einen sonstigen fehler entdeckt, bin ich sehr 
dankbar, aber ich kämpf mich auch gern alleine durch. das programm soll 
eigentlich auf einer 7-segmentanzeige hochzählen. zeigt aber nur 001 an 
und das wars. irgendwas läuft halt ned richtig.


thx and greets, Jens

von Cypress (Gast)


Lesenswert?

Hi,
GOTOs sind keine Unterprogrammaufrufe! Der Stack wird vollkommen in Ruhe 
gelassen und nur ein neuer Wert in den PC (programm counter) geladen.

Cheers

von Florian (Gast)


Lesenswert?

Betrifft nur call:

Call Subroutine. First, return
address (PC+1) is pushed onto
the stack. The eleven-bit immediate
address is loaded into PC bits
<10:0>. The upper bits of the PC
are loaded from PCLATH. CALL is
a two-cycle instruction.



Anstatt
    movlw  B'00000000'
    movwf  PORTA
    movwf  PORTB
    movwf  PORTC
    movwf   PORTD
    movwf  PORTE
kannst Du
  clrf PORTA
  clrf PORTB
  clrf PORTC
  clrf PORTD
  clrf PORTE

nehmen --- einen Befehl und ein wenig Zeit gespart.


Dein Konstrukt zum Ausgeben der Ziffern ist doch ein wenig 
umständlich.

Es geht hier um Pressetabelle.

Was hältst Du denn von einem Konstrukt wie (ungetestet):
1
    clrf Ziffer1 ; Ziffern auf 0 setzen
2
    clrf Ziffer2
3
    clrf Ziffer3
4
5
Z1
6
    movf Zahl,0   ; Zahl nach W holen
7
    addlw D'156' ; 100 von W abziehen 
8
                 ; Bei Fragen bitte nachrechnen
9
    btfsc STATUS, Z ; wenn Zero-Bit nicht gesetzt, nächste Anweisung
10
                   ; überspringen
11
    goto Z2      ; also nur zu Z2, wenn die Subtraktion 0 ergab
12
    
13
    btfsc STATUS, C 
14
    goto Z2      ; oder wenn Carry gesetzt ist (= Überlauf oben)
15
16
    ; geht sicher auch schöner, nur fällt mir das im Moment nicht 
17
    ; ein --- es ist ja schon spät
18
19
    movwf Zahl   ; Ergebnis zurückschreiben
20
    incf Ziffer1,1 ; Ziffer1 erhöhen
21
    goto Z1      ; und weitermachen
22
23
Z2
24
    movf Zahl,0   ; Zahl nach W holen
25
    addlw D'246' ; 10 abziehen
26
    btfsc STATUS, Z ; wenn Zero-Bit nicht gesetzt, nächste Anweisung
27
                   ; überspringen
28
    goto Z3      ; also nur zu Z3, wenn die Subtraktion 0 ergab
29
    
30
    btfsc STATUS, C 
31
    goto Z3      ; oder wenn Carry gesetzt ist (= Überlauf oben)
32
33
    movwf Zahl   ; Ergebnis zurückschreiben
34
    incf Ziffer2,1 ; Ziffer2 erhöhen
35
    goto Z2      ; und weitermachen
36
    
37
38
Z3
39
    movf Zahl,0   ; Zahl nach W holen
40
    movwf Ziffer3 ; und als Ziffer3 speichern

Mit Umlauten und Sonderzeichen in den Label-Namen wäre ich persönlich 
vorsichtig, allerdings weiß ich nicht, ob das vielleicht doch 
unproblematisch ist.

Mit 'movfw' würde ich vorsichtig sein, da es vom Compiler abhängt, wie 
er damit umgeht. In der Doku heißt es:

MOVF Move f
Syntax: [ label ] MOVF f,d
Operands: 0 ≤ f ≤ 127
d ∈ [0,1]
Operation: (f) → (destination)
Status Affected: Z
Description: The contents of register f are
moved to a destination dependant
upon the status of d. If d = 0,
destination is W register. If d = 1,
the destination is file register f itself.
d = 1 is useful to test a file register,
since status flag Z is affected.

Dein Programm läuft übrigens aus folgendem Grund nicht richtig:

M1  incf   zahl, 1          ; Erhöhe Zahl um eins und Speichere in Zahl
  call   Presettabelle
M2  call  Anzeigeschleife


es fehlt ein simples goto, um wieder zu M1 zu kommen. Effektiv wird es 
zum das nachfolgende BCD einen Return zu irgendeiner Adresse ausführen 
und dann passieren komische Dinge.

Gruß,

Florian

von Jens P. (Gast)


Lesenswert?

Danke für deine Ausführlichen erklärungen. habe zwar jetzt auf die 
schnelle noch nicht alles verstanden, werds mir aber heut abend nochmal 
genauer anschauen.

aber ein goto auf M1 habe ich ja in der anzeigeschleife. oder meinst da 
müsste trotzdem noch eins drunter?

von Florian (Gast)


Lesenswert?

Habe ich übersehen.

Allerdings ist das kein goto auf M1, sondern auf MAIN und da wird die 
Zahl wieder zurückgesetzt.

Stattdessen sollte allerdings ein retlw da hin, da Du die Routine ja mit 
call aufrufst.

Mir ist nicht ganz klar, was Du mit

  movlw  D'128'          ; Lade Grenzwert in Akku
  subwf  zahl, 0          ; Subtrahiere W von Zahl und Speichere in W
  btfsc  STATUS, Z        ; Überspringe nächsten Befehl wenn nicht null
  goto  MAIN          ; wieder von ganz vorne beginnen

  bcf    STATUS, Z        ; Zero-Bit zurücksetzen

bezwecken willst.

In Deiner Schleife (wenn Sie denn da wäre) um M1 wird die Zahl 
hochgezählt und Anzeigeschleife stellt die Ziffern eine bestimmte Zeit 
dar. Eigentlich hat die doch nichts mit der Zahl an sich zu tun.

Also
1
M1  incf   zahl, 1          ; Erhöhe Zahl um eins und Speichere in Zahl  
2
  call   Presettabelle
3
  call  Anzeigeschleife
4
        goto    M1
5
6
...
7
Anzeigeschleife
8
  movlw  D'127'            ; Anzahl Aufrufe Subroutine
9
  movwf  durchg  
10
11
  clrf  PORTE
12
  clrf  PORTC
13
  
14
A1  bsf    PORTE, 0        ; Segment eins aktiv
15
  movfw  Ziffer1          ; Wert Ziffer 1 laden
16
  call  BCD            ; BCD-Auswertung
17
  movwf  PORTC          ; 7-Segmentanzeige beschreiben
18
  call  WAIT          ; 1ms Warten
19
  
20
  bcf    PORTE, 0
21
  bsf    PORTE, 1          
22
  movfw  Ziffer2    
23
  call  BCD
24
  movwf  PORTC
25
  call   WAIT
26
  
27
  bcf    PORTE, 1
28
  bsf    PORTE, 2
29
  movfw  Ziffer3
30
  call  BCD
31
  movwf  PORTC
32
  call  WAIT
33
  bcf    PORTE, 2
34
  
35
  
36
  decfsz  durchg, F        ; durchgang um eins vermindern, wenn null ist 
37
                  ; nächsten befehl überspringen
38
  goto  A1            ; wenn nein gehe wieder zu A1
39
  retlw  D'0'

So sollte (auch mit Deiner komplizierten Auswertung) eigentlich 
hochgezählt und angezeigt werden.

Übrigens nebenbei:
Du musst das Zero- oder Carry-Flag nicht jedesmal zurücksetzen, da Die 
Anweisung wie z.B. subwf das Fläg überschreiben.

von gravewarrior (Gast)


Lesenswert?

ok, danke soweit. das ich das flag nich zurücksetzen muss is auch gut zu 
wissen (habs mir fast gedacht, wollt aber auf nummer sicher gehen) die 
zusätzliche Subtraktion/auswertung in meiner anzeigeschleife rührt daher 
das es ab 128 wieder mit 0 anfangen soll, also ganz zurück zur main.

die auswertung is deshalb so aufwändig, weil da später noch einiges in 
die einzelnen parts soll (also noch EEPROM-Variablen setzen, EDIT-Modus 
bedienen usw. das is nur das ganz grundsätzliche skellet zum 
ausprobieren. is dann ium endeffekt natürlich auch was ganz anderes als 
n programm das von selbst rumzählt ;-)

vielen dank auf jeden fall! greets, JEns

von Jens P. (Gast)


Lesenswert?

also irgendwie ändert sich auch durch das temporäre abschalten des 
abfragens nach der programmnummer in der anzeigeschleife und nach dem 
einfügen des fehlenden gotos auch nichts. schon seltsam.

greets, Jens

von Jens P. (Gast)


Angehängte Dateien:

Lesenswert?

hier nochmal der aktuelle code ( in dem die angesprochenen sachen schon 
geändert wurden)

von Florian (Gast)


Lesenswert?

Also du siehst immer noch 001? Ich kann Dir nur empfehlen, den Code mal 
in der MPLAB IDE durchzusteppen. Da wirst Du das Problem sehen.

Nochmal zu Deiner Abfrage:

Wenn du wirklich einzelne Label brauchst, dann würde ich das so ähnlich 
wie Deine Funktion BCD (hast Du vermutlich aus dem Netz, oder?) machen, 
also etwa so:

Pressetabelle clrf  Ziffer1
        clrf  Ziffer2
         clrf  Ziffer3

        movf zahl, W
  addwf   PCL,f
        goto Null
        goto Eins
        ...

Dann aber aufpassen, dass ungültige Werte vorher aussortiert werden 
(also Werte > Deines letzten Labels).

Und so ungefähr dann weitermachen:
Null   movlw D'0'
       movwf Ziffer1
       retlw D'0'

Eins   movlw D'1'
       movwf Ziffer1
       retlw D'0'


Wenn 001 angezeigt wird, heißt das erstmal, dass die Funktion 
Anzeigeschleife soweit läuft (es werden ja nacheinander die Segmente 
angesteuert). Jetzt könnte es entweder sein, dass die Funktion nicht 
verlassen wird (Endlosschleife) oder Deine Auswertung nicht richtig 
funktioniert. Hast Du das mal mit der von mir vorgeschlagenen Auswertung 
probiert?

von Jens P. (Gast)


Lesenswert?

die von dir vorgeschlagene variante hab ich noch nicht durch. ja, die 
BCD-tabelle ist recht eng an spruts variante angelehnt. Welchen vorteil 
hat deine varinte der abfrage denn genau? weniger code, oder? und eine 
übersichtlichere tabelle, oder?

Das mit dem durchsteppen ist so ne sache. ich hab auch schon dran 
gedacht, aber keine ahnung davon wie. gibt es da irgendwo ne 
verständliche beschreibung?(vielleicht sogar auf deutsch?)  das wäre mir 
ne rießen-hilfe.

als elektroniker kann ich mit meinen messgeräten umgehen, dann würd ich 
auch gerne als "programmierer" (nennen wirs elektroniker mit notwendigem 
übel ;-) )
debuggen und selber suchen können.


Auf jeden fall mal vielen vielen dank für deine hilfe!

von Florian (Gast)


Lesenswert?

Die Abfrage-Variante hat deutlich weniger Code. OK, es kommt darauf an, 
was Du überhaupt am Ende machen möchtest aber der Speicherplatz im PIC 
ist endlich. Ich habe jetzt lange schon nichts mehr mit PICs gemacht, 
aber ich meine mich erinnern zu können, dass man in der IDE einfach auf 
Debug stellen konnte und dann den PIC am Rechner simulieren konnte. Ich 
meine, das wäre alles mit der MPLAB IDE gegangen. Wenn Du die sowieso 
benutzt, dann hast Du doch bestimmt schon die Device-Einstellungen 
vorgenommen und so sollte das kein großen Problem sein.

Was Anleitungen in Deutsch angeht: Es hat sich im Laufe der Zeit in 
vielen Bereichen die englische Sprache etabliert, um so einen weiteren 
Kreis von Menschen anzusprechen. Wer heutzutage des Englischen nicht 
oder nur schlecht mächtig ist, hat leider schlechte Karten (ich sehe das 
an meinen Eltern). Leider gibt es aber auch immer mehr Leute, die der 
deutschen Sprache, obwohl sie Muttersprachler sind, nicht mächtig sind 
(auf meinem Weg zum Einkaufen muss ich an einer Fahrschule vorbei, die 
auf Ihrer Scheibe groß 'Außbildung' stehen hat --- grausam), aber das 
ist ein anderes Thema.

Ich könnte leider nur soetwas anbieten:
http://ww1.microchip.com/downloads/en/DeviceDoc/51410b.pdf

Auf Deutsch ist weniger zu finden:
http://www.fh-sw.de/sw/fachb/et/halbl/ProjektMux/mux.html

Da steht aber auch etwas zum Thema Debugging.

von Jens P. (Gast)


Lesenswert?

vielen dank! das mit dem englisch is mir eigentlich auch klar. verdien 
ja meine brötchen auch in der elektronik. auf deutsch (sofern vorhanden) 
tut man sich eben doch etwas leichter.

aber danke für die links!

PS: Bedienungsanleitungen auf Niederländisch rulen ;-)

von Florian (Gast)


Lesenswert?

Mir ist es auch schon häufiger passiert, dass ich deutsche E-Mails auf 
englisch beantwortet habe. Wenn man jeden Tag englisch korrespondiert, 
fällt einem das irgendwann nicht mehr auf, was allerdings nicht 
bedeutet, dass man nicht auch das ein oder andere Mal zum Wörterbuch 
greifen muss, wenn es um etwas 'Branchenfremdes' geht.

von Jens P. (Gast)


Lesenswert?

Ich habs! Danke, das durchsteppen hat echt geholfen. ich hab zwar noch 
nicht den dreh raus mir beim steppen variablen anzeigen zu lassen, oder 
irgendwie einfach alles als breakpoint zu markieren, aber das einfache 
steppen und zusehen hat mich draufgebracht. der fehler lag in der 
presettabelle. bei wert null war alles noch perfekt, aber ab wert eins 
habe ich ausversehen (und per C und P dann natürlich ab dort überall) 
statt zahl und zahlh auf einmal zahl und zahl subtrahiert. das das 
natürlich immer wahr ist und deswegen immer eins als richtig erkannt 
wird ist klar ;-)

naja, als anfänger muss man durch sowas durch. aber mit dem debugen muss 
ich mich echt noch etwas mehr beschäftigen. da kommt man wirklich gut 
vorwärts mit (auch wenn die bedienung recht unübersichtlich ist)


DANKE auf jeden fall mal wieder an dich/euch.

Finds echt klasse, dass man hier noobs so gut zur seite steht ;-)

baut doch mal n bissel e-gitarren-equipment, da kann ich dann helfen ;-)

von Ralf M. (Firma: Titel) (ego)


Lesenswert?


von Jens P. (Gast)


Lesenswert?

DANKE!

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.