Hallo zusammen,
ich hoffe ihr könnt mir weiterhelfen...
Ich bin gerade dabei einen Praktikumsversuch zu bewältigen und hänge an
einer Stelle.
Ich möchte mit zwei Schalter (Bestandteile des Simulators) dazu benutzen
eine Geschwindigkeit zu erhöhen und zu veringern. Dieser Fahrsteller hat
16 Stufen (0..15). Der Schalter P4.0 erhöht die Geschwindigkeit in
Einerschritten und der Schalter P4.7 verringert die Geschwindigkeit in
Einerschritten, der Wertebereich 0..15 daf aber nicht verlassen werden.
Die Fahrstufen sollen zunächst als einfache Binärzahl (auch im
Simulator) am Port P4.5 ... P4.2 binär ausgegeben werden.
Bei mir klemmt es jetzt an dem Unterprogramm "speedAdjust:". Nach meinem
Verständnis (und das reicht noch nicht soweit) müsste schon etwas
ausgegeben werden.
So sieht das Programm bis jetzt aus. Danke für eure Hilfe im Voraus.
1
#include <PWB2000.h> // verwendete HW bekannt geben
2
3
// Funktionen veröffentlichen
4
public speedInit, speedAdjust, speedDisplay, checkSwitch, wait50ms
5
6
// Interface zu den Funktionen im ROM
7
lcdWrite code 0x8199 // R7=Row, DPTR=XDATA Buffer, show 16 chars
8
9
// Defines
10
sbit SW_DWN = P4^7; // switch downgrade speed
11
sbit SW_UP = P4^0; // switch accellerate speed
12
#define SW_MASK 0x81 // switch @ port P4 (1000 0001)
13
// P4: SW_UP - [speed (4 LEDs)] - SW_DWN
14
15
#define SW_DEBOUNCE_MS 50 // wait time after (possible) change in ms
16
#define LCD_SIZE 16 // chars each LCD line
17
#define LCD_TOTAL_SIZE (2*LCD_SIZE) // and totally
18
#define WAIT1MS 250 // @ 12MHz and 12 OscCycles
19
20
bseg at 0
21
// save last state of switch
22
23
dseg at 8 // behind register bank 0
24
// actual speed (0 - 15)
25
// but ASCII-Hi-Digit '0'...'1'
26
// but ASCII-Low-Digit '0'...'9'
27
28
xseg at 0x1000 // muss auf Adresse modulo 256 beginnen
29
lcdLine0: ds LCD_SIZE // [####------------]
30
lcdLine1: ds LCD_SIZE // [04 ]
31
32
cseg at 0x200 // Lücke zu main sollte groß genug sein
33
34
35
36
////////////////////////////////////////
37
// speedInit - Grundeinstellungen
38
// Wert wird nach Starten des Programms geladen
39
// Destroy: ?
40
////////////////////////////////////////
41
speedInit:
42
mov p4, #SW_MASK
43
mov b, p4 ; Variable b initialisieren
44
ret
45
46
////////////////////////////////////////
47
// wait50ms - Schalterentprellung
48
// 50ms warten, nachdem Schalter betätigt
49
// Destroy: A, R0, R1
50
////////////////////////////////////////
51
wait50ms:
52
53
mov r1, #SW_DEBOUNCE_MS
54
auSchl: ; Dauer: 501µs * 50 * 2 = 50,1 ms
55
mov r0, #WAIT1MS
56
innSchl: ; Dauer: 250µs * 2 + 1µs = 501µs
57
djnz r0, innSchl ; 2µs
58
djnz r1, auSchl ; 2µs
59
ret
60
61
////////////////////////////////////////
62
// slowdown - Register2 Minus 1
63
// wird von checkSwitch aufgerufen
64
// Destroy: A, R2
65
////////////////////////////////////////
66
slowdown:
67
68
dec r2
69
mov a, r2
70
ret
71
72
////////////////////////////////////////
73
// min - setzt R2 = 0
74
// wird von slowdown aufgerufen
75
// Destroy: R2
76
////////////////////////////////////////
77
min:
78
79
mov r2, #0 ; nach Programmstart Stufe 0 aktiv
80
ret
81
82
////////////////////////////////////////
83
// speedup - Register2 Plus 1
84
// wird von checkSwitch aufgerufen
85
// Destroy: A, R2
86
////////////////////////////////////////
87
speedup:
88
89
inc r2
90
mov a, r2
91
ret
92
93
////////////////////////////////////////
94
// max - setzt R2 = 15
95
// wird von speedup aufgerufen
96
// Destroy: R2
97
////////////////////////////////////////
98
max:
99
mov r2, #15 ; maximal 16 Fahrstufen
100
ret
101
102
////////////////////////////////////////
103
// checkSwitch - Schalterstellung testen
104
// (SW_DWN hat Priorität gegenüber SW_UP)
105
// Return R2: -1 slow down, 0 steady, 1 speed up
106
// Destroy: A, B, C
107
////////////////////////////////////////
108
checkSwitch:
109
xrl a, b
110
jbc acc.0, speedup
111
jbc acc.7, slowdown
112
ret
113
114
/***************************************
115
** speedAdjust - neue Geschwindigkeit einstellen
116
** Variablen speed, speedAscH und speedAscL sowie P4 aktualisieren
Hi,
ohne mir jetzt dein ganzes Programm angesehen zu haben, so hast du doch
bereits grundlegende Fehler in deinem geposteten Code. Die Stelle:
checkSwitch:
xrl a, b
jbc acc.0, speedup
jbc acc.7, slowdown
ret
ist fehlerhaft, weil du dort mit einem JUMP hinspringst. Die
entsprechenden Funktionen SPEEDUP und SLOWDOWN werden aber mit einem RET
beendet, was dir den Stackpointer verhagelt. Merke: Ein Unterprogramm,
welches durch ein RET beendet wird, MUSS immer mit einem CALL
aufgerufen werden, niemals mit einem JUMP.
Die korrekte Implementierung müsste eher folgendermassen lauten (ohne
Gewähr):
checkSwitch:
xrl a, b
jnb acc.0, cs1
inc r2
jmp cs2
cs1: jnb acc.7,cse
dec r2
cs2: mov a,r2
cse: ret
Mit dieser Variante fallen die beiden Routinen SPEEDUP und SLOWDOWN
komplett raus, was mir persönlich besser gefällt, da mit einem
Unterprogramm zwei zusammenhängende Funktionen bedient werden. Bei
größeren Funktionen sieht es natürlich anders aus.
Du kannst auch mit einzelnen Routinen arbeiten, aber dann musst du wie
bereits gesagt, mit CALL arbeiten!!!
Ralf
Es funktioniert immer noch nicht. Wenn ich auf Port 4.1 (Schalter S0)
drücke wie im Anhang gezeigt sollte eigentlich mit den LED's links
daneben (Kreise über den Schaltern S1 bis S6) die Binärzahl angezeigt
werden. Wenn ich auf den Schalter ganz links drücke sollte die Binärzahl
wieder inkrementiert werden.
Immer wenn der Schalter S1 oder S7 logisch 1 ist, soll die Binärzahl
incr. bzw. decr. werden. Habe das Programm nochmal umgeändert:
1
#include <PWB2000.h> // verwendete HW bekannt geben
2
3
// Funktionen veröffentlichen
4
public speedInit, speedAdjust, speedDisplay, checkSwitch, wait50ms
5
6
// Interface zu den Funktionen im ROM
7
lcdWrite code 0x8199 // R7=Row, DPTR=XDATA Buffer, show 16 chars
8
9
// Defines
10
sbit SW_DWN = P4^7; // switch downgrade speed
11
sbit SW_UP = P4^0; // switch accellerate speed
12
#define SW_MASK 0x81 // switch @ port P4 (1000 0001)
13
// P4: SW_UP - [speed (4 LEDs)] - SW_DWN
14
15
#define SW_DEBOUNCE_MS 50 // wait time after (possible) change in ms
16
#define LCD_SIZE 16 // chars each LCD line
17
#define LCD_TOTAL_SIZE (2*LCD_SIZE) // and totally
18
#define WAIT1MS 250 // @ 12MHz and 12 OscCycles
19
20
bseg at 0
21
// save last state of switch
22
23
dseg at 8 // behind register bank 0
24
// actual speed (0 - 15)
25
// but ASCII-Hi-Digit '0'...'1'
26
// but ASCII-Low-Digit '0'...'9'
27
28
xseg at 0x1000 // muss auf Adresse modulo 256 beginnen
29
lcdLine0: ds LCD_SIZE // [####------------]
30
lcdLine1: ds LCD_SIZE // [04 ]
31
32
cseg at 0x200 // Lücke zu main sollte groß genug sein
33
34
35
36
////////////////////////////////////////
37
// speedInit - Grundeinstellungen
38
// Wert wird nach Starten des Programms geladen
39
// Destroy: ?
40
////////////////////////////////////////
41
speedInit:
42
mov p4, #SW_MASK
43
mov b, p4 ; Variable b initialisieren
44
ret
45
46
////////////////////////////////////////
47
// wait50ms - Schalterentprellung
48
// 50ms warten, nachdem Schalter betätigt
49
// Destroy: A, R0, R1
50
////////////////////////////////////////
51
wait50ms:
52
53
mov r1, #SW_DEBOUNCE_MS
54
auSchl: ; Dauer: 501µs * 50 * 2 = 50,1 ms
55
mov r0, #WAIT1MS
56
innSchl: ; Dauer: 250µs * 2 + 1µs = 501µs
57
djnz r0, innSchl ; 2µs
58
djnz r1, auSchl ; 2µs
59
ret
60
61
////////////////////////////////////////
62
// checkSwitch - Schalterstellung testen
63
// (SW_DWN hat Priorität gegenüber SW_UP)
64
// Return R2: -1 slow down, 0 steady, 1 speed up
65
// Destroy: A, B, C
66
////////////////////////////////////////
67
checkSwitch:
68
mov a, p4
69
xrl a, b
70
jnb acc.0, mar1 ; wenn p4.1 gleich Null springe zu mar1
71
inc r2 ; inc r2
72
jmp mar2
73
mar1: jnb acc.7, mar2
74
dec r2
75
mov a, r2
76
mar2: mov a, r2
77
ret ; springe zu Unterprogramm speedAdjust
78
79
/***************************************
80
** speedAdjust - neue Geschwindigkeit einstellen
81
** Variablen speed, speedAscH und speedAscL sowie P4 aktualisieren
82
** Destroy: A, PSW, P4
83
***************************************/
84
speedAdjust:
85
86
mov p4, a ; Inhalt von a nach P4
87
88
ret
89
90
/***************************************
91
** speedDisplay - Ausgabe auf dem LCD
92
** Destroy: A, R4, R5, R6 , DPTR, P2, R0
93
** Call: lcdWrite, zerstört weitere Register
94
***************************************/
95
speedDisplay:
96
97
ret
98
99
end
Hier ist noch das Hauptprogramm mit dem Aufruf der Unterfunktionen.
1
// Interface zu den Funktionen im ROM
2
lcdInit code 0x8150 // initialize LCD, clear both lines