Hallo zusammen, Ich versuche schon den ganzen morgen diese Ansteuerung der Registerbänke in Assembler hinzubekommen aber es funktioniert nicht. Infos: - Mikrocontroller AT89S8253 - Compiler Ride 51 Ich schaffe es nicht z.b. Registerbank 1 zu verwenden anstatt Registerbank0 Nach meiner Auffassung muss ich zum verwenden einer anderen Registerbank nur RS0 und RS1 im PSW zu setzten/löschen. Jedoch funktioniert dann mein ganzes Programm nicht mehr. (Register sind beliebig zugeordnet) RS1 RS0 Registerbank Adressen im RAM 0 0 0 00 bis 07 0 1 1 08 bis 0F 1 0 2 10 bis 17 1 1 3 18 bis 7F Beispielprogramm: Include 51/reg51.inc ORG 0000H ;Speicheradressse 0 Start: SETB RS0 ;Registerbank 1 auswählen CLR RS1 MOV R1,#125 CLR RS0 ;Registerbank 2 auswählen SETB RS1 MOV R1,#50 SJMP Start
Bin nun schon weiter gekommen.. Dieses Problem der Registerbankauswahl tritt bei mir nur auf bei der Registerbank 1: SETB RS0 CLR RS1 Wieso??? Ist die Registerbank 1 etwas besonderes?
Gast
#1227207
Der Stackpointer vom 8051 wird mit 0x07 initialisiert, wenn du nun die Registerbank 1 auswählst, überschreibst du dir den Stack. Du solltest vielleicht mal posten was nicht mehr funktioniert, den an deinem Codefragment sieht man nicht viel.
Der Komplette Code ist im Anhang. Sorry wegen der Formatierung Ride macht dies ein wenig wie er will. Es soll eine Uhr werden die im Hintergrund eines anderen Programms läuft. Hier im Code verwende ich schon die Registerbank 2. Doch mit der Registerbank 1 funktioniert einfach nichts mehr bzw. es werden irgendwelche Werte seriell ausgegeben. Die Ausgabe geht seriell raus an Schieberegister welche dann 4x 7Segment Anzeigen treiben. nähere Infos zur Porterweiterungsplatine kann man auf meiner Beta Seite sehen http://elektronik-freaks.de/wordpress/ Aber wie kann es sein das die Adressen 0x07 zweimal vom Controller verwendet werden? Und wie kann ich das umgehen?
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | |
122 | |
123 | |
124 | |
125 | |
126 | |
127 | |
128 | |
129 | |
130 | |
131 | |
132 | |
133 | |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | |
143 | |
144 | |
145 | |
146 | |
147 | |
148 | |
149 | |
150 | |
151 | |
152 | |
153 | |
154 | |
155 | |
156 | |
157 | |
158 | |
159 | |
160 | |
161 | |
162 | |
163 | |
164 | |
165 | |
166 | |
167 | |
168 | |
169 | |
170 | |
171 | |
172 | |
173 | |
174 | |
175 | |
176 | |
177 | |
178 | |
179 | |
180 | |
181 | |
182 | |
183 | |
184 | |
185 | |
186 | |
187 | |
Gast
#1227432
>Aber wie kann es sein das die Adressen 0x07 zweimal vom Controller >verwendet werden? >Und wie kann ich das umgehen? In dem du den SP mit einem anderen Wert initialisierst. Oder du steigst auf C um, dann must du dich um den Stack & Register nicht mehr selber kümmern.
Gast
#1227545
Da RSO und RS1 ein bestandteil des PSW Registers ist solltest Du auch das PSW sichern. Also z.B.: Testroutine: PUSH PSW MOV PSW,#0001000b ; Umschaltung Registerbank 1 POP PSW RET Auf jedenfall vorher das PSW sichern in den Unteroutinen wo Du die Registerbankumschaltung machen willst. Wenn nicht kommt da nur heiloses durcheinander dabei raus.
Gast
#1227584
Sorry! So sollte es sein. Testroutine: PUSH PSW ORL PSW,#0001000b ; Umschaltung Registerbank 1 POP PSW RET
Klaus wrote: > Auf jedenfall vorher das PSW sichern in den Unteroutinen wo Du die > Registerbankumschaltung machen willst. Wenn nicht kommt da nur heiloses > durcheinander dabei raus. Ne das PSW lasse ich ja so wie es ist und manipuliere nur die zwei Bits RS0 und RS1. Der Rest bleibt ja so wie es war. Mars wrote: >In dem du den SP mit einem anderen Wert initialisierst. Wie soll ich das machen?? Ich benutze den Stack in meinem Programm ja garnicht. (nur die Interrupts und Unterprogramme) und diese können den oberen RAM Speicher niemals ausnutzten. Der Stack ist doch normal im oberen RAM oder irre ich mich da?
Gast
#1227638
Hallo Stefan, Du benutzt sehr wohl den Stack, oder wo meinst Du werden die Rücksrungadressen von ACALL und der Interruptroutine gespeicher ? Der Stack beim 8051 wird von unten nach oben gefüllt. Also wird die Registerbank 1 überschrieben. Andreas
Gast
#1227660
> Ne das PSW lasse ich ja so wie es ist und manipuliere nur die zwei Bits > RS0 und RS1. Der Rest bleibt ja so wie es war. Die Aussage ist in sich nicht lösbar, weil RS0 und RS1 Bits im PSW sind :) Ralf
Gast
#1227662
moin moin, nicht vergessen: Auch das CarrayFlag liegt im PSW! Daher, so wie Klaus beschrieben hat, immer mit Push/Pop PSW arbeiten. Alles andere ist ULK! mfg Pieter
Gast
#1227744
Hallo Stefan, die Speicheraufteilung beim 8051 ist gewöhnungsbedürftig und Du solltest Dir das genau ansehen. mov sp,#60h lagert Dir den Stack z.B. nach 60h aus. Im Anhang ein kleines Testprogramm das den Speicher mit Dummydaten beschreibt. Ich hab mal nen kleinen ICE für den 8051 gebaut und damit konntest Du dann den internen Speicher auch zu sehen bekommen. Der Screenshot zeigt das Ergebnis des Programms. Ab "start" kannst Du das Programm verwenden und Dir das Ergebnis auch in einem Simulator ansehen... vielleicht hilft ja ein Bild :-)
>die Speicheraufteilung beim 8051 ist gewöhnungsbedürftig und Du solltest >Dir das genau ansehen. Alles klar. Der Stack wird von von 08h standardmässig aufgefüllt. Das bedeutet er überschreibt als erstes Registerbank 1. Programm funktioniert, wenn ich den Stack mit mov sp,#30h auslager, da er dann oberhalb der vier Registerbänke und oberhalb der von mir verwendeten Direkt Bytes anfängt aufzufüllen. >Auch das CarrayFlag liegt im PSW! >Daher, so wie Klaus beschrieben hat, immer mit Push/Pop PSW arbeiten. >Alles andere ist ULK! Das Carrybit steht unter anderem im PSW. Aber wieso muss ich das ganze PSW sichern, wenn ich doch nur die Bits RS0, RS1 verändere?
Gast
#1228478
Hallo Stefan! Zumindest in der ISR solltest du alle Register, die du veränderst(PSW, ACC, DPT, ...) sichern, sonst kommt es zu unerklärlichen Fehlern. Warum das so ist kannst du dir ja selber überlegen. Grüße
Gast
#1228488
Nachtrag: Für Subroutinen kannst du dir ja selbst Konventionen, wie wie werden die Parameter übergeben, wo der Rückgabewert, welche Register dürfen verändert, welche müssen gesichert werden.
Stellt sich die Frage, ob man mit dieser Art der Banknutzung für globale Variablen überhaupt etwas gewinnt. Verlieren tut man in jedem Fall erstmal die Übersicht. Wo verschiedene Registerbänke sinnvoll sind, ist z.B. in Interrupts, dann spart man einiges an PUSH/POP. Im Main würde ich immer nur eine Bank benutzen und globale Variablen im Data-Bereich ablegen. Du könntest schonmal Speicher sparen, indem Du die Einer und Zehner zusammen in einem Byte speicherst. Dann wird auch der 24-Stunden Überlauf einfacher. Eine Beipiel-Uhrenroutine findest Du hier: http://www.mikrocontroller.net/attachment/49155/UHR.A51 Peter
>Zumindest in der ISR solltest du alle Register, die du veränderst(PSW, >ACC, DPT, ...) sichern, sonst kommt es zu unerklärlichen Fehlern. Sehr guter Tipp :D War bisher bei den einfachen Programmen nicht nötig doch es wird gerade sehr komplex THX >Stellt sich die Frage, ob man mit dieser Art der Banknutzung für globale >Variablen überhaupt etwas gewinnt. Ich denke auch weniger, doch habe ich bis heute noch nie wirklich mit Globalen Variablen gearbeitet bzw. noch nie mit dem RAM-Bereich überhalb 30h ^^ aber es würde vieles einfacher machen und mir vieleicht ein wenig Übersicht bringen. (wen's interessiert im Anhang die noch nicht laufende DCF77 Uhr, aber nicht erschrecken) >Du könntest schonmal Speicher sparen, indem Du die Einer und Zehner >zusammen in einem Byte speicherst. Dann wird auch der 24-Stunden >Überlauf einfacher. Der Überlauf schon aber um die Ziffern einzelnd an der 7-Segment Anzeige auszugeben müsste ich sie wieder auseinanderpfriemeln.
Gast
#1231265
> Der Überlauf schon aber um die Ziffern einzelnd an der 7-Segment Anzeige > auszugeben müsste ich sie wieder auseinanderpfriemeln. Nana, stell dir das nicht so schwer vor. Du löschst die oberen vier Bits weg, und konvertierst das Ergebnis in den Wert für die Anzeige. Für das obere Nibble machst du genau das gleiche, nur führst du vorher noch ein "swap a" aus, das vertauscht die Nibbles des Akkus. Wenn du dann noch den Wert für die Anzeige aus einer Tabelle holst, hast du doch schon alles. Ralf
Stefan S. wrote: > Der Überlauf schon aber um die Ziffern einzelnd an der 7-Segment Anzeige > auszugeben müsste ich sie wieder auseinanderpfriemeln. Im Prinzip richtig, aber bei großen Programmen wird das Leben bedeutend einfacher, wenn alle Rechnungen im Binärsystem (8, 16, 32 Bit) gemacht werden, das ist nämlich das Lieblingsformat der CPU. Und nur zur Ausgabe an den nicht binären Menschen gibt es eine einzige Umwandlungsroutine. Für 8-Bit Zahlen kann man einfach den DIV-Befehl benutzen, z.B. bis 99:
1 | |
2 | |
3 | |
4 | |
5 | |
Peter
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.