Teile eines Strings in Integer umwandeln

OP #1934279
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
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
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
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
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
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
> 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
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
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
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
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

Eine eigene Frage? Dieser Thread ist über 15 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.