PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Eine Binärzahl in ASCII umwandeln



SiDe
31.03.2007, 18:07
Hallo,

Ich brauchte mal einen Tipp, wie ich Zahlen aus 2 Registern auf einem LCD-Display (einzeilig - 16 Zeichen) anzeigen lassen kann.

Wenn ich z.B Impulse an einem Eingang zähle, nehmen wir an, ich verwende 2 Register, so incrementiere ich das 1. Register. Tritt ein Überlauf auf, so incrementiere ich das 2. Register.
Wenn ich jetzt aber z.B 259 Impulse gezählt habe, Steht in Register1 eine 1
und in Register2 eine 3 (00000001-00000011).
Wenn ich diese 2 Register nun an mein LCD-Display übertragen würde (2.
Register ab Adresse0 und 1. Register ab Adresse H40, so sähe ich im Display die Zahl 1003.

Ich brauchte also eine Routine, welche mir das Ganze umrechnet. Hat jemand einen einfachen Tipp für mich?

Ich hoffe, ich konnte mein Problem anschaulich schildern.

MfG LotharK

Hanni
31.03.2007, 18:23
1. Wandle die Binärzahl in eine BCD Zahl um.
2. Addiere 30 zu jeder einzelnen Ziffer.
3. Gib die einzelnen Zeichen aus.

Grüße,
Hanni

SiDe
31.03.2007, 18:39
Hi,
Danke erst mal für den Tipp.

Na ja, so lange mache ich das hier noch nicht. (Einige Wochen) Wie wandle ich eine Binärzahl in eine BCD-Zahl?

MfG LotharL

bax
31.03.2007, 19:12
Hi Lothar,

sieh Dich mal auf den Seiten hier um ->> http://www.avr-asm-tutorial.net/avr_de/rechnen/konversion.html

greetz Rajko

SiDe
31.03.2007, 19:55
Hallo,

diese Seite habe ich mir schon angesehen. Das Ganze war mir ehrlich gesaht zu komplex und zu kompliziert. Gibt es vielleicht was einfacheres?

MfG LotharK

izaseba
31.03.2007, 21:09
Gibt es vielleicht was einfacheres?


1. Möglichkeit
subtrahieren Methode :
als erstes prüfen, ob Deine Zahl > 10000 ist, wenn ja solange 10000 subtrahieren bis sie kleiner wird und Anzahl der Schritte mitzählen.
Zum Schluß Anzahl der schritte mit 0x30 verodern und ausgeben.
Weiter mit 1000 100 10 , die Einer nicht mehr subtrahieren sondern direkt verodern, fertig.

2. Möglichkeit

Programmiersprache wechseln z.B. C oder Basic, da ist es nicht mehr komplex und kompliziert...

Gruß Sebastian

SiDe
31.03.2007, 21:43
Hi,

Danke für die Antwort. Obwohl ich es noch nicht begriffen habe...
Müßte ich nicht immer 256 abziehen?
C oder Basic wollte ich nicht verwenden, da es mir nicht darum geht, was Konkretes zu bauen, sondern Assembler lernen will.

Hanni
31.03.2007, 21:48
Hi,

Danke für die Antwort. Obwohl ich es noch nicht begriffen habe...
Müßte ich nicht immer 256 abziehen?

Nein.

BCD = Binär codierte Dezimalzahl.

Das heisst, jede einzelne Stelle deiner 16 Bit Zahl steht nach der Umwandlung in einem extra Register / Variable.

SiDe
31.03.2007, 22:27
Hallo Hanni,

meine Funktion für die Darstellung der Zahlen existiert schon. Solange bei mir weniger als 256 Impulse gezählt werden, kann ich das Register gleich an die Funktion übergeben. Werden mehr als 256 Impulse gezählt, stehen im 2. Register die Anzahl der Überläufe des 1. Registers.
Ich müßte doch nur in einer Schleife die Anzahl des oberen Registers in ein Doppelregister addieren. Also so viel mal 256, wie im oberen Register steht. Zum Schluss wird noch das untere Register zum Doppelregister addiert und fertig. Danach werden die 2 Register ausgegeben.

Wieso sollte ich den Um weg über BNC nehmen?

Das alles sind so meine Überlegungen. Testen werd ich das morgen. Meines Erachtens sollte das funktionieren - oder?
MfG Lo

izaseba
01.04.2007, 10:38
Hallo,
schau Dir mal mein Programm unter https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=10101&highlight= an.

Was Dich interessieren könnte, ist die Routine berechne:
Es wandelt bin->BCD und speichert das Ergebnis im RAM .
Viel Erfolg

Gruß Sebastian

SiDe
01.04.2007, 16:51
Hi,

erst mal vielen Dank. Ich werde den Code heute Abend mal durcharbeiten.

Ist ja ne ganze Menge. Mal sehen, ob ich das gebacken kriege.

MfG L

SiDe
01.04.2007, 18:24
Hallo izaseba,

ich kenne den Code schon (Posting weiter oben).
Ehrlich gesagt, ist mir der Code noch zu komplex (Anfänger).
Ich sehe nicht mal, in welche Register meine 2 Reggister gehören. Könntest Du mir bitte noch etwas unter die Arme greifen?

Danke schon jetzt Lothar

izaseba
07.04.2007, 23:30
Hallo Lothar,
Sorry, ich habe Deine Antwort etwas verpennt ](*,)

Trotzdem versuche ich es etwas zu erklären (vielleicht hast Du das Problem noch nicht gelöst :-k )

Der einstieg ist hier:



warte:
sbis ADCSRA,ADIF
rjmp warte
;fertig und lese Ergebnis ein
in rBin1L,ADCL
in rBin1H,ADCH
cbi PORTD,PD3 ;Pin PD3 wieder LOW
cbi DDRD,PD3 ;und wieder als Eingang
sei ;Interrups wieder an
rcall berechne ;Rechne Ergebnis in ascii um und schreibe
;es in sram


und zwar werden die Register rBin1L und rBin1H mit Deinem Wert belegt, den Rest mit sei usw. kannst Du hier vergessen...

dann geht es nach berechnen und weiter nach Bin2ToBcd5, was dann die Routine von Gerd Schmidt wohl ist...

So, zuerst werden die Reister mit push auf den Stack gelegt, damit die Werte beim verlassen der Routine nicht weg sind, ob man das braucht, weiß ich nicht, naja...



ldi rmp,HIGH(10000) ; Lade 10.000 in rBin2H:L
mov rBin2H,rmp
ldi rmp,LOW(10000)
mov rBin2L,rmp
rcall Bin2ToDigit ; Ermittle 5.Stelle durch Abziehen


hier wird mit Hilfe von rmp, was wohl ein Arbeitsregister >= R16 ist 10000 in die zwei unteren Register rBin2H u. rBin2L geladen. Hier könnte man auch zwei Register über R16 nehmen, wenn man noch welche frei hat, ich habe es aber einfach so übernommen...
So, jetzt wird Bin2ToDigit angesprungen, die nichts anderes macht als



Bin2ToDigit:
clr rmp ; Zähler auf Null
Bin2ToDigita:
cp rBin1H,rBin2H ; Vergleiche MSBs miteinander
brcs Bin2ToDigitc ; MSB Binärzahl kleiner, fertig
brne Bin2ToDigitb ; MSB Binärzahl größer, subtrahiere
cp rBin1L,rBin2L ; MSB gleich, vergleiche LSBs
brcs Bin2ToDigitc ; LSB Binärzahl kleiner, fertig
Bin2ToDigitb:
sub rBin1L,rBin2L ; Subtrahiere LSB Dezimalzahl
sbc rBin1H,rBin2H ; Subtrahiere Carry und MSB
inc rmp ; Erhöhe den Zähler
rjmp Bin2ToDigita ; Weiter vergleichen/subtrahieren
Bin2ToDigitc:
st z+,rmp ; Speichere das Ergebnis und erhöhe Zeiger
ret ; zurück


rmp auf null setzen,
Deine Ausgangszahl in rBin1L / H mit rBin2 L / H (wo jetzt 10000 drin steht) zu vergleichen,
Ist Deine Zahl kleiner, wird rmp in RAM abgespeichert (wo der z Zeiger hinzeigt) und mit ret zurückgegangen, ist sie größer wird davon 10000 ( rBin1L / H ) abgezogen rmp inkrementiert, wieder verglichen.
Das Spielchen solange, bis Deine Zahl kleiner als 10000 wird...
Jetzt ist hoffentlich auch klar, daß im rmp z.B. bei 30000 3 drin steht und bei 45121 eine 4 [-o<

So nach dem ret geht es in Bin2ToBcd5 mit 1000 100 und 10 weiter die einser werden direkt gespeichert.
jetzt steht im Ram irgendwo wo der Z Zeiger hingezeigt hat, unsere Ausgangszahl in Digits zerlegt drin.
rBin1L / H werden wiederhergestellt ( die zwei pop's)

Ich habe dann noch eine Routine eingebaut, die mit die führenden Nullen bei Zahlen die kleiner 10000 sind entfernt und fertig, danach kommt nur noch die UART Ausgabe wo die Zahlen mit 0x30 verodert werden.

Ich hoffe, daß es etwas verständlicher geworden ist :-k

Gruß Sebastian

SiDe
08.04.2007, 07:33
Hallo izaseba,

vielen Dank für Deine ausführliche Erklärung. Dank Deiner Hilfe ist es mir jetzt klar geworden. Ich hatte den Versuch schon auf Eis gelegt und wollte es mir später mal wieder anschauen, wenn ich besser bescheid weiß.
Das mit dem Ablegen im Ram mittels Z-Zeiger hatte ich nicht verstanden. Jetzt ja.

MfG Lothar