Forum: Mikrocontroller und Digitale Elektronik 8051 assembler bitmuster teilen


von dribble T (Gast)


Lesenswert?

hey leute,

hab ne frage zu 8051 assembler, ich tu mir wirklich schwer mit diesem 
(scheiss) assembler...

ich möchte folgendes realisieren ein bitmuster wird eingelesen
z.B. 10010010b = 15

ich möchte nun diese zahl an zwei sieben segmentanzeigen darstellen

wie kann ich die zahl / das bitmuster so manipulieren, das ich einmal 
die dezimalzahl 5 und einmal die dezimalzahl 1 habe, bzw einmal die 
hexzahl 5 und einmal die hexzahl 1.

hintergrund ist der: ich will später über basis-index-programmierung dem 
datenpointer sagen gehe an die und die stelle und dazu brauch ich diese 
beiden einzelnen zahlen

leider muss das ganze in assembler sein und nicht in einer 
hochsprache...

danke für die hilfe


mfg

TTT

von M. B. (m_beffa)


Lesenswert?

Ich bin jetz nicht sicher ob ich dich richtig verstanden habe, du 
möchtest eine Zahl in Einer, Zehner, Hunderter etc. aufteilen und die 
dann jeweils an ne sieben-segment Anzeige ausgeben?

Ich hab mal ne kleine Funktion geschrieben, die dir die Zahl in Stellen 
aufteilt!

Wenn du willst kann ich dir das Assembler Zeugs morgen reinstellen...

Weis nicht mehr genau auswendig wie ich das gemacht habe... War aber 
glaub ich nicht so schwierig...

ich denke das ging irgendwie so:

du dekrementiers ständig die zu zerlgende Zahl, testest sie auf null... 
jedesmal wenn du dekrementierst zählst du einen zähler hoch, wenn du 10 
mal dekrementiert hast, geht der zähler für die Zehnerstelle um eins 
hoch, und der Zähler für die einer wieder auf 0..

so solltest du die Zahl zerlegen können...

Grüsse

von dribble T (Gast)


Lesenswert?

danke für die schnelle antwortet,

das würde so funktionieren, habe ich auch schon drangedacht, wäre auch 
toll, wenn du deinen code morgen hier rein stellen könntest...

gibt es den keine einfachere lösung ?

TTT

von Ronny (Gast)


Lesenswert?

Einfacher:

Division durch 10 und Modulo 10.Mit dem Divisionsergebnis wird 
weitergerechnet,das Moduloergebnis (Divisionsrest) ist deine letzte 
Ziffer.Die kannst du z.B als Index in eine Tabelle zur Dekodierung für 
die 7 Segmentanzeige benutzen.

Pseudocode für eine 2-stellige Zahl:

Ziffer1 = Zahl modulo 10;
Zahl = Zahl / 10;
Ziffer2 = Zahl modulo 10;

7SegmentZehner = Tabelle[Ziffer2];
7SegmentEiner = Tabelle[Ziffer1];

Oder in einer Schleife:

Schleife:
Ziffer[i] = Zahl modulo 10;
Zahl = Zahl / 10;
i = i+1;
wenn Zahl <> 0 gehe zu Schleife

Wie du allerdings auf 10010010b = 15 kommst,ist mir unklar

von Peter D. (peda)


Lesenswert?

mov a, #15h
mov b, #16
div ab

nun ist A = 1 und B = 5

Und zum Umwandelen in 7-segment schau Dir mal den Befehl "mov a,@a+pc" 
an.


Peter

von M. B. (m_beffa)


Lesenswert?

@Peter Dannegger

Ich schätze deine Postings über alle Massen, aufgrund ihrer 
Professionalität. Aber ich denke manchaml wäre es angebracht ein wenig 
mehr zu erklären... Habe ständig dass Gefühl dass du mit Absicht so 
wenig wie möglich kommentierst und erklärst , damit manche Leute das 
Gefühl haben "ohh, wie klug isn der!"... Es bringt einem Fragesteller 
meistens nicht viel, wenn du nur npaar Zeilen Code hinschreibst... Dies 
ist jetz nicht explizit auf den Post hier bezogen.. Das ist mir jetz 
schon mehrmals aufgefallen...

@Ronny
Er soll das mit Assembler machen... Sein 8051 dividieren kann, sei mal 
dahin gestellt.

Grüsse

von M. B. (m_beffa)


Lesenswert?

Der letzte Satz sollte natürlich heissen: " Ob sein 8051 dividieren 
kann, sei mal dahin gestellt..."

von Ronny (Gast)


Lesenswert?

Ob der konkrete 8051 Divisionsbefehle hat,weiss ich nicht.Davon ausgehen 
kann man nicht.Mir ging es lediglich um das grundlegende Prinzip und das 
ist immer das selbe wenn Binär->ASCII umgerechnet oder Ziffern 
herausgepickt werden sollen.

Alternativ hätte ich ihn auch auf die Codesammlung hinweisen können,wo 
bestimmt Beispielcode dafür existiert.Darüber nachdenken muss er jedoch 
immer selber...

von M. B. (m_beffa)


Lesenswert?

Da hast du natürlich Recht...

von Peter D. (peda)


Lesenswert?

Marco Beffa wrote:

> Habe ständig dass Gefühl dass du mit Absicht so
> wenig wie möglich kommentierst und erklärst


Ja, ich kaue mit voller Absicht nicht alles vor.

Ich will damit zum selber Nachdenken anregen.

Und wenn etwas unverständlich ist, kann man ja ruhig mal nachfragen.


Ich will nur ein bischen in eine richtige Richtung schubsen, mehr nicht.


Peter

von Joe (Gast)


Lesenswert?

mov a, #15h
mov b, #10d
div ab

Das wäre vielleicht verständlicher gewesen. Das mit 16 habe ich schon 
öfter gesehen und dann kein h für hex angeben...

Also 16h = 10 d = dezimal. 15 / 10 = 1,5 der 8x51 kann mittels div 
Befehl dividieren. Es muß explizit a und b als Register verwendet 
werden. Nach der Division ist das Ergebnis in a und der Rest in b. das 
ist auch schon das ganze Geheimnis.

von Jörg (Gast)


Lesenswert?

Also halt, stop mal, das interressiert mich jetzt wirklich. 
Möglicherweise habe ich da auch etwas ernsthaftes verpasst, aber welcher 
Zusammenhang besteht denn zwischen der oben angegebenen Binärzahl 
"10010010b" und der Zahl 15 (ob dezimal oder 0x15 ist egal). Kann mir 
das mal jemand erklären?

Jörg

von Hagen R. (hagen)


Lesenswert?

der einzigste Zusamenhang dürfte es sein als Beispiel in diesem Thread 
gedient zu haben, und wie du bemerkt hast als "falsches" Beispiel ;)

Gruß Hagen

von Jörg (Gast)


Lesenswert?

Dann ist es natürlich recht schwierig, eine korrekte Umrechnung 
vorzuschlagen.

Wenn aus einer 15hex die Ziffern 1 und 5 entstehen sollen, muss man doch 
nicht "aufwendig" dividieren. Die einzelnen Ziffern stehen ja bereits in 
den beiden Nibbeln des Bytes und können damit sehr einfach über 
maskieren und swapen extrahiert werden.

Wenn eine 15dez (=0Fhex) zerlegt werden soll, muss man durch 10 
dividieren oder (bei Controllern ohne Divisionsbefehl) über fortlaufende 
Subtraktion die Zahl zerlegen.

Für krumme Sachen oder wenns ohne Division besonders schnell gehen soll, 
kann man auch eine Tabelle verwenden.

Übrigens hat (meines Wissens nach) JEDER 8051 die Fähigkeit zur 
Division, sonst ist es kein 8051.

Jörg

von ich&er (Gast)


Lesenswert?

@joe:
16hex = 10dec ??? nicht wirklich, oder?

von kolrabi (Gast)


Lesenswert?

Im 8051 Assembler gibts doch den schönen Befehl "DA" genau dafür (vorher 
das Carry-Flag löschen). Oder hab ich jetzt die Fragestellung falsch 
verstanden?

von Joe (Gast)


Lesenswert?

> 16hex = 10dec ??? nicht wirklich, oder?

16d = 10h... wie dem auch sei, /10d.

> der einzigste Zusamenhang dürfte es sein als Beispiel in diesem Thread
> gedient zu haben, und wie du bemerkt hast als "falsches" Beispiel ;)

Das kann man wohl sagen. Das kommt dabei raus wenn man alles mit 3 
halbsätzen ausdrücken will ;-))

00010101 = 15h, vielleicht sollten Einige an Ihren Grundlagen arbeiten.

von Simon K. (simon) Benutzerseite


Lesenswert?

>00010101 = 15h, vielleicht sollten Einige an Ihren Grundlagen arbeiten.

Achwas, hauptsache erstmal "Assembler" als Scheiße bezeichnen! Passt 
schon..

von Hagen R. (hagen)


Lesenswert?

jetzt vergrault mal den Jungen nicht, wir wollen doch noch die Antwort 
hören ;)

Gruß Hagen

von Joe (Gast)


Lesenswert?

> hauptsache erstmal "Assembler" als Scheiße bezeichnen!

Wenn der Schütze nichts taugt liegts immer am Gewehr ;-)) steht an jeder 
Schießbude.

von Rodney (Gast)


Angehängte Dateien:

Lesenswert?

Wandeln in eine BCD - Zahl dann kannst Du die Nibbles direkt angreifen

siehe Anhang

von dernixwois (Gast)


Lesenswert?

Der 8051'er hat doch den befehl DA.

Werden deine 7-Segmentanzeigen mit BCD - Code versorgt?

Wenn ja! dann kannste direkt mit einem Port die Zahl senden.


Bsp.

     Mov A,#0Ah   ; entspricht 10d
     Add A,#05h   ;
     DA  A        ;Decimal Adjustment Accumulator
                  ;macht jetzt schön daraus 15 anstatt 0Fh

    Mov  P1,A     ;jetzt einfach den BCD-Code senden über Port 1


von B.Spitzer (Gast)


Lesenswert?

Hallo,
als Ergänzung... Im Akku steht jetzt endlich die 2-Stellige BCD-Zahl,
so dass die unteren 4 Bit die erste Ziffer darstellen und die oberen 4 
Bit
die zweite Ziffer.
Die Ausgabe muss zunächst über eine Tabelle umgerechnet werden:
BDC => Segment
    A B C D E F G dp
 0  1 1 1 1 1 1 0 0
 1  0 1 1 0 0 0 0 0
 2  1 1 0 1 1 0 1 0
 3  1 1 1 1 0 0 1 0
und so weiter...
Wenn HEX-Ziffern dargestellt werden sollen gibt es auch noch:
 A  1 1 1 0 1 1 1 1  (ich schalte bei HEX den dp ein, damit
 b  0 0 1 1 1 1 1 1   man es leichter erkennt)
 C  1 0 0 1 1 1 0 1
 d  0 1 1 1 1 0 1 1
 E  1 0 0 1 1 1 1 1
 F  1 0 0 0 1 1 1 1
Die Zuordnung der Segmente zu den Portpins ist halt anzupassen.


Jetzt ist die Frage, wie die 7-Segment-Anzeige angesteuert ist...
1: Jedes Segment an einem Portpin (z.B. Port 0 linke Stelle und
   Port 2 rechte Stelle):
; Im Akku steht die 2-Stellige Zahl
push ACC                   ; Akku sichern
anl  ACC,#00001111b        ; obere 4 Bits ausblenden
mov  dptr,#SegmentTabelle
movc A,@A+dptr             ; Wert mit Tabelle umrechnen
mov  P2, A                 ; auf rechte Stelle ausgeben
pop  ACC                   ; Akku wieder herstellen
swap A                     ; Nibbles tauschen
anl  ACC,#00001111b        ; obere 4 Bits ausblenden
mov  dptr,#SegmentTabelle
movc A,@A+dptr             ; Wert mit Tabelle umrechnen
mov  P0, A                 ; auf linke Stelle ausgeben
ajmp irgendwohin           ; rest des Programms

; Umrechnungstabelle für 7-Segment-Anzeige
SegmentTabelle:
     db 11111100b, 01100000b, 11011010b, etc...

2. Möglichkeit: Die Anzeigen hängen am selben Datenport und werden über 
je einen Transistor an einem anderen Portpin geschaltet (bei meinem 
Board P3.6 schaltet rechte Anzeige, P3.7 schaltet linke Anzeige)

; Im Akku steht die 2-Stellige Zahl
push ACC                   ; Akku sichern
anl  ACC,#00001111b        ; obere 4 Bits ausblenden
mov  dptr,#SegmentTabelle
movc A,@A+dptr             ; Wert mit Tabelle umrechnen
mov  P2, A                 ; auf rechte Stelle ausgeben
setb P3.6                  ; Rechte Anzeige aktivieren
call Warte_2ms             ; 2ms Warten für stabile Anzeige
clr  P3.6                  ; Anzeige deaktivieren
pop  ACC                   ; Akku wieder herstellen
swap A                     ; Nibbles tauschen
anl  ACC,#00001111b        ; obere 4 Bits ausblenden
mov  dptr,#SegmentTabelle
movc A,@A+dptr             ; Wert mit Tabelle umrechnen
mov  P2, A                 ; auf linke Stelle ausgeben
setb P3.7                  ; Linke Anzeige aktivieren
call Warte_2ms             ; 2ms Warten für stabile Anzeige
clr  P3.7                  ; Anzeige deaktivieren
ajmp irgendwohin           ; rest des Programms

3. Möglichkeit: mehrere Anzeigen werden über einen Decoder (z.B. 74138) 
aktviert. Wie bei 2. nur dass jetzt die passende Bitkombination 
(A2,A1,A0) an den Decoder ausgegeben werden muss. (Stelle 0 : 000, Stell 
1: 001 etc).


tschuessle
Bernhard

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.