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
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
@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
Der letzte Satz sollte natürlich heissen: " Ob sein 8051 dividieren kann, sei mal dahin gestellt..."
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
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
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.
>00010101 = 15h, vielleicht sollten Einige an Ihren Grundlagen arbeiten.
Achwas, hauptsache erstmal "Assembler" als Scheiße bezeichnen! Passt
schon..
jetzt vergrault mal den Jungen nicht, wir wollen doch noch die Antwort hören ;) Gruß Hagen
> hauptsache erstmal "Assembler" als Scheiße bezeichnen!
Wenn der Schütze nichts taugt liegts immer am Gewehr ;-)) steht an jeder
Schießbude.
Wandeln in eine BCD - Zahl dann kannst Du die Nibbles direkt angreifen siehe Anhang
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.