mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Mit atoi() aus char-String-Array ein uint64_t machen?


Autor: Wolfgang Birner (logox2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Morgen,

Kann ich mit atoi() aus
// ein array mit hex-werten als ASCII-Zeichen
uint8_t array[24] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '\r', '\n', 0, 0, 0, 0, 0, 0};
ein einfaches int64
uint64_t = 0x0123456789ABCDEF
machen?

Wolfgang

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Wolfgang,

für "string" mit anderen Basen als 10 nach "unsigned long int" benötigst 
Du "strtoul(..)". Ob "unsigned long int" identisch mit uint64_t ist, 
hängt vom Compiler ab.

Gruß

Fred

Autor: Wolfgang Birner (logox2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Fred,

danke für erste Info.

AVR-GCC: typedef unsigned long long int uint64_t

Ich hätte vielleicht mein Problem noch ein wenig genauer beschreiben 
sollen:
Ich verwende WinAVR und einen atmega128 und möchte eine Zeichenkette die 
ich über UART empfange in eine 'echte' Zahl umwandeln. Die Zeichenkette 
ist dabei max. 14 'Hex-Zeichen' lang. Dabei entspricht das erste Zeichen 
dem höchstwertigen Nibbel in der Zahl, das letzte Zeichen, dem 
niederwertigsten Nibbel, die uint64_t muß also (nachdem alle Zeichen 
empfangen worden sind) von rechts her aufgebaut werden.

Wolfgang

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

Bewertung
0 lesenswert
nicht lesenswert
Wolfgang Birner wrote:

> ist dabei max. 14 'Hex-Zeichen' lang. Dabei entspricht das erste Zeichen
> dem höchstwertigen Nibbel in der Zahl, das letzte Zeichen, dem
> niederwertigsten Nibbel, die uint64_t muß also (nachdem alle Zeichen
> empfangen worden sind) von rechts her aufgebaut werden.

Das kannst du on-the-fly zusammenbauen.

Frei nach dem Muster

  Result = 0

  while( nächstes Zeichen gehört zur Hex Zahl ) {
    Result = Result * 16 + HexDigit( nächstes Zeichen )
  }

Getreu dem (Dezimal)Muster

1287 = 1 * 1000 + 2 * 100 + 8 * 10 + 7 * 1 =
       (((( 1 * 10 ) + 2 ) * 10 ) + 8 * 10 ) + 7


Mit der Hilfsfunktion:  HexDigit
int HexDigit( char Digit )
{
  if( Digit >= '0' && Digit <= '9' )
    return Digit - '0';

  return Digit - 'A' + 10;
}

Das hat den Vorteil, dass du theoretisch die Character
gar nicht zwischenspeichern musst, sondern die Zahl aufbauen
kannst während die Ziffern über die UART eintrudeln.

Aufpassen auf die Datentypen!

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Wolfgang,
> AVR-GCC: typedef unsigned long long int uint64_t
also wird es nicht gehen, da "typedef long int uint32_t"! Ausweg: Du 
wandelst zuerst die unteren 8 Zeichen um (gibt Dir die unteren 4 Bytes), 
dann die oberen (gibt Dir die oberen 4) und fügst alles zusammen.
> niederwertigsten Nibbel, die uint64_t muß also (nachdem alle Zeichen
> empfangen worden sind) von rechts her aufgebaut werden.
Sowohl atoi() als auch strtoul() machen es so!

Wenn Du nur mit 16 als Basis arbeitest, ist doch eine Ziffer immer ein 
Nibble. Du kannst also leicht selbst eine Funktion schreiben, die den 
String zeichenweise umwandelt und die Ergebnisse Byte-weise in eine 
Union mit Deiner uint64_t Variablen schreibt!

Gruß

Fred

P.S. Karl-Heinz war schneller - hätte ich mal nicht zwischendurch 
telefoniert!

Autor: Wolfgang Birner (logox2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also theoretischer Weiße müßte ich jetzt alles haben, aber es geht 
nicht:
typedef union{
  uint8_t b8[8];
  uint64_t ll;
} rfid_uid_t;

void main(void)
{
  uint8_t zwischen[20] = {'E', 'A', '4', 'E', '8', 'E', 'A', '4', '\r', '\n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  rfid_uid_t rfid;
  uint8_t l = 0;

  rfid.ll = 0;

      for(l = 0; zwischen[l] != '\r'; l++);
      {
        rfid.ll = rfid.ll * 16 + ( zwischen[l] >= '0' && zwischen[l] <= '9' ? zwischen[l] - 48 : zwischen[l] - 55 );
      }
}

In rfid.ll steht danach aber: 0x17F55555555697A7 und nicht 
0x08000000EA4E8EA4

Was mach ich bloß falsch?

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

Bewertung
0 lesenswert
nicht lesenswert
Wolfgang Birner wrote:

Schau dir mal diese Zeile an. Schau sie dir genau an!

>
>       for(l = 0; zwischen[l] != '\r'; l++);
> 

Siehst du den ; am Ende der Zeile?


PS: Ich werde mein Lebtag nicht verstehen, wass so schön daran ist
48 anstatt '0' zu schreiben.

Autor: Wolfgang Birner (logox2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für den Hinweiß, mach mal sieht man den Wald vor Bäumen nicht.

Ich habs jetzt mal mit einer anderen ID ausprobiert (04055859EE0281) da 
steht jetzt in rfid.ll = 0x9EE027DF55556A47, was immer noch nicht 
0x0004055859EE0281 ist.

Autor: Wolfgang Birner (logox2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke nochmal.

Ich hab gerade eine Möglichkeit gefunden meinen RFID-Reader binär 
auszulesen, jetzt werde ich halt mal versuchen, das zu realisieren. Die 
Sache mit der Umrechnung bekomme ich nicht gebacken.

Wolfgang

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Wolfgang,

zwei Anmerkungen:
1. Ich glaube, der Fehler liegt irgendwie in der Art und Weise, wie Du 
rfid.ll anzeigst, nicht im obigen Code (nach Entfernen des ';').
2. Deine fast klammerlose Zeile rfid.ll=.... ist korrekt. Gerade beim 
Konstrukt "bedingung?a:b" gibt es aber Unterschiede zwischen 
verschiedenen Compilern (C vs. C++; ich bin diesbezüglich mal gewaltig 
reingefallen!) -- deshalb setze ich gerne Klammern (gibt ja keinen extra 
Code, macht die Sache aber übersichtlicher).

Gruß

Fred

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.