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?
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.
'Tschuldigung: der µC steht ja im Betreff, nur die Sprache finde ich nicht.
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
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...
3te Klase Mathematik teilen von zahlen 111 / 10 = 11 (rest1) 110 _ 1
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
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
@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!
@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
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.
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
@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
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.)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.