Forum: Mikrocontroller und Digitale Elektronik Programmcounter-Sprungbefehl


von Patrick O. (mrjack)


Lesenswert?

Hallo zusammen

Für einen Kollegen bin ich eine Anzeige für seinen Töff am entwickeln. 
Dies zeigt den aktuellen Gang, Liter im Tank und diverse weitere 
Eigentschaften an. Die Visualisierung verfolgt über eine 
7-Segmentanzeige (Ganganzeige sowie Tankanzeige) sowie eine 
Balkenanzeige (einfacher Tankpegel)
Bei der Anzeige der Liter habe ich jedoch noch irgeneinen Fehler drin.

Hier ist der Ausschnitt des Codes für die Literermittelung:
1
ADREAD          BSF  ADCON0,2      ;Tanklevel einlesen
2
WAITADC          BTFSC  ADCON0,2
3
    GOTO  WAITADC
4
    MOVFW  ADRESH
5
    MOVWF  ADWERT
6
    BTFSC  PORTA,2                       ;Wenn PortA 2 high ist Liter anzeigen
7
    GOTO  LITER
8
    BTFSS  ADWERT,1
9
    GOTO  LEVEL1
10
    GOTO  LEVEL2
11
12
LITER          BCF  STATUS,0      ;Carry-Bit löschen
13
    MOVFW  TANKST
14
    MOVWF  HILFSBYTE      
15
    CLRF  ADLOOP        ;Loop-Zahl löschen
16
LOOP          MOVFW  ADWERT        
17
    ADDWF  HILFSBYTE,w      ;AD-Wandlerwert ermitteln
18
    BTFSS  STATUS,0
19
    GOTO  ANZLITER      ;Falls detektiert anzeigen
20
    MOVLW  b'00000101'      
21
    ADDWF  ADLOOP,f      ;Loop 5 dazu addieren
22
    MOVFW  TANKST
23
    ADDWF  HILFSBYTE,f      ;nächster Tank-Schritt ermitteln
24
    GOTO  LOOP
25
26
;===========================   
27
;Tankpegel
28
;=========================== 
29
30
LEVEL1          BCF  PORTB,3
31
    BSF  PORTB,4
32
    GOTO  MAIN
33
34
LEVEL2          BSF  PORTB,3
35
    BSF  PORTB,4
36
    GOTO  MAIN
37
38
ANZLITER
39
    CALL  DISPL
40
    CALL  DELAY1
41
    MOVFW  ADLOOP
42
    ADDWF  PCL,f
43
LITER0
44
    CALL  DISP2        ;21Liter
45
    CALL  DELAY1
46
    CALL  DISP1
47
    CALL  DELAY1
48
    GOTO  MAIN
49
50
    CALL  DISP2        ;20Liter
51
    CALL  DELAY1
52
    CALL  DISP0
53
    CALL  DELAY1
54
    GOTO  MAIN
55
56
    CALL  DISP1        ;19Liter
57
    CALL  DELAY1
58
    CALL  DISP9
59
    CALL  DELAY1
60
    GOTO  MAIN
61
62
.......(immmer 5 Programmzeilen im Literschritt bis:
63
64
    CALL  DISP_        ;0Liter
65
    CALL  DELAY1
66
    CALL  DISP0
67
    CALL  DELAY1
68
    GOTO  MAIN

Die Literanzeige verändert sich fast nicht, wenn ich das Potentiometer 
am AD-Eingang maximal verstelle. Die einfache Balkenanzeige (Level1, 
Level2), welche immer angezeigt wird, funktioniert einwandfrei.
Irgendetwas bei der Modifikation des Programmcounters geht schief, 
konnte jedoch nicht herausfinden was...

Gruss

von Purzel H. (hacky)


Lesenswert?

Schon mal mit dem Simulator probiert. Da kann man singlesteppen.

von 17:15 (Gast)


Lesenswert?

Siebzehn Zu Fuenfzehn schrieb:
> Da kann man singlesteppen

...oha, sehr schönes Wort, solltest du mal für den neuen Duden 
einreichen

von Teo D. (teoderix)


Lesenswert?

Schon überprüft, ob all die Calls, innerhalb ihrer Reichweite liegen?!
Was ist eigentlich mit PCLATCH?
http://www.sprut.de/electronic/pic/grund/adress.htm#pcl


Nett wäre es auch, wenn Du mitteilen würdest, für welchen Prozessor das 
geschrieben wurde!

von Max H. (hartl192)


Lesenswert?

Patrick Oppliger schrieb:
> ADDWF  PCL,f
Das kann leicht schiefgehen, da du bis zu 100 Befehle überspringst. PCL 
ist nur 8bit breit und wenn PCL bei der Addition überläuft hast du dann 
eine Sprung zur falschen Adresse. Falls es ein
Enhanced Mid-range PIC ist würde ich den "BRW" Befehl empfehlen.

von Patrick O. (mrjack)


Lesenswert?

Ich verwende den PIC16F818. Habe leider im Moment noch eine steinalte 
Software auf meinem alten XP-PC, den ich für basteleien benötige, und 
die hat irgendwelche Probleme im Simulationsmodus.

Mir kam gerade ein anderer Lösungsansatz in den Sinn, bei welchem ich 
weniger grosse Sprungschritte machen muss. Probiere auch mal das ganze 
mit BRW (danke an Max H.!!)
Werde dies mal testen und mich dann wieder melden.

von Peter D. (peda)


Lesenswert?

Patrick Oppliger schrieb:
> .......(immmer 5 Programmzeilen im Literschritt bis:
>
>     CALL  DISP_        ;0Liter
>     CALL  DELAY1
>     CALL  DISP0
>     CALL  DELAY1
>     GOTO  MAIN

Sowas derart umständliches nennt man, die Hose mit der Kneifzange 
anziehen.

Warum schaust Du Dir nicht einfach mal an, wie alle anderen 
Programmierer Zahlen anzeigen?

Zuerst zerlegt man die Zahl in Zehner und Einer (z.B. 10 abziehen bis 
Unterlauf). Und dann greift man damit auf eine Tabelle zu, die den 
7-Segment Code für 0..9 beinhaltet (10 * RETLW).
Die beiden Ergebnisbytes kann man, wenns denn unbedingt sein muß, mit 
Delay ausgeben. Timerinterrupt ist natürlich besser, da flackerfrei.

von Patrick O. (mrjack)


Lesenswert?

Peter Dannegger schrieb:
> Patrick Oppliger schrieb:
>> .......(immmer 5 Programmzeilen im Literschritt bis:
>>
>>     CALL  DISP_        ;0Liter
>>     CALL  DELAY1
>>     CALL  DISP0
>>     CALL  DELAY1
>>     GOTO  MAIN
>
> Sowas derart umständliches nennt man, die Hose mit der Kneifzange
> anziehen.
>
> Warum schaust Du Dir nicht einfach mal an, wie alle anderen
> Programmierer Zahlen anzeigen?
>
> Zuerst zerlegt man die Zahl in Zehner und Einer (z.B. 10 abziehen bis
> Unterlauf). Und dann greift man damit auf eine Tabelle zu, die den
> 7-Segment Code für 0..9 beinhaltet (10 * RETLW).
> Die beiden Ergebnisbytes kann man, wenns denn unbedingt sein muß, mit
> Delay ausgeben. Timerinterrupt ist natürlich besser, da flackerfrei.

Ich habe meine 7-Segmentanzeige über 2 Ports verteilen müssen, damit die 
Stromversorgung von 100mA pro Port nicht überschritten wird. Für jede 
Anzeige, sei es ein Zeichen oder eine Zahl habe ich ein Unterprogramm 
mit den nötigen Zeilen geschrieben.

Damit ich das Programm simulieren kann, habe ich nun MPLAB v2.10 
installiert, jedoch kommt jedesmal beim Programmbuild ein Fehler: "DOS 
Error: Fail not found". Hatte dies auch schon jemand zuvor?

von Max H. (hartl192)


Lesenswert?

Patrick Oppliger schrieb:
> Probiere auch mal das ganze
> mit BRW (danke an Max H.!!)
Das wird nichts, der PIC16F818 ist zu alt und hat den Befehl nicht.

von Peter D. (peda)


Lesenswert?

Patrick Oppliger schrieb:
> Ich habe meine 7-Segmentanzeige über 2 Ports verteilen müssen

Ich mache das auch, wenn sich die Platine dadurch leichter routen läßt.
Ich schalte dann eine Routine dazwischen, die das Ausgabebyte auf die 
jeweiligen Pins verteilt (Bitbefehle).

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.