Forum: Mikrocontroller und Digitale Elektronik 8051: Problem mit mov bzw. rlc / rrc Befehlen


von Michael L. (eagle87)


Lesenswert?

Hallo zusammen,
ich hab das Problem, dass beim hin und her Kopieren eines Bytes nach 
einem rotier Befehl auf einmal alle Bits gelöscht sind. Konkret geht es 
um die Stelle an der auskommentiert "weiterer Code" steht. Wenn ich die 
mov Befehle davor und danach (mov nb0,a & mov a,nb0) entferne 
funktioniert es auf einmal. Ich komm einfach nicht drauf woran das 
liegen könnte. Eigentlich wird doch nur der Akku auf nb0 geschrieben und 
danach wieder nb0 auf den Akku.
Komischerweise werden die Bits nicht gelöscht wenn ich den Rotierbefehl 
weglasse. Aber ohne macht das Programm halt keinen Sinn.
1
#include <REG8253.H>
2
3
;Stack-Bereich im indirekt adressierbaren internen RAM
4
stackbereich  segment idata
5
  rseg  stackbereich
6
  ds  10h    ;16 Byte
7
8
;Bytes im int. direkt adressierbaren RAM
9
dir_daten  segment data
10
  rseg  dir_daten
11
nb0: ds 1
12
13
;LJMP von Adresse 0 im Code-Speicher zum Programmanfang
14
  cseg  at  0
15
  ljmp  start
16
17
;Programmcode (Code-Beginn über Linker festgelegt)
18
programmcode  segment code
19
  rseg  programmcode
20
  using  0    ;Registerbank 0 für Programmcode (rseg -> verschiebbar)
21
22
;Initialisierung  Stack
23
start:
24
  mov sp,#stackbereich-1  ;STACK-Definition
25
26
;--------------------------------------------------------------------------
27
28
29
  mov nb0,#0a6h
30
main:
31
32
  clr c
33
  mov a,nb0    ;Nennerbyte 0 durch Carry nach links
34
  rlc a
35
  mov nb0,a
36
37
  ;!!!weiterer Code!!!
38
39
  mov a,nb0    ;Nennerbyte 0 auf Port 0 ausgeben
40
  cpl a
41
  mov p0,a
42
43
  ljmp main
44
45
46
  end

Gruß
Michael

von Peter D. (peda)


Lesenswert?

Alle Segmente beginnnen bei 0.
Dein nb0 zeigt also auf R0 der ersten Bank und der Stack auch.

Du mußt daher sinnvolle Adressen vergeben.
Daten legt man gerne hinter den bitadressierbaren Bereich, also ab 30h.
Und den Stack einfach hinter das letzte Datenbyte.
1
  rseg at 30h
2
nb0:   ds 1
3
; hier alle weiteren Daten
4
stack: ds 10h


Peter

von Jobst M. (jobstens-de)


Lesenswert?

Wenn ich das richtig verstehe, funktioniert dieser Fetzen schon nicht. 
Korrekt?

Michael L. schrieb:
> mov nb0,#0a6h
> main:
>
>   clr c
>   mov a,nb0    ;Nennerbyte 0 durch Carry nach links
>   rlc a
>   mov nb0,a

Der Stack ist dem hier nicht im Weg. Auch R0 nicht.

Was passiert, wenn Du vor und hinter das 'rlc a' ein nop setzt?
Sollte das funktionieren, dann hast Du einen handfesten Hardware-Bug 
gefunden.


Gruß

Jobst

von Michael L. (eagle87)


Lesenswert?

@ Peter:
Zur Speicherplatzeinteilung fehlen mir leider noch einige Grundlagen. 
Das hab ich bisher nur aus einer Vorlage genommen und halt versucht zu 
verstehen. Was die einzelnen Direktiven machen ist inzwischen glaub 
relativ klar. Aber bei dem Sinn der dahinter steckt haperts noch. Hast 
du dazu vielleicht einen guten Link oder ähnliches. Hab im Netz noch 
nichts wirklich hilfreiches gefunden.
rseg bedeutet doch reloctable segment, also verschiebbares Segment. 
Sucht der Linker dann nicht selbst eine passende Adresse aus? Die 
Direktive at hab ich bisher nur in Kombination mit cseg (code segment) 
gesehen. Daher dachte ich dass rseg für variable Adressen ist und cseg 
at für feste Adressen.
Den Stack hinter den Programmcode zu hängen werd ich gleich mal 
ausprobieren.

@Jobst:
Ein nop vor und hinter dem rlc bringt nichts. Aber ich konnte das 
Problem noch ein bischen eingrenzen. Wenn ich nur den Befehl mov nb0,a 
also die Zeile nach rlc und vor "weiterer Code"auskommentiere werden die 
Bits nicht gelöscht. Das wär also in dem von dir genannten Codesegment.

Gruß
Michael

von Jobst M. (jobstens-de)


Lesenswert?

Okay, von welchen Bits, die gelöscht werden redest Du eigentlich?

Mit 'mov nb0,a' überschreibst Du den Inhalt von nb0 mit dem vom Akku.

Natürlich ist der vorherige Inhalt von nb0 dann nicht mehr da ...


Gruß

Jobst

von Michael L. (eagle87)


Lesenswert?

Also, da sollt ich wohl doch etwas genauer werden. Der Codeblock 
"Nennerbyte 0 auf Port 0 ausgeben" ist dazu da um den Wert von nb0 
anzuzeigen. Zwischen diesem Open-Drain-Port und VCC hängen LEDs mit 
Vorwiderstand. Deswegen auch cpl. Darauf dass alle Bits 0 sind bin ich 
gekommen weil keine LED leuchtet.

Der Befehl "mov nb0,a" muss sein, da es eim eigentlichen Programm (3 
Byte Division) außer nb0 noch nb1 und nb2 gibt und die Werte im Programm 
immer wieder gebraucht werden. Eigentlich sollen die Bits in nb0 rotiert 
werden, aber das geht ja nicht direkt.

Wenn ich das gesamte Programm / den Programmablaufplan posten soll 
einfach melden.

Gruß
Michael

von Peter D. (peda)


Lesenswert?

Las es dochmal im Simulator laufen.
Google: sim51


Peter

von Jobst M. (jobstens-de)


Lesenswert?

Naja, Dein '#0A6h' ist nach 8 Durchläufen aus nb0 herausgeschoben. Was 
meinst Du wie lange der Prozessor dafür benötigt? Meinst Du, daß Dein 
Auge schnell genug dafür ist?


Gruß

Jobst

von Michael L. (eagle87)


Lesenswert?

So ein blöder Fehler...
Klar dass es dann nicht funktionieren kann. Ich hätt einfach die 
Wertzuweisung hinter oder die Rotation vor die main Marke setzen müssen.

Das eigentliche Unterprogramm für das der Test war funktioniert zwar 
immer noch nicht richtig. Doch zumindest krieg ich nichtmehr lauter 
Nullen. Aber ich versuchs besser erstmal selbst hinzukriegen.

Danke für die Hilfe

Gruß
Michael

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.