Forum: Compiler & IDEs Dezimal nach Hex-Umwandlung PIC18


von Gerhard (sgssn)


Lesenswert?

Hallo
steh gerade auf dem Schlauch. Ich empfange Daten über eine 
UART-Schnittstelle, die Spannungen in ASCII kodiert überträgt. Spannung 
in mV. 26,100 Volt kommt da also als 32, 36, 31, 30, 30
daraus die Zahl 26100 zu machen ist kein Problem. So zum Vergleichen und 
weiterverabeiten bräuchte ich das jetzt als 16-Bit Integer in hex, das 
wäre lt meinem Taschenrechner 65F4. Nur wie komme ich dahin? habs mal 
mit google probiert, nur die rechnen dabei ja in Dezimal, das tut aber 
der uC nicht. Und ich komme nicht drauf, wie das gehen könnte, jongliere 
mit dem taschenrechner im Hex-modus, komm aber nicht klar. Kann mir 
einer nen Tipp geben?

Danke und Gruß
Gerhard

von Harald A. (embedded)


Lesenswert?

atoi

von Rüdiger B. (rbruns)


Lesenswert?

Keine passende Lib für deine Entwicklungsumgegund gefunden ? scanf etc.

von Gustl B. (gustl_b)


Lesenswert?

Gerhard schrieb:
> daraus die Zahl 26100 zu machen ist kein Problem.

Wir haben zum Glück ein Stellenwertsystem.
1
2*10^4 + 6*10^3 + 1*10^2 + 0*10^1 + 0*10^0

: Bearbeitet durch User
von Harald A. (embedded)


Lesenswert?

Gerhard schrieb:
> So zum Vergleichen und
> weiterverabeiten bräuchte ich das jetzt als 16-Bit Integer in hex

Ich glaube da liegt auch noch ein kleines Verständnisproblem vor. Der 
Wert als solches muss zum Weiterverarbeiten muss in eine Variable. Wie 
sie von Dir "interpretiert" wird, also Binär, Octal, Dezimal, HEX ist 
nur eine Betrachtungsweise.

Wenn Du z.B. schreibst "wert=0x5A;" wird im Speicher der 16-bit Variable 
das Bitmuster "0000000001011010" abgelegt. Du hättest auch "wert=90;" 
schreiben können und das Ergebnis ist exakt identisch.

von Oliver S. (oliverso)


Lesenswert?

Gerhard schrieb:
> So zum Vergleichen und
> weiterverabeiten bräuchte ich das jetzt als 16-Bit Integer in hex,

Wo und warum brauchst du das? Kannst du das mal näher beschreiben?

Oliver

von Rüdiger B. (rbruns)


Lesenswert?

Er hat einen STRING und will daraus eine Variable machen.
also mit z.B. https://de.mathworks.com/help/matlab/ref/str2num.html

von Rolf (rolf22)


Lesenswert?

Harald A. schrieb:
> Wenn Du z.B. schreibst "wert=0x5A;" wird im Speicher der 16-bit Variable
> das Bitmuster "0000000001011010" abgelegt. Du hättest auch "wert=90;"
> schreiben können und das Ergebnis ist exakt identisch.

Das stimmt zwar, geht aber an der Fragestellung völlig vorbei. Dass das 
Ergebnis in deinem Beispiel identisch ist, liegt ja nur daran, dass der 
Compiler freundlicherweise und quasi unsichtbar die Umwandlung aus dem 
Dezimal- ins Dualsystem vornimmt, bevor das Anwendungsprogramm gestartet 
wird. In dessen Speicher gibt es in dem Fall gar keine Dezimalzahl, 
soweit es die beiden Befehle betrifft: Die arbeiten beide mit dem 
Dualsystem.

Die Daten, die das Programm des OP über eine serielle Schnittstelle 
bekommt, gelangen aber als Dezimalzahl in den Speicher des Programms, da 
ist nirgendwo ein Compiler beteiligt, der irgendetwas umwandelt.

> eine Variable. Wie die von Dir "interpretiert" wird, also Binär, Octal,
> Dezimal, HEX ist nur eine Betrachtungsweise.

Nein. Das Rechenwerk des µP rechnet IMMER im Dualsystem, nie im 
Dezimalsystem. Der Unterschied zeigt sich z. B. bei den Ergebnissen von 
Addition, Multiplikation usw., die wären im Dezimalsystem ganz anders.

: Bearbeitet durch User
von Gerhard (sgssn)


Lesenswert?

Hallo
dankle für die posts. atoi() wäre auch mein Favorit gewessen, gibts aber 
in C99 nicht mehr.

von Frank K. (fchk)


Lesenswert?

Gerhard schrieb:
> Hallo
> steh gerade auf dem Schlauch. Ich empfange Daten über eine
> UART-Schnittstelle, die Spannungen in ASCII kodiert überträgt. Spannung
> in mV. 26,100 Volt kommt da also als 32, 36, 31, 30, 30
> daraus die Zahl 26100 zu machen ist kein Problem. So zum Vergleichen und
> weiterverabeiten bräuchte ich das jetzt als 16-Bit Integer in hex, das
> wäre lt meinem Taschenrechner 65F4. Nur wie komme ich dahin? habs mal
> mit google probiert, nur die rechnen dabei ja in Dezimal, das tut aber
> der uC nicht. Und ich komme nicht drauf, wie das gehen könnte, jongliere
> mit dem taschenrechner im Hex-modus, komm aber nicht klar. Kann mir
> einer nen Tipp geben?

(%= Mod, Rest beim Teilen)
26100 -> gößer oder gleich 16, also ist es nicht das Ergebnis, also 
anfangen
26100 % 16 = 4 -> letzte Stelle
26100 / 16 = 1631 -> größer oder gleich 16, also nächste Runde
1631 % 16 = 15 = F -> vorletzte Stelle
1631 / 16 = 101 -> größer oder gleich 16, also nächste Runde
101 % 16 = 5 -> vorvorletzte Stelle
101 / 16 = 6 -> kleiner als 16, also vorvorvorletzte Stelle und Abbruch

fchk

von Mario M. (thelonging)


Lesenswert?

Spricht ja nichts dagegen, sich beim Sourcecode von atoi() Anregungen zu 
holen. Den Nicht-Hex-Teil kann man ja weg lassen.

von Rolf (rolf22)


Lesenswert?

Gerhard schrieb:
> atoi() wäre auch mein Favorit gewessen, gibts aber
> in C99 nicht mehr.

--> strtoll()

von Jan B. (jan)


Lesenswert?

Vorschlag um die Division zu vermeiden:
26100 -> 65f4

  2 * 0x2710  ; 0x2710 = 10000 in hex
+ 6 * 0x3E8   ; 0x3E8 = 1000 in hex
+ 1 * 0x64    ; 0x64 = 100 in hex
+ 0 * 0xA
+ 0 * 1
-----------
      65f4

Die Multiplikationen lassen sich leicht durch Addition ersetzen,
weil der erste Faktor immer <=9 ist.

von Mario M. (thelonging)


Lesenswert?

Wozu dividieren? Einfach die Stellen (ASCII-0x30) der Reihe nach 
Addieren und zwischendrin die Summe mal 10 nehmen. Statt Multiplikation 
natürlich linksschieben und die Zwischenwerte x2 und x8 addieren.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Die unterste Stelle erhälst du mit
1
 (x >> 0) & 0xf;
Die nächste Stelle erhälst du mit
1
 (x >> 4) & 0xf;
Die nächste Stelle erhälst du mit
1
 (x >> 8) & 0xf;
...
Um aus einer Stelle ein ASCII-Zeichen zu machen addierst du '0' falls 
die Stelle in 0...9 ist und ansonsten 'a'-10 (hex in Kleinschreibung). 
Um Großbuckstaben zu erhalten addierst du stattdessen 'A'-10.

: Bearbeitet durch User
von Gerhard (sgssn)


Lesenswert?

Hallo
Jan genau, so gehts, wie Jan geschrieben hat oder oben schon der Gustl

hier in Primitiv-Form:

//0x26100->0x65F4
  rc24 = 2*10000;
  rc24+= 6*1000;
  rc24+= 100;

Die Lösung von fchk geht nicht, da der olle uC ja in hex rechnet, da 
kommt nur Mist raus - sorry, nicht böse gemeint, mit dem der nem 
ähnlichen Lösungsansatz habe ich mich schon 2 Stunden erfolglos 
rumgeschlagen.

Danke an Alle, ihr seit die Größten!!!

Gerhard

von Rainer W. (rawi)


Lesenswert?

Gerhard schrieb:
> So zum Vergleichen und weiterverabeiten bräuchte ich das jetzt
> als 16-Bit Integer in hex, das wäre lt meinem Taschenrechner 65F4.

Hex ist eine Darstellungsart, genauso wie Dezimal und wird als Format 
bei der Ausgabe festgelegt. Was hat das mit der Verarbeitung zu tun?
Dafür wären die 16-Bit Integer möglicherweise ok, je nachdem, was du 
damit vor hast, d.h. wie du da irgendetwas weiter verarbeiten möchtest.

Gerhard schrieb:
> hier in Primitiv-Form:
>
> //0x26100->0x65F4

Was soll das sein?
0x26100 (155904 dezimal) wäre mindestens eine 24-Bit Integerzahl und hat 
mit 0x65F4 (26100 dezimal) nichts zu tun ('0x' sagt jeweils, dass die 
nachfolgende Zahl als Hexadezimalzahl zu lesen ist, d.h. 16er-System).

> Die Lösung von fchk geht nicht, da der olle uC ja in hex rechnet

Der µC rechnet binär, z.B. mit 16-Bit Integer. Ob du das hinterher in 
Form einer Dezimal- (10er-System) oder Hexadezimalzahl (16er-System) 
schreibst, ist ihm egal.

: Bearbeitet durch User
von Rbx (rcx)


Lesenswert?

Rainer W. schrieb:
> Der µC rechnet binär, z.B. mit 16-Bit Integer. Ob du das hinterher in
> Form einer Dezimal- (10er-System) oder Hexadezimalzahl (16er-System)
> schreibst, ist ihm egal.

Oktal ginge auch noch. Oktal hätte 3 Binärstellen zum Schnellablesen, 
Hexzahlen 4.
(und weil das so ist, könnte man sich auch eine Tabelle erstellen)

von Oliver S. (oliverso)


Lesenswert?

Rainer W. schrieb:
> Was soll das sein?
> 0x26100 (155904 dezimal) wäre mindestens eine 24-Bit Integerzahl und hat
> mit 0x65F4 (26100 dezimal) nichts zu tun

Lies nochmal. Vielleicht kommst ja doch noch drauf.

Gerhard schrieb:
> Spannung
> in mV. 26,100 Volt kommt da also als 32, 36, 31, 30, 30
> daraus die Zahl 26100 zu machen ist kein Problem.

Oliver

von Michael B. (laberkopp)


Lesenswert?

Gerhard schrieb:
> daraus die Zahl 26100 zu machen ist kein Problem.

Du hast also ein

int zahl=26100

und willst die in 4 Stellen hex als ASCII ausgeben
1
char hex[]="0123456789ABCDEF";
2
char digits[]=
3
{
4
   hex[zahl>>12],
5
   hex[(zahl>>8)&15],
6
   hex[(zahl>>4)&15],
7
   hex[zahl&15]
8
};

Gerhard schrieb:
> atoi() wäre auch mein Favorit gewessen, gibts aber in C99 nicht mehr.

C99 ist die Sprache, die enthält nur intrinsische Funktionen, atoi ist 
eine Libraryfunktion, die gibt es so bald du die passende library, z.B. 
stdlib mit #include einschliesst.

Welche libraries auf deiner Plattform vorhanden sind, wissen wir 
natürlich nicht.

Allerdings wüsste ich nicht, was atoi hier nutzt.

itoa wurde mehr helfen  heisst manchmal _itoa.

: Bearbeitet durch User
von R. L. (roland123)


Lesenswert?

Michael B. schrieb:
> Du hast also ein
>
> int zahl=26100
>
> und willst die in 4 Stellen hex als ASCII ausgeben


hier das Wesentliche in Kurzfassung, so wie ich das verstehe:

Gerhard schrieb:
> 26,100 Volt kommt da also als 32, 36, 31, 30, 30

> So zum Vergleichen und
> weiterverabeiten bräuchte ich das jetzt als 16-Bit Integer

von Klaus F. (klaus27f)


Lesenswert?

"Es ist schon alles gesagt, nur noch nicht von allen."


   http://www.karl-valentin.de/zitate/zitate.htm

von Rainer W. (rawi)


Lesenswert?

Oliver S. schrieb:
> Rainer W. schrieb:
>> Was soll das sein?
>> 0x26100 (155904 dezimal) wäre mindestens eine 24-Bit Integerzahl und hat
>> mit 0x65F4 (26100 dezimal) nichts zu tun
>
> Lies nochmal.

Ja, du hast Recht, für manche Leute mögen Einheiten Schall und Rauch 
sein. Deswegen sind schon Marssonden oder Flugzeuge abgestürzt.

Für 0x26100 bräuchte man natürlich nur eine 18-Bit Integerzahl, bei 
byteweiser Speicherorganisation endet das eben trotzdem bei einer 
mindestens 24-Bit Variablen.
Mit 0x26100 als hexadezimaler Schreibweise ergibt sich binär 
0b100110000100000000, d.h. als 3 Byte octal 0o460400.

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

Rainer W. schrieb:
> Für 0x26100 bräuchte man natürlich nur eine 18-Bit Integerzahl

Mag sein, hat aber mit der Fragestellung nichts zu tun. Da kommt gar 
kein 0x26100 vor. Insofern: Frage nochmal lesen, solange, bis du die 
kapiert hast.

Oliver

von Rainer W. (rawi)


Lesenswert?

Oliver S. schrieb:
> Da kommt gar kein 0x26100 vor

War irgendetwas in meinem Tee?

Gerhard schrieb:
> //0x26100->0x65F4

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

Rainer W. schrieb:
> Oliver S. schrieb:
>> Da kommt gar kein 0x26100 vor
>
> War irgendetwas in meinem Tee?
>
> Gerhard schrieb:
>> //0x26100->0x65F4

Ja, da hat der TO dann auch halluziniert. Die eigentliche Frage mit 
allen Infos steht in einem Thread, so auch hier, ganz oben. Da gibt es 
kein 0x26000

Oliver

von Rick (rick)


Lesenswert?

Gerhard schrieb:
> atoi() wäre auch mein Favorit gewessen,
> gibts aber in C99 nicht mehr.
Doch gibt es. Von C89 bis C23. Steckt in stdlib:
https://en.cppreference.com/w/c/string/byte/atoi

von Nick (b620ys)


Lesenswert?

sscanf

von Alexander S. (alesi)


Lesenswert?

Rainer W. schrieb:
> Oliver S. schrieb:
>> Da kommt gar kein 0x26100 vor
>
> War irgendetwas in meinem Tee?
>
> Gerhard schrieb:
>> //0x26100->0x65F4

Du hast nur übersehen, dass das zweimal schlampig bzw. falsch 
geschrieben wurde.

Jan B. schrieb:
> Vorschlag um die Division zu vermeiden:
> 26100 -> 65f4
Gemeint ist 26100 -> 0x65f4

Gerhard schrieb:
> hier in Primitiv-Form:
>
> //0x26100->0x65F4
Gemeint ist 26100 -> 0x65F4

0x26100 kommt vor, gemeint war aber 26100.

Jetzt klar?

: Bearbeitet durch User
von Sebastian W. (wangnick)


Lesenswert?

Das war Rainer auch oben schon klar -- und eigentlich war das auch jedem 
klar.

LG, Sebastian

von Günter L. (Firma: Privat) (guenter_l)


Lesenswert?

von Gerhard schrieb:
> 32, 36, 31, 30, 30
>daraus die Zahl 26100 zu machen ist kein Problem.

Also ist dann ein ASCII-String "26100"?
Daraus soll nun eine echte 16-Bit Integer Binärzahl
0110010111110100 gemacht werden, damit der PIC damit
mathematisch rechnen kann? Und es soll diese 16-Bit Zahl in
Hex angezeigt werden, also als ASCII-String "65F4"?
Die 16-Bit Zahl muß also in ASCII umgewandelt werden.
Ich würde die 0110010111110100 in Vierergruppen aufteilen,
0110 0101 1111 0100. Eine Tabelle anlegen 0000 bis 1111,
und zugeordneter ASCII-Zeichen. Ein Programm schaut nun
in die Tabelle und bekommt das ASCII-Hex-Zeichen.

Den ASCII-String "26100" in Binär wandeln habe ich
erstmal keine Lösung.

von Alexy N. (alexy9)


Lesenswert?

Dein Ansatz ist korrekt, und keine Sorge, das ist ein klassischer 
Stolperstein. Sobald du aus dem ASCII-Strom den Dezimalwert 26100 
gebildet hast, ist die Umrechnung nach Hex reine Mathematik: 26100₁₀ 
entspricht 0x65F4 im 16-Bit-Format. Der Mikrocontroller macht da nichts 
Magisches. Die Verwirrung entsteht meist durch die verschiedenen 
Darstellungen derselben Zahl. Ähnlich wie bei einer Auswahl an 
Herzketten in Rot:https://www.ketteherz.de/  Das Aussehen variiert, die 
Bedeutung bleibt gleich. Hier ändert sich nur das Zahlenformat, nicht 
der Wert.

: Bearbeitet durch User
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.