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
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
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
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
@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
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...
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
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.
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
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
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?
> 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.
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
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