Teile eines Strings in Integer umwandeln

OP #1934279
Lesenswert?

Guten Morgen,

vorerst einmal, ich bin neu hier im Forum =] Habe aber schon ein wenig 
mitgelesen und über die Suchfunktion nach meinem Thema gesucht, leider 
nicht fündig geworden.
Ich bin derzeit dabei ein OBD-Interface mit einem ATmega32 aufzubauen. 
Als Scnittstelle zum Auto habe das Diamex DXM-Modul, dass mir alle 
Protokolle aufschlüsselt, ich muss lediglich eine serielle Kommunikation 
zw. DXM Modul und ATmega herstellen.
Soweit klappt das auch erstmal alles ganz gut, siehe obiges Bild! Jetzt 
hab ich folgendes Problem, ich will die Daten nicht nur anzeigen, 
sondern bspw. mit anderen Größen verknüpfen, vor allem muss man sie erst 
noch decodieren.  Bsp.: auf dem Bild zu sehen 41 05 43

"41" ist der Identifier vom Motorsteuergerät
"05" ist der PID, Parameter Identifier, hier Kühlertemperatur
"43" ist der tatsächliche Wert: 4*16 + 3 = 67, jetzt noch 40°C abziehen 
und dann ist die Kühlertemperatur von 27°C berechnet (ist auch korrekt 
so ;-))

Im Programm selbst habe ich den String als char* vorliegen, habe schon 
mit sprintf und sscanf versucht, der Controller stürzt dann ab, 
respektive resettet sich immer wieder selbst.
1
sprintf(buffer, "%c%c", inbuffer[6], inbuffer[7]);
2
sscanf(buffer, "%x", &tmp_CoolantTemp);
3

4
tmp_CoolantTemp = tmp_CoolantTemp - 40;

Ich hoffe ihr könnt mir weiterhelfen. Ist es eventuell ratsam einen 
anderen µC zu nehmen, wie z.B. einen 32bit?

Ich freue mich riesig auf Antworten und verbleibe bis dahin

mit freundlichen Grüßen

Marc Nitze
Angehängte Dateien:
#1934295
Lesenswert?

Marc N. schrieb:

> Ich hoffe ihr könnt mir weiterhelfen. Ist es eventuell ratsam einen
> anderen µC zu nehmen, wie z.B. einen 32bit?

Was soll das bringen.
Ratsam wäre ein C-Buch und ein paar Übungsstunden auf dem PC

Also:
Ich hab dein Problem jetzt noch nicht wirklich verstanden.
Allerdings drängt sich die Frage auf, warum du da jetzt einen Umweg über 
sprintf/sscanf machst.

  tmp_CoolantTemp = inbuffer[6] * 16 + inbuffer[7];

scheint das zu sein, was du suchst.
Moderator (Firma: Titel) Persönliche Seite #1934297
Lesenswert?

Karl heinz Buchegger schrieb:
> tmp_CoolantTemp = inbuffer[6] * 16 + inbuffer[7];
> scheint das zu sein, was du suchst.
Wird für ASCII-Hex-Zahlen so nicht gehen...

Marc N. schrieb:
> Ich hoffe ihr könnt mir weiterhelfen.
Hart aber herzlich wäre sowas:
1
#define HEXTOI(x)  (isdigit(x) ? x - '0' : x - 'W')
2
:
3
tmp_CoolantTemp = 16*HEXTOI(inbuffer[6]) + HEXTOI(inbuffer[7]);
OP #1934301
Lesenswert?

Das Format ändert sich für andere PID's, bspw. die Motordrehzahl. Da 
sind dann 2 Bytes auszuwerten, siehe die Zeile darüber. Dort erfolgt die 
Umrechnung mit:

((A*256)+B)/4 = x -> 41 0C 0C E5, dabei ist 0C das Byte A, E5, das Byte 
B... Zudem kann bei jedem der PID's noch "CAN ERROR" zurückkommen, 
leider^^


Grüße

Marc
#1934302
Lesenswert?

Karl heinz Buchegger schrieb:

> Allerdings drängt sich die Frage auf, warum du da jetzt einen Umweg über
> sprintf/sscanf machst.
>
>   tmp_CoolantTemp = inbuffer[6] * 16 + inbuffer[7];
>
> scheint das zu sein, was du suchst.


Oder wenn das Hex Zahlen sein sollen:
1
void atohex( 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;
10
}
11

12
....
13

14
  tmp_CoolantTemp = atohex( inbuffer[6] ) * 16 + atohex( inbuffer[7] );
#1934309
Lesenswert?

Marc N. schrieb:
> Das Format ändert sich für andere PID's, bspw. die Motordrehzahl. Da
> sind dann 2 Bytes auszuwerten,

Das macht nichts.
Bau dir eine Funktion die erst mal 1 Byte entsprechend umwandelt.
Die nimmst du dann als Baustein um mehrere Bytes entsprechend 
umzuwandeln.

Genau aus dem Grund hat man ja Funktionen.
Damit man aus einfachen Basisfunktionalitäten komplexere 
Funktionalitäten zusammensetzen kann.
OP #1934317
Lesenswert?

> Hart aber herzlich wäre sowas:
>
1
> #define HEXTOI(x)  (isdigit(x) ? x - '0' : x - 'W')
2
> :
3
> tmp_CoolantTemp = 16*HEXTOI(inbuffer[6]) + HEXTOI(inbuffer[7]);
4
>

Ich kann diese Funktion nicht nachvollziehen, sie wandelt mir ein 
Hex-Byte in einen Integer um, korrekt? Wie tut sie das?
#1934325
Lesenswert?

Marc N. schrieb:
>> Hart aber herzlich wäre sowas:
>>
1
>> #define HEXTOI(x)  (isdigit(x) ? x - '0' : x - 'W')
2
>> :
3
>> tmp_CoolantTemp = 16*HEXTOI(inbuffer[6]) + HEXTOI(inbuffer[7]);
4
>>
>
> Ich kann diese Funktion nicht nachvollziehen, sie wandelt mir ein
> Hex-Byte in einen Integer um, korrekt? Wie tut sie das?

indem sie unterscheidet, ob es sich beim ASCII Zeichen um eines im 
Bereich '0' bis '9' handelt oder nicht (dann kann es nur noch ein 
Buchstabe 'A' bis 'F' sein)

isdigit macht das. Das stellt fest ob es sich bei einem Zeichen um eines 
im Bereich '0' bis '9' handelt.

Wenn ja, dann wird vom Zeichen, eigentlich dessen ASCII Code, der ASCII 
Code von '0' abgezogen.  Aus '0' wird 0, aus '1' wird 1, etc.

Dasselbe bei den Buchstaben
Aus 'A' muss 10 werden, aus 'B' muss 11 werden etc.
Zieht man daher vom Zeichen den ASCII Code von 'A' ab, dann wird 'A' zu 
0, 'B' zu 1, 'C' zu 2 etc. Dann noch 10 dazuzählen und aus 0, 1, 2, 3 
wird 10, 11, 12 13 ....

    x - 'A' + 10

Lothar hat das 'A' + 10 zusammengezogen (hätte er nicht machen müssen. 
das macht der Compiler auch).

Und das ? :
Das ist einfach nur die kurze C-Schreibweise für

    if ( a )
      b = c;
    else
      b = d;

oder in Kurzform

    b =  a  ?  c  : d;


und da das alles Basissachen in der C Programmierung sind, bleibe ich 
nach wie vor dabei, dass dein Hauptfehler darin besteht, dass du kein 
C-Buch durchgearbeitet hast. Eine Sprache wie C kann man nicht nach dem 
Muster Versuch und Irrtum erlernen. Dazu hat sie viel zu viele 
Feinheiten und Nuancen. Geht man da nicht systematisch ran, dann ist 
hinterher das Geschrei immer groß, dass C soooo kompliziert und 
fehleranfällig wäre.
Gast #1934327
Lesenswert?

isdigit(x) ? x - '0' : x - 'W'

wenn x eine Zahl ist dann wird x-'0' gerechnet (also ASCII 0)
sonst wird x-'W' gerechnet (also ASCII W)

Schau dir mal die ASCII Tabelle an. Die '9' ist z.B. die dez 57, wird 
davon nun '0' (also dez 48) abgezogen, so erhälst du deine int 9
Moderator (Firma: Titel) Persönliche Seite #1934330
Lesenswert?

Marc N. schrieb:
> Ich kann diese Funktion nicht nachvollziehen, sie wandelt mir ein
> Hex-Byte in einen Integer um, korrekt? Wie tut sie das?
Erst mal das Makro:
es wandelt ein Ascii-Zeichen in einen Integer zwischen 0..15 um. Zum 
Nachvollziehen ist eine ASCII-Tabelle sinnvoll...

Statt:
#define HEXTOI(x)  (isdigit(x) ? x - '0' : x - 'W')
könnte man auch schreiben:
#define HEXTOI(x)  (isdigit(x) ? x - '0' : x - 'a' + 10)
Weil 0xa = 10 ist...
Am Rande sollte man wissen, dass das Makro nur für "kleine" Hex-Zahlen 
funktioniert 0..9, a..f

Für "große" Hex-Zahlen (0..9, A..F) wäre das hier nötig:
#define HEXTOI(x)  (isdigit(x) ? x - '0' : x - 'A' + 10)
bzw:
#define HEXTOI(x)  (isdigit(x) ? x - '0' : x - '7')

Vielleicht wirds jetzt klarer?
#1934338
Lesenswert?

Marc N. schrieb:
> Vielen Dank auf jeden Fall für eure Hilfe! Werde mal nach einem
> geeigneten Buch suchen! Hoffe, dass ich dennoch bei weiteren Fragen auf
> euch zurückgreifen darf!

Natürlich.
Aber du hast einfach mehr von der Sprache, wenn dein Verständnis nicht 
auf in Foren zusammengefragtem Halbwissen beruht.

Kernighan&Ritchie  Programmieren in C

ist zb der Klassiker der C-Bücher

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren