Forum: Mikrocontroller und Digitale Elektronik Umwandeln von Char "C" und "2" in Hex C2


von Tobias S. (Gast)


Lesenswert?

Hallo zusammen,

ich schreibe gerade an einer UART Kommunikation, bei der Eigentliche 
Hex-Bytes also z.B 0xC2 als 2 einzelne Char (je ein byte) C und 2 
übermittelt werden.

Einseitig habe ich die Umwandlung mit Bitmanipulation und einem 
Hilfsarray hinbekommen, jedoch klappt der folgende Weg nicht.

Es liegt C als Char vor, also 0x43 und somit 0100 0011
ebenso wie 2 also 0x32 und somit 0011 0010

Nun möchte ich diese beiden Chars wieder zu einem Hexwert zusammenfügen.

Leidet kommt bei meinem Veruschen alles raus, aber nicht dass was ich 
möchte, nämlich 0xC2, also 1100 0010

Kann mir vielleicht jemand auf die Sprünge helfen.
Bin mir fast sicher, dass ich nur einen Denkfehler hab.

Besten Dank.

Gruß Tobias

von M. K. (sylaina)


Lesenswert?

Aus einem Char, welches eine Zahl ist, einen Int zu machen ist ja kein 
Ding, weißt du, oder? Tipp: ATOI.
Und aus dem Char C eine Zahl zu machen ist ja auch kein Ding, könnte man 
über eine Switch-Case-Funktion lesen, es sind ja nur 6 Werte, die bei 
rum kommen können.

von c-hater (Gast)


Lesenswert?

Tobias S. schrieb:

> Bin mir fast sicher, dass ich nur einen Denkfehler hab.

Ich würde eher sagen: du beherrschst einfach nicht mal ansatzweise die 
Sprache, in der du programmierst...

Das hat nix mit "Denken" zu tun. Ist vielmehr eine reine Fleißaufgabe. 
So ähnlich wie das Auswendiglernen von Gedichten. Jedenfalls nicht sehr 
viel darüber.

von Juven (Gast)


Lesenswert?

c-hater schrieb:
> Tobias S. schrieb:
>
>> Bin mir fast sicher, dass ich nur einen Denkfehler hab.
>
> Ich würde eher sagen: du beherrschst einfach nicht mal ansatzweise die
> Sprache, in der du programmierst...
>
> Das hat nix mit "Denken" zu tun. Ist vielmehr eine reine Fleißaufgabe.
> So ähnlich wie das Auswendiglernen von Gedichten. Jedenfalls nicht sehr
> viel darüber.

Diesen Schwätzer einfach nicht beachten. Der kann nichts, der macht sich 
nur wichtig.

von Tobias S. (Gast)


Lesenswert?

Michael K. schrieb:
> Aus einem Char, welches eine Zahl ist, einen Int zu machen ist ja
> kein
> Ding, weißt du, oder? Tipp: ATOI.
> Und aus dem Char C eine Zahl zu machen ist ja auch kein Ding, könnte man
> über eine Switch-Case-Funktion lesen, es sind ja nur 6 Werte, die bei
> rum kommen können.

Hallo Michael,

ja das ist korrekt.
Nur fuchst es mich etwas, dass ich es nicht mit Bitmanipulation 
hinbekommen.
Im Endeffekt ist es ja nur ein zusammenführen von 2 nibble.

Nur genau beim verschieben und Ver"UND"en ist wahrscheinlich mein 
Fehler.

Gruß Tobias

von Tobias S. (Gast)


Lesenswert?

Juven schrieb:
> c-hater schrieb:
>> Tobias S. schrieb:
>>
>>> Bin mir fast sicher, dass ich nur einen Denkfehler hab.
>>
>> Ich würde eher sagen: du beherrschst einfach nicht mal ansatzweise die
>> Sprache, in der du programmierst...
>>
>> Das hat nix mit "Denken" zu tun. Ist vielmehr eine reine Fleißaufgabe.
>> So ähnlich wie das Auswendiglernen von Gedichten. Jedenfalls nicht sehr
>> viel darüber.
>
> Diesen Schwätzer einfach nicht beachten. Der kann nichts, der macht sich
> nur wichtig.

Das hab ich bemerkt, ich ignoriere das jetzt einfach dezent

von Michael U. (amiga)


Lesenswert?

Hallo,

was ist das Problem?
Die 2 Char als 8-Bit Wert betrachten. Ist der Wert größer als 9 (0x39) 
dann - 0x37, wenn nicht -0x30.
Den höherwertigen teil * 16 oder 4 Bit nach links schieben.
Den niederwertigen Teil genauso behandeln und mit den oberen ver-odern.

Macht man beim konvertiren von Bin nach Hex genauso, nur andersrum.

Gruß aus Berlin
Michael

von Karl H. (kbuchegg)


Lesenswert?

Tobias S. schrieb:

> Kann mir vielleicht jemand auf die Sprünge helfen.

Fang damit an, dir eine Funktion zu schreiben, die aus EINEM Character 
den entsprechenden Zahlenwert generiert.
Das ist an für sich leicht. Denn wenn dieses Zeichen im Bereich '0' bis 
'9' liegt, dann brauchst du vom ASCII Code des Zeichens nur den ASCII 
COde von '0' abziehen und du hast den numerischen Wert. Liegt das 
Zeichen aber im Bereich 'A' bis 'F', dann ziehst du von ihm den ASCII 
COde von 'A' ab und addierst wieder 10. Dann das Hexadezimale Digit A 
hat ja den dezimalen Wert 10.
1
uint8_t toHexDigit( char c )
2
{
3
  if( c >= '0' && c <= '9' )
4
    return c - '0';
5
6
  if( c >= 'A' && c <= 'F' )
7
    return c - 'A' + 10;
8
9
  return 0;

AUf die Kleinbuchstaben nicht vergessen! Das ist aber als Übung für den 
geneigten Leser gedacht.

Um aus 2 eingehenden Zeichen die enstprechende Zahl zu machen ist dann 
einfach
1
uint8_t zahl = toHexDigi( erstes_Zeichen ) * 16 + toHexDigit( zweites_Zeichen );

> Bin mir fast sicher, dass ich nur einen Denkfehler hab.

es wäre gut, wenn du COde zeigen würdest. Dann könnte man dir zeigen, wo 
du den Denkfehler hast.

: Bearbeitet durch User
von Sebastian V. (sebi_s)


Lesenswert?

Tobias S. schrieb:
> Nur genau beim verschieben und Ver"UND"en ist wahrscheinlich mein
> Fehler.

Ich hoffe du hast nicht wirklich ein UND gemacht. Da bleibt nichts mehr 
übrig von deinen Nibbles. Du meinst wohl OR.

von Karl H. (kbuchegg)


Lesenswert?

Tobias S. schrieb:

> Nur genau beim verschieben und Ver"UND"en ist wahrscheinlich mein
> Fehler.

Überlass solchen Kleinscheiss dem Compiler. der kann das.

Für dich ist es ganz einfach:
Um aus den beiden dezimalen Ziffern 3 und 4 die Zahl 34 zu erzeugen, 
rechnest du
1
   3 * 10     -> 30
2
                + 4
3
              ------
4
                 34

und nichts anderes machst du bei Hex-Ziffern. Nur dass du anstelle von 
10 mit 16 multiplizierst. Denn genau deswegen ist es ja das 
Hexadezimalsystem.

von Tobias S. (Gast)


Lesenswert?

Karl H. schrieb:
> Tobias S. schrieb:
>
>> Kann mir vielleicht jemand auf die Sprünge helfen.
>
> Fang damit an, dir eine Funktion zu schreiben, die aus EINEM Character
> den entsprechenden Zahlenwert generiert.
> Das ist an für sich leicht. Denn wenn dieses Zeichen im Bereich '0' bis
> '9' liegt, dann brauchst du vom ASCII Code des Zeichens nur den ASCII
> COde von '0' abziehen und du hast den numerischen Wert. Liegt das
> Zeichen aber im Bereich 'A' bis 'F', dann ziehst du von ihm den ASCII
> COde von 'A' ab und addierst wieder 10. Dann das Hexadezimale Digit A
> hat ja den dezimalen Wert 10.
> uint8_t toHexDigit( char c )
> {
>   if( c >= '0' && c <= '9' )
>     return c - '0';
>
>   if( c >= 'A' && c <= 'F' )
>     return c - 'A' + 10;
>
>   return 0;
>
> AUf die Kleinbuchstaben nicht vergessen! Das ist aber als Übung für den
> geneigten Leser gedacht.
>
> Um aus 2 eingehenden Zeichen die enstprechende Zahl zu machen ist dann
> einfachuint8_t zahl = toHexDigi( erstes_Zeichen ) * 16 + toHexDigit(
> zweites_Zeichen );
>
>> Bin mir fast sicher, dass ich nur einen Denkfehler hab.
>
> es wäre gut, wenn du COde zeigen würdest. Dann könnte man dir zeigen, wo
> du den Denkfehler hast.

Vielen Dank,

du wirst lachen, oder mir es nicht glauben, aber genau den Ansatz habe 
ich jetzt gerade aufgeschrieben.

Das macht mich jetzt aus eigenem Interesse nicht ganz glücklich aber es 
klappt auf jeden Fall..


Also vielen Dank, für eure Hilfe :)

Gruß Tobias

von Ralph S. (jjflash)


Lesenswert?

#include <stdio.h>

unsigned char asc2char(unsigned char ziffhi, unsigned char zifflo)
{
  unsigned char ziff2nibble(unsigned char ziff)
  {
    if (ziff < ':') { return ziff - 48; }
    if (ziff < 'G') { return ziff - 55; }
    return (ziff - 87);
  }

 return (ziff2nibble(ziffhi) << 4) + ziff2nibble(zifflo);
}

int main(void)
{
  unsigned char by;

  by= asc2char('f','3');
  printf("\n\r%.2X\n\r",by);
  return 0;
}

von Ralph S. (jjflash)


Lesenswert?

oh ... :-(( ich war zu langsam !

von Karl H. (kbuchegg)


Lesenswert?

Ralph S. schrieb:
> #include <stdio.h>
>
> unsigned char asc2char(unsigned char ziffhi, unsigned char zifflo)
> {
>   unsigned char ziff2nibble(unsigned char ziff)
>   {
>     if (ziff < ':') { return ziff - 48; }

Autsch.
Gewöhn dir diesen Unsinn ab, die ASCII Codes direkt hinzuschreiben.

Wenn du '0' meinst, dann schreib auch '0'
1
    .... return ziff - '0';

von Ralph S. (jjflash)


Lesenswert?

... dann ... muesste ich auch schreiben:

return ziff - 'A' + 10;

Hmm, ich komme noch von "richtig alten Zeiten" als ein Compiler noch 
nicht so "schlau" war und ein -'A' + 10 intern NICHT optimierte und 
daraus noch eine Rechenoperation mehr machte...

(smile ... die "Entry-Punkte" für '0', 'a', 'A' des Ascii-Codes sind mir 
damals ins Blut gelegt worden)


Der Uralte Compiler war damals ein Compiler fuer einen 8048 MCU auf 
einem HP-150 Rechner mit C/PM 86

Sorry (werde mich bei weiteren Codeschnippseln "bessern")

Ralph

PS: ich weiß nicht mehr welcher C- Compiler das war .... irgendwie muß 
das um das Jahr 1981 gewesen sein (da war ich mit der Lehre gerade 
fertig)

von Karl H. (kbuchegg)


Lesenswert?

Ralph S. schrieb:
> ... dann ... muesste ich auch schreiben:
>
> return ziff - 'A' + 10;

Ja. Klar.
so ist es doch viel einfacher zu verstehen, was hier die Absicht ist.

> Hmm, ich komme noch von "richtig alten Zeiten" als ein Compiler noch
> nicht so "schlau" war und ein -'A' + 10 intern NICHT optimierte und
> daraus noch eine Rechenoperation mehr machte...

Ah geh.
Schon die ersten Compiler vor Beginn der Zeitrechnung konnten Constant 
Folding. Das ist die simpelste aller Übungen für einen Compiler. Einen 
Expression Tree muss er sich sowieso aufbauen, um notwendige Casts 
einzubauen. Diesen Baum dann noch einmal rekursiv abklappern, bei jeden 
Operations-Knoten links im Baum nachsehen, ob da eine Konstante steht, 
rechts nachsehen ob eine Konstante steht und wenn ja den 
Operationsknoten samt linken und rechtem Subknoten durch das 
ausgerechnete Ergebnis zu ersetzen, ist trivial.
Wenn ein Compiler das nicht kann, dann nur aus stinkender Faulheit des 
Compilerbauers. Technisch sind zumindest die einfacheren Formen von 
Constant Folding bei dem die Konstanten direkt hintereinander kommen ein 
Kinderspiel.

: Bearbeitet durch User
von Thomas E. (picalic)


Lesenswert?

oder so:

    return (ziff <= '9' ? ziff&0x0F : (ziff&0x0F)+9);

von Michael B. (laberkopp)


Lesenswert?

Thomas E. schrieb:
> oder so:
>
     return (ziff <= '9' ? ziff : ziff+9 ) & 0x0F;

von S. K. (hauspapa)


Lesenswert?

>AUf die Kleinbuchstaben nicht vergessen! Das ist aber als Übung für den
>geneigten Leser gedacht.

evtl. solltem an noch abfangen das ein böser Bube auch mal:
Q§ W° R+ T" Z* Uç I% O& P/ ü( l) K= j? S` ~^ '...
oder ein paar Steuerzeichen senden könnte.

hat mit der gestellten Frage nichts mehr zu tun aber die ist ja auch 
beantwortet
hauspapa

von Stefan K. (stefan64)


Lesenswert?

Der Vollständigkeit halber:
Kleine Erweiterung, damit Karls Funktion auch mit Kleinbuchstaben als 
Hexziffern umgehen kann:

1
uint8_t toHexDigit( char c )
2
{
3
  if( c >= '0' && c <= '9' )
4
    return c - '0';
5
6
  if( c >= 'A' && c <= 'F' )
7
    return c - 'A' + 10;
8
9
  if( c >= 'a' && c <= 'f' )
10
    return c - 'a' + 10;
11
12
  return 0;
13
}


Gruß, Stefan

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.