www.mikrocontroller.net

Forum: Projekte & Code 8 Bit binär zu ASCII


Autor: Daniel Katzenberger (lostsoul)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Anbei ein einfaches Programm um einen 8bit Wert in ASCII umzuwandeln.
Ist vielleicht nicht die eleganteste Lösung aber für meine Zwecke hat es 
bisher gereicht.

Gruß Daniel
Viel Spaß damit

Autor: Christian Berger (casandro) Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auf den ATMegas ist das so ziemlich die einfachste und schnellste 
Lösung. Gäbe es einen Divitionsbefehl ginge es jedoch einfacher.

Vielleicht gibts noch eine obskure Möglichkeit das per Multiplikation zu 
machen.

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Christian Berger wrote:

> Vielleicht gibts noch eine obskure Möglichkeit das per Multiplikation zu
> machen.

Ja, die gibt es. Ich habe zwar momentan den Link nicht gefunden, aber 
irgendwo (ich glaube auf http://www.avrfreaks.net/ war das), gab es eine 
ziemlich ausführliche Diskussion dazu. Das Problem dabei ist nur, dass 
man eine Multiplikation mit einer relativ groeßn Zahl braucht, damit die 
Rundungsfehler oder ähnliches einem das Ergebnis nicht verfälschen.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Daniel Katzenberger wrote:
> Anbei ein einfaches Programm um einen 8bit Wert in ASCII umzuwandeln.

So gehts auch:

;input:  R16 = 8 bit value 0 ... 255
;output: R18, R17, R16 = ASCII-digits

bcd:
        ldi     r18, -1 + '0'
_bcd1:
        inc     r18
        subi    r16, 100
        brcc    _bcd1
        ldi     r17, 10 + '0'
_bcd2:
        dec     r17
        subi    r16, -10
        brcs    _bcd2
        sbci    r16, -'0'
        ret


Peter

Autor: 655432 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter, könntest du deinen Code wohl noch etwas erläutern? Der ist schön 
kurz.

Autor: Christian Berger (casandro) Flattr this
Datum:

Bewertung
1 lesenswert
nicht lesenswert
655432 wrote:
> Peter, könntest du deinen Code wohl noch etwas erläutern? Der ist schön
> kurz.

Im Prinzip macht er das selbe, wie der Vorredner.

Er beginnt bei einer Zahl in "Variable X". Ist X größer als 100, so 
zieht er 100 davon ab (X=X-100), und erhöht die 100-er Stelle.

Dann kuckt er nach, ob der Rest (X) größer als 10 ist. Ist das der Fall, 
so zieht er 10 davon ab (X=X-10) und erhöht die 10-er Stelle.

Im Pseudecode ist das etwa so:

X: Originalzahl
H: Hunderter
Z: Zehner
E: Einer


H=0
Z=0
E=0
Solange X>100
  X=X-100
  H=H+1
Solange X>10
  X=X-10
  Z=Z+1
E=X

Will man binär in BCD umwandeln, so kann man das für 2 Stellen etwas 
abkürzen:
X: Originalzahl
Y: BCD-Version
Y=0
Solange X>10
  X=X-10
  Y=Y+$10
Y=Y+X

Autor: 655432 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK danke!

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
655432 wrote:
> Peter, könntest du deinen Code wohl noch etwas erläutern? Der ist schön
> kurz.

Zuerst werden jeweils 100 abgezogen bis ein Unterlauf eintritt.

Z.B. von 234 wird 3-mal abgezogen und übrig bleibt:
234 - 3 * 100 = -66.
und -1 + '0' + 3 = '2'

Dann wird 10 addiert, bis ein Überlauf eintritt:
-66 + 7 * 10 = 4
und 10 + '0' - 7 = '3'

Dann noch 4 + '0' = '4'
und fertig.


Peter

Autor: Christian Berger (casandro) Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohh, das ist originell. Darauf wäre ich nicht gekommen.

Autor: Daniel Katzenberger (lostsoul)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

@ Peter Dannegger: dein code ist ja um einiges kürzer als meiner. Wär da 
nicht drauf gekommen... vorallem auf meinem at-mega habe ich die 
Register oberhalb von r16 schon alle in Verwendung, also ist mir nicht 
anderes übrig geblieben als die unteren Register zu verwenden...
Trotzdem gut zu wissen, dass es noch einfacher geht.

Gruß Daniel

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daniel Katzenberger wrote:
> nicht drauf gekommen... vorallem auf meinem at-mega habe ich die
> Register oberhalb von r16 schon alle in Verwendung, also ist mir nicht
> anderes übrig geblieben als die unteren Register zu verwenden...


Wenn Du länger programmierst, wirst Du merken, daß es unklug ist, alle 
Variablen ständig in Registern zu halten.

Globale Variablen legt man überlicher Weise im SRAM an.
Werden sie gebraucht, lädt man sie in Register, macht damit die 
anstehenden Aufgabe und schreibt die Ergebnisse wieder ins SRAM.

Nur Variablen, die besonders häufig gebraucht werden, kann man 
ausnahmsweise in Registern definieren (vorzugsweise in den unteren 
R2..R15).

D.h. die meisten Register sind Arbeitsregister und werden kurzzeitig 
verwendet, wie eine Wandtafel (Scratchpad-Register).

Schau Dir mal größere Projekte von anderen an oder das Assemblerlistung 
von einem C-Programm.


Peter

Autor: Daniel Katzenberger (lostsoul)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Peter Dannegger
Ich arbeite schon ein paar Jahre mit µC allerdings mit PIC16FXXX.
Auf Avr bin ich erst vor ein paar Wochen umgestiegen. Daher bin ich mit 
deren Struktur noch nicht so vertraut... Bei PIC kann man ja direkt mit 
werten rechnen die im SRAM stehen. Daher verwende ich den SRAM der AVR 
im moment nur für größere Datenmengen (Laufschrift für LCD usw.)
Aber danke für die tipps.
Ich hoffe ich kann mich "schnell" in die AVR-Welt einarbeiten.

Gruß Daniel

Autor: Matthias Schläfli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Ich habe eine Lösung gefunden! Ist zwar etwas lang, aber es 
funktioniert!
Einfach den gewünschten Wert in die Variable x speichern und du erhälst 
den Zehner und Einer Wert zurück.


if((x>=0) && (x<=9))
 {
 Ascii_Zehner=48;
 }

 if((x>=10) && (x<=19))
 {
 Ascii_Zehner=49;
 }

 if((x>=20) && (x<=29))
 {
 Ascii_Zehner=50;
 }

 if((x>=30) && (x<=39))
 {
 Ascii_Zehner=51;
 }

 if((x>=40) && (x<=49))
 {
 Ascii_Zehner=52;
 }

 if((x>=50) && (x<=59))
 {
 Ascii_Zehner=53;
 }

 if((x>=60) && (x<=69))
 {
 Ascii_Zehner=54;
 }

 if(x==0 || x==10 || x==20 || x==30 || x==40 || x==50 || x==60)
 {
 Ascii_Einer=48;
 }

 if(x==1 || x==11 || x==21 || x==31 || x==41 || x==51 || x==61)
 {
 Ascii_Einer=49;
 }

 if(x==2 || x==12 || x==22 || x==32 || x==42 || x==52 || x==62)
 {
 Ascii_Einer=50;
 }

 if(x==3 || x==13 || x==23 || x==33 || x==43 || x==53 || x==63)
 {
 Ascii_Einer=51;
 }

 if(x==4 || x==14 || x==24 || x==34 || x==44 || x==54)
 {
 Ascii_Einer=52;
 }

 if(x==5 || x==15 || x==25 || x==35 || x==45 || x==55)
 {
 Ascii_Einer=53;
 }

 if(x==6 || x==16 || x==26 || x==36 || x==46 || x==56)
 {
 Ascii_Einer=54;
 }

 if(x==7 || x==17 || x==27 || x==37 || x==47 || x==57)
 {
 Ascii_Einer=55;
 }

 if(x==8 || x==18 || x==28 || x==38 || x==48 || x==58)
 {
 Ascii_Einer=56;
 }

 if(x==9 || x==19 || x==29 || x==39 || x==49 || x==59 || x==69)
 {
 Ascii_Einer=57;
 }

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias Schläfli wrote:

> Ich habe eine Lösung gefunden! Ist zwar etwas lang,

Ja das stimmt, die ist wirklich schon extrem lang, 3800% größer als 
meine.


> aber es
> funktioniert!

Aber nur von 0 ... 63.
Was ist mit den Zahlen 64 ... 255?


Peter

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

@Matthias

Kennt dein Compiler keinen 'mod' (Modulo) Befehl? Damit ist das mit ca. 
10 Zeilen gegessen.

MfG Spess

Autor: Marc Seiffert (euro)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Qlternativ hier mal ein codeschnipsel den ich mir mal zusammen gebastelt 
habe, ist allerdings direkt aus ner LCD-Routine:
void lcd_int8out(uint8_t i){
bool temp = false;
if((i/100)||temp){lcd_data((i/100)+48);temp = true;}else{lcd_data(' ');};
i %= 100;
if((i/10)||temp){lcd_data((i/10)+48);}else{lcd_data(' ');};
i%= 10;
lcd_data(i+48);
};

Ist vermutlich am einfachsten zu verstehen, arbeitet allerdings mit 
Division ;)

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marc Seiffert wrote:
> Ist vermutlich am einfachsten zu verstehen, arbeitet allerdings mit
> Division ;)

Alles in möglichst wenig Code Zeilen zu stecken fördert aber nicht die 
Verstehbarkeit ;)

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon K. wrote:

> Alles in möglichst wenig Code Zeilen zu stecken fördert aber nicht die
> Verstehbarkeit ;)

Das stimmt.
Man kann ein Programm auch als Einzeiler schreiben, aber dann muß der 
Code noch lange nicht kleiner sein, als mit 1000 Zeilen.
Besonders der AVR-GCC läßt sich mit verschiedenen Schreibweisen 
überhaupt nicht beeinflussen, der compiliert (leider) immer seinen 
eigenen Stil.


Man sollte aber nicht mit der Brechstange versuchen, alles nur mit 
Vergleichen zu machen.
Man kann ja auch jede beliebige Digitalschaltng nur mit 2-fach NAND 
(74HC00) aufbauen, aber das macht keiner.

Und es schadet nichts, zu wissen, daß 10 Subtraktionen effizienter sind 
als eine Division auf MCs ohne Hardware-Division.


Peter

Autor: Schnulli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ja das stimmt, die ist wirklich schon extrem lang, 3800% größer als
>meine.

Welche Codesammlung muß man eigentlich im Kopf haben, um so krankhaft 
angeben zu müssen?

Autor: Rudi D. (rulixa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter D. schrieb:
> Daniel Katzenberger wrote:
>> Anbei ein einfaches Programm um einen 8bit Wert in ASCII umzuwandeln.
>
> So gehts auch:
>
> 
> ;input:  R16 = 8 bit value 0 ... 255
> ;output: R18, R17, R16 = ASCII-digits
> 
> bcd:
>         ldi     r18, -1 + '0'
> _bcd1:
>         inc     r18
>         subi    r16, 100
>         brcc    _bcd1
>         ldi     r17, 10 + '0'
> _bcd2:
>         dec     r17
>         subi    r16, -10
>         brcs    _bcd2
>         sbci    r16, -'0'
>         ret
> 
> 
>
> Peter

Habe heute so eine Routine gebraucht.
Ich bin ja nicht so sattelfest, aber ich finde, dass da drin ein Fehler 
steckt. Nämlich entweder die 1. Zeile muss sein
             ldi      r18, -2 + '0'

;oder man fügt nach der Zeile mit brcc eine Zeile   

               dec    r18          ;ein

Später im Thread mit dem Beispiel 234 sehe ich nirgends -1 +'0',
die die 3 Hunderter auf 2 Hunderter korrigiert. Man darf ja nicht das 
erste inc    r18 vergessen.

 Wo liegt mein ev. Fehler?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rudi D. schrieb:

 die die 3 Hunderter auf 2 Hunderter korrigiert. Man darf ja nicht das
> erste inc    r18 vergessen.

Dem ersten inc r18 wird doch dadurch Rechnung getragen, dass er nicht 
bei 0 anfängt zu zählen, sondern bei -1.

Sind 3 Subtraktionen notwendig, bis das Ergebnis unterläuft (salopp 
gesprochen: negativ wird), dann waren genau 2 Hunderter in der Zahl. Und 
genau das kriegt er doch auch raus.

Einfach mal im Einzelschrittbetrieb durchsteppen. Dann sollte das 
Prinzip klarer werden.

: Bearbeitet durch Moderator
Autor: Rudi D. (rulixa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da sieht man was im Kopf falsch laufen kann. Die 3. Subtraktion 
verursacht ja kein inc r18 mehr. Aber am Papier hab ich das getan, als 
ich es durchspielte.
Danke Rudi

Autor: Rudi D. (rulixa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rudi D. schrieb:
> Da sieht man was im Kopf falsch laufen kann. Die 3. Subtraktion
> verursacht ja kein inc r18 mehr. Aber am Papier hab ich das getan, als
> ich es durchspielte.
> Danke Rudi

Das Codeschnipsel wird im DDS-Generator bei der Einstellung der 
Wobbelfrequenz von 2 Hz bis 73 Hz erfolgreich verwendet Siehe

http://www.radiomuseum.org/forum/neues_vom_dds_hei...

Der Thread dort ist schon sehr lang.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.