Forum: Mikrocontroller und Digitale Elektronik Teile eines Strings in Integer umwandeln


von Marc N. (marc-mh)


Angehängte Dateien:

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

von Justus S. (jussa)


Lesenswert?

haben die Daten denn immer dieses XA YB ZC Format? wenn ja, würde ich 
einfach immer die beiden einzelnen Zeichen/chars nehmen und einfach
Zahl1 = 10*(X-0x30)+(A-0x30)
etc machen

von Karl H. (kbuchegg)


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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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]);

von Marc N. (marc-mh)


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

von Karl H. (kbuchegg)


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] );

von Karl H. (kbuchegg)


Lesenswert?

Lothar Miller schrieb:
> 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...

Habs auch grad bemerkt.
Die Info ist mir beim ersten Durchlesen der Frage entgangen.

von Karl H. (kbuchegg)


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.

von Marc N. (marc-mh)


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?

von Karl H. (kbuchegg)


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.

von Tescht (Gast)


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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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?

von Marc N. (marc-mh)


Lesenswert?

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!

Grüße

Marc

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Marc N. schrieb:
> Werde mal nach einem geeigneten Buch suchen!
Fass das Standardwerk ins Auge:
 K&R "Programmieren in C"

von Karl H. (kbuchegg)


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

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.