mikrocontroller.net

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


Autor: Marc N. (marc-mh)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.
sprintf(buffer, "%c%c", inbuffer[6], inbuffer[7]);
sscanf(buffer, "%x", &tmp_CoolantTemp);

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

Autor: Justus Skorps (jussa)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
#define HEXTOI(x)  (isdigit(x) ? x - '0' : x - 'W')
:
tmp_CoolantTemp = 16*HEXTOI(inbuffer[6]) + HEXTOI(inbuffer[7]);

Autor: Marc N. (marc-mh)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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:
void atohex( char c )
{
  if( c >= '0' && c <= '9' )
    return c - '0';

  if( c >= 'A' && c <= 'F' )
    return c - 'A' + 10;

  return 0;
}

....

  tmp_CoolantTemp = atohex( inbuffer[6] ) * 16 + atohex( inbuffer[7] );

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Marc N. (marc-mh)
Datum:

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

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marc N. schrieb:
>> Hart aber herzlich wäre sowas:
>>
>> #define HEXTOI(x)  (isdigit(x) ? x - '0' : x - 'W')
>> :
>> tmp_CoolantTemp = 16*HEXTOI(inbuffer[6]) + HEXTOI(inbuffer[7]);
>> 
>
> 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.

Autor: Tescht (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Marc N. (marc-mh)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.