Forum: Mikrocontroller und Digitale Elektronik Atmega128: Umwandeln von HEX in ASCII


von Bernd (Gast)


Lesenswert?

Hallo,
ich möchte über ein Display einige, im MC gespeicherte, Zahlen
ausgeben.
Diese sind aber im 2-stelligen Hex-Format (also 8bit).
Weiß jemand, wie ich diese Hex-Zahlen in jeweils 3 ASCII-Zeichen
umwandeln kann?
Gibt eis da einen Trick, oder brauche ich da eine Tabelle?

von Philipp S. (philipp)


Lesenswert?

Das Thema war hundertmal da.

Es gibt fertigen Code für wohl jede Programmiersprache auf der Welt (Du
verrätst ja nicht, welche Sprache auf welchem Gerät Du einsetzt).

Im aller-allerschlimmsten Fall mußt Du Dein Gehirn benutzen.
Denkansatz: beginne mit dem ASCII-Zeichen für null ($30). Solange Du
von der Zahl hundert abziehen kannst, tu es und erhöhe jedesmal den
ASCII-Wert. Wenn Deine Zahl dann unter hundert ist, kannst Du den
ersten Wert rausschreiben und beginnst wieder mit $30, diesmal mit den
Zehnern. Usw.

von Philipp S. (philipp)


Lesenswert?

'Tschuldigung: der µC steht ja im Betreff, nur die Sprache finde ich
nicht.

von Michael Wilhelm (Gast)


Lesenswert?

Geht evtl. auch noch einfacher, aber ich habe es in C mal so gemacht:
die Variable enthält die Zahl 145.
1. 145%10=5  -> einer
2. 145/10=14
3. 14%10=4   -> zehner
4: 14/10=1   -> hundetrter
Die Ergebnisse mit einem Offset beaufschlagen, der sich nach dem
Character-ROM des Displays richtet.

MW

von Bernd (Gast)


Lesenswert?

Die Variante mit der Division klingt eigentlich recht einfach.
Allerdings programmiere ich mit dem AVR-Assembler.
Ich muss mal schauchen, obs da die Möglichkeit zur Modulo-Division
gibt...

von Jens D. (jens) Benutzerseite


Lesenswert?

3te Klase Mathematik teilen von zahlen

111 / 10 = 11 (rest1)
110
_
  1

von dds5 (Gast)


Lesenswert?

gibt auch noch andere Varianten, z.B. für jedes gesetzte Bit des
Quellregisters den entspr. dezimalen Wert (1,2,4,8,16,usw.) auf
Zielregister addieren und nach jeder Addition eine Dezimalkorrektur
("DAA" oder so) ausführen.
Das ergibt gepacktes BCD, muss man noch entpacken und jeweils 30h
dazuzählen, dann ists ASCII.

Dieter

von Mike Schaub (Gast)


Lesenswert?

Hier ein kleines Progrämmchen!


void itohexa(unsigned int n, unsigned char * s)    // wandelt eine long
Zahl in einen 4 Byte grossen HEX-String
{
  unsigned int  help,z;

  help = n;

  for (z=3;z>0;z--)
    {
      if ((help & 0x000F) > 9) s[z] = (help & 0x000F) + 55;
      else s[z] = (help & 0x000F) + '0';
      help = help >> 4;
    }

  s[4] = 0;
}


Gruß
Mike

von Philipp S. (philipp)


Lesenswert?

@Michael: Schön in Hochsprachen, wenn man viel Zeit hat. Aber Division
und Modulo gibt es auf einem AVR nicht geschenkt.

@Jens: Hast Du den Eindruck, daß Bernd das hinbekommt, wenn ihm schon
subtrahieren zu schwierig ist?

@dds5: Wetten, daß das langsamer ist und mehr Takte braucht?

@Mike: Schön, war aber nicht verlangt.

@Bernd: Gerade wenn Du Assembler schreibst, vertraue mir: das
beschriebene Verfahren ist das einfachste. Ehrlich.

Aus dem Stegreif; die Zahl stehe in r16:

  ldi r17, $30 - 1 ; ein inc kommt immer!
Hunderterschleife:
  inc r17
  subi r16, 100
  brpl Hunderterschleife
  subi r16, -100 ; weil einmal zuviel abgezogen

  ldi r18, $30 - 1 ; ein inc kommt immer!
Zehnerschleife:
  inc r18
  subi r16, 10
  brpl Zehnerschleife

  ldi r18, $30 + 10 ; weil 10 zuviel von r16 abgezogen
  add r18, r16

Ich hoffe, das stimmt alles; das Ergebnis steht dann in r17,r18,r19. 11
Befehle. Ich bezweifle, daß man das mit Modulo oder anderen Methoden
hinbekommt. Und schneller sollte es auch sein.


Im übrigen meine Bewunderung für ein Mega128-Projekt in Assembler!

von dds5 (Gast)


Lesenswert?

@Philipp
Ich hab sowas für 16Bit auf PIC18F in Assembler realisiert.
Ergibt knapp doppelt so viel Code wie die Subtraktion in Schleifen, ist
aber worst case (65535) rund doppelt so schnell.

Dieter

von Philipp S. (philipp)


Lesenswert?

Hm. Worst case für meine Schleife sollte bei 16 Bit übrigens 59999 sein.
Und dann ist noch die Frage, ob Durchschnitt (für max. Durchsatz) oder
Maximum (für real time scheduler!) wichtiger sind.

Ich kann es mir immer noch nicht richtig vorstellen, immerhin muß nach
jeder von bis zu 15 Additionen auf bis zu 5 Stellen auf Dezimalüberlauf
getestet werden.

Kannst Du auch AVR-Assembler? Dann steht meine Wette, daß Dein
Verfahren nicht mithält, selbst mit doppelt soviel Code. Auch nicht bei
16 Bit! Schlägst Du ein?

Gruß, Philipp.

von Peter D. (peda)


Lesenswert?

Hier mal 16 Bit zu ASCII:
1
;*************************************************************************
2
;*                                                                     
3
 *
4
;*                      Convert unsigned 16 bit to ASCII               
5
 *
6
;*                                                                     
7
 *
8
;*              Author: Peter Dannegger                                
9
 *
10
;*                      danni@specs.de                                 
11
 *
12
;*                                                                     
13
 *
14
;*************************************************************************
15
;
16
;input: R17, R16 = 32 bit value 0 ... 65535
17
;output: R20, R19, R18, R17, R16 = 5 digits (ASCII)
18
;cycle: 20 ... 170
19
;
20
bin16_ascii:
21
22
        ldi     r20, 1- + '0'
23
_bcd1:  inc     r20
24
        subi    r16, low(10000)         ;-10000
25
        sbci    r17, high(10000)
26
        brcc    _bcd1
27
28
        ldi     r19, 10 + '0'
29
_bcd2:  dec     r19
30
        subi    r16, low(-1000)         ;+1000
31
        sbci    r17, high(-1000)
32
        brcs    _bcd2
33
34
        ldi     r18, -1 + '0'
35
_bcd3:  inc     r18
36
        subi    r16, low(100)           ;-100
37
        sbci    r17, high(100)
38
        brcc    _bcd3
39
40
        ldi     r17, 10 + '0'
41
_bcd4:  dec     r17
42
        subi    r16, -10                ;+10
43
        brcs    _bcd4
44
45
        subi    r16, -'0'
46
        ret
47
;-------------------------------------------------------------------------


Peter

von dds5 (Gast)


Lesenswert?

@Philipp
AVR-Asm kenn ich leider nicht, hab bisher nur mit (in dieser
Reihenfolge) Z80, µPD75108 (4Bit!), 8051, PIC16C und jetzt PIC18F
gearbeitet. Vieles kann man trotzdem erkennen und teilweise auch
verstehen, aber ist schon blöd dass jeder andere Mnemonics benutzt weil
fast alle Markenschutz haben.
Wette verlier ich wahrscheinlich, weil
1. Ergebnis liegt nicht in ASCII sondern 3 Byte gepackt BCD vor.
2. Es ist nur mit den Standard AppNote Routinen verglichen.



@Peter
Interessante Technik, alternierendes addieren / subtrahieren.
Das sieht wirklich nicht mehr unterbietbar aus.
Den Tippfehler in Zeile 22 bügelt der Profi selbst aus und verliert
kein Wort darüber (bin halt kein Profi), aber welchen numerischen Wert
hat der Ausdruck in Z 45 "-'0'" oder ist da nur das "-" zu viel?

Dieter

von Philipp S. (philipp)


Lesenswert?

Stimmt, mit dem abwechselnden Addieren spart man sich noch jeweils das
zurücknehmen der überschüssigen Subtraktion: noch drei Befehle gespart.
Clever!

Das -'0' ist richtig, entspricht dem -100 in meinem Code, ist aber
nur verständlich, wenn man AVR-Assembler kennt: es gibt kein 'ADDI',
also 1-Byte-Konstantenaddition, sondern nur SUBI. Um '0' zu addieren,
muß man also -'0' subtrahieren. (Verstehen tue ich das Fehlen von ADDI
übrigens nicht, schließlich braucht man keinen eigenen Befehl im µC,
sondern nur eine Übersetzung durch den Assembler.)

von Patrick M. (Gast)


Lesenswert?

In C würde ich einfach itoa() aus der stdlib benutzen.

Grüße

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.