Forum: Mikrocontroller und Digitale Elektronik Bascom: 10 stellige Hexzahl in Dezimalzahl wandeln


von Jesse P. (parker)


Lesenswert?

Der RFID Leser von Pollin (Best.Nr. 810 059) gibt die Werte in 
hexadezimaler Form aus, ich brauche die Zahlen in dezimaler Form.

Mit Bascom habe ich mich vorher noch nie beschäftigt, denke aber (noch 
:), es ist einfacher die Ausgabe zu ändern, als alles in C neu zu 
programmieren.

Die Umwandlung von einer hexadezimalen Zahl in einem String zu einer 
dezimalen Zahl geschieht mit Hilfe von Hexval 
(http://avrhelp.mcselec.com/hexval.htm). Leider funktioniert diese 
Umrechnung nur für Zahlen des Typs Long (signed 32 Bit: -2147483648 to 
2147483647). Meinen Versuch den Typ Single (unsigned 32 Bit: 1.5 x 
10^–45 to 3.4 x 10^38) zu verwenden quittiert Bascom mit einer 
Fehlermeldung.

Der Hexwert besteht jedoch aus 5 einzelnen Werten, z.B. 1F00451682, dies 
ist korrekt umgewandelt 133148513922. Entsprechend reicht Long nicht 
aus.

Bevor ich mich jetzt in Bascom mit einer manuellen Umrechnung 
beschäftige, dachte ich, ich frage mal die Experten, ob ich etwas 
übersehen habe und/oder ob mir jemand mit einem Codeschnipsel helfen 
kann.

Hier der bisherige Code, der ohne Fehler kompiliert wird, jedoch im 
Ergebnis falsch ist:
1
Dim Hexstr As String * 5
2
Dim Dezzahl As Long
3
4
Dezzahl = Hexval(Hexstr)
5
Hexstr = Str(Dezzahl)
6
Lcd Hexstr

Ich danke schon einmal vorab für eure Hilfe.

Parker

von Route_66 (Gast)


Lesenswert?

Da ich mir keine Anwendung vorstellen kann, wo man den Hex-String von 
RFID's wirklich als Zahl benötigt (z.B. zum Addieren oder 
Multiplzieren),
solltest Du an das Umwandeln einer 48-Bit Hex-Zahl in einen 
Dezimalstring nachdenken. Weil sowas einfach keiner braucht, wird das 
von allen, bei Microcontrollern üblichen, Sprachen nicht unterstützt. 
Auch nicht von BasCom. Du musst es "zu Fuss" selbst machen!

von Route_66 (Gast)


Lesenswert?

sorry: 40-Bit Hex-String

von Jesse P. (parker)


Lesenswert?

Route_66 schrieb:
> Da ich mir keine Anwendung vorstellen kann, wo man den Hex-String von
> RFID's wirklich als Zahl benötigt (z.B. zum Addieren oder
> Multiplzieren),

Die Kartennummer wird in dem Zeiterfassungsystem unserer Firma dezimal 
eingetragen. Ich brauche den Leser nur zur Anzeige der Kartennummer und 
möchte den Zwischenschritt über einen Taschenrechner vermeiden, ein µC 
kann schließlich rechnen :)
Jedoch nur das, was ich ihm vorgebe und da hapert es derzeit ein wenig.

von Route_66 (Gast)


Lesenswert?

d.h. die Verarbeitungssoftware kann keine Buchstaben innerhalb von 
Strings! Wie lang darf denn die Kartennummert werden?

von Route_66 (Gast)


Lesenswert?

Ich persönlich würde das so lösen:
Um Zeit zu sparen, muss nicht der Dezimalwert, sondern ein eindeutiger 
Ziffern-String „errechnet“ werden. Ich würde Byteweise verfahren - also 
aus FF -> 255, aus 00 -> 0 und aus 80 -> 128 machen.
Das ergibt in Deinem Beispiel (1F 00 45 16 82) 31 0 69 22 130.
Das geht mit BasCom. Jetzt können 2 Probleme auftauchen: Die Software 
kann keine "Spaces" in der Kartennummer, dann also 031000069022130. Dies 
könnte zum zweiten Problem führen: Die Ziffernfolge wird zu lang, dann 
kann ein immer gleicher Teil (z.B. der manufacturer-code) weggelassen 
werden.

von Jesse P. (parker)


Lesenswert?

Route_66 schrieb:
> Das ergibt in Deinem Beispiel (1F 00 45 16 82) 31 0 69 22 130.

Das Programm akzeptiert nur die komplett Dezimalzahl, in dem Fall also 
133148513922. Die Umrechnung habe ich jetzt selber geschrieben, ist ja 
kein Problem, nur ist der Speicherplatz des ATiny2313 sehr begrenzt und 
ich überschreite bei der Verwendung von Single die Grenzen.

Ich vermute, ich werde auf C ausweichen müssen.

Danke für Deine Hilfe!

von Peter D. (peda)


Lesenswert?

Jesse Parker schrieb:
> kein Problem, nur ist der Speicherplatz des ATiny2313 sehr begrenzt und
> ich überschreite bei der Verwendung von Single die Grenzen.
>
> Ich vermute, ich werde auf C ausweichen müssen.

Hast Du denn einen Compiler der (long long) unterstützt?

Der AVR-GCC hat das nur sehr codefressend implementiert, läuft daher 
erst auf AVRs >5kB Flash.

Auf dem ATtiny2313 mußt Du es wohl selber implementieren über ein 5 Byte 
Array.
Am einfachsten geht die Subtraktionsmethode von Zehnerpotenzen.


Peter

von Karl H. (kbuchegg)


Lesenswert?

Jesse Parker schrieb:
> Route_66 schrieb:
>> Das ergibt in Deinem Beispiel (1F 00 45 16 82) 31 0 69 22 130.
>
> Das Programm akzeptiert nur die komplett Dezimalzahl, in dem Fall also
> 133148513922. Die Umrechnung habe ich jetzt selber geschrieben, ist ja
> kein Problem, nur ist der Speicherplatz des ATiny2313 sehr begrenzt und
> ich überschreite bei der Verwendung von Single die Grenzen.
>
> Ich vermute, ich werde auf C ausweichen müssen.

Auch dort musst du dir die 48 Bit Arithmetik selber schreiben (wenn long 
long nicht verfügbar ist)

Aber habt ihr wirklich so viele Leute?
Umsatztabelle: mit der RFID Nummer in eine Tabelle gehen aus der man die 
Mitarbeiterkennung herausliest.

Das ist sowieso auch aus folgenden Gesichtspunkten besser:
RFID Karten gehen auch schon mal verloren. Die RFID Nummer wird aus der 
Umsetztabelle herausgelöscht, die neue Karte mit ihrer neuen Nummer wird 
der Mitarbeiterkennung zugeordnet.
-> In den restlichen Datenbanken ändern sich keine Kennungen
   Die verlorene Karte wird sofort unbrauchbar, da es für sie keinen
   Eintrag mehr in der Tabelle gibt

von Jesse P. (parker)


Lesenswert?

@Peter: Du hast Recht, es liegt wohl eher an der Größe der Zahl denn an 
der Programmiersprache. Das mit dem Array ist ein guter Tip, werde das 
mal testen.

@Karl Heinz: Ich glaube hier besteht noch ein Mißverständnis. Ich nutze 
den RFID Leser nur zur Anzeige der Nummer der RFID Karte. Die serielle 
Schnittstelle wird nicht verwendet.
Bisher muß ich mit einer Karte zum Terminal gehen, welches die Nummer 
eine Sekunde anzeigt, d.h. ich stehe recht lange davor, bis ich die 13 
Stellen der Nummer aufgeschrieben habe. Ok, ich schicke immer meinen 
Kollegen die Nummer holen, aber nunja :)
Den RFID Leser von Pollin habe ich in ein Gehäuse eingebaut und ein LCD 
angeschlossen, dort möchte ich nur die Nummer angezeigt bekommen.

Theoretisch ganz einfach, bis dann die Praxis beginnt, mit 13 stelligen 
Zahlen in kleinen ATinys :)

von Peter D. (peda)


Lesenswert?

Jesse Parker schrieb:
> Theoretisch ganz einfach, bis dann die Praxis beginnt, mit 13 stelligen
> Zahlen in kleinen ATinys :)

Kannst Du nicht auf nen ATtiny84 oder 861 wechseln?


Peter

von Karl H. (kbuchegg)


Lesenswert?

Jesse Parker schrieb:

> @Karl Heinz: Ich glaube hier besteht noch ein Mißverständnis. Ich nutze
> den RFID Leser nur zur Anzeige der Nummer der RFID Karte. Die serielle
> Schnittstelle wird nicht verwendet.


Ah. ok
Ich dachte, du möchtest den Leser als Eingabegerät in die Zeiterfassung 
benutzen.

> Theoretisch ganz einfach, bis dann die Praxis beginnt, mit 13 stelligen
> Zahlen in kleinen ATinys :)

Ist aber nicht so schlimm.
Arrayaddition ist nicht so schwer und viel mehr brauchst du nicht, wenn 
du dir die 48 Zahlen mit jeweils nur einem einzigen 1 Bit in einer 
Tabelle vorrätig hältst.

von Jesse P. (parker)


Lesenswert?

Peter Dannegger schrieb:
> Kannst Du nicht auf nen ATtiny84 oder 861 wechseln?

Das werde ich noch versuchen, habe mich bisher nur mit den ATMegas 
beschäftigt und keinen einzigen ATiny vorrätig.

Die Zahl wird mittlerweile (sehr wahrscheinlich) korrekt berechnet, es 
hapert (vermutlich) an der Wandlung mit STR, um die Zahl auszugeben. 
Aufgrund der beengten Verhältnisse habe ich aber auch nicht viel Platz 
zum Testen. Denke ich werde erst einmal den µC tauschen und dann weiter 
testen.

Vielen Dank für die Ideen!

von Karl H. (kbuchegg)


Lesenswert?

Jesse Parker schrieb:
> Peter Dannegger schrieb:
>> Kannst Du nicht auf nen ATtiny84 oder 861 wechseln?
>
> Das werde ich noch versuchen, habe mich bisher nur mit den ATMegas
> beschäftigt und keinen einzigen ATiny vorrätig.
>
> Die Zahl wird mittlerweile (sehr wahrscheinlich) korrekt berechnet, es
> hapert (vermutlich) an der Wandlung mit STR, um die Zahl auszugeben.

Daher auch der Vorschlag das ganze als BCD zu rechnen.
Dann brauchst du keine String Umwandlung :-)

von Jesse P. (parker)


Lesenswert?

Karl heinz Buchegger schrieb:
> Daher auch der Vorschlag das ganze als BCD zu rechnen.
> Dann brauchst du keine String Umwandlung :-)

Jau, das macht Sinn. Leider reicht der ATiny2313 nicht, um das mit 
Bascom umzusetzen. Zumindest kenne ich mich mit Bascom zu wenig aus, um 
dort effektiven Code zu erzeugen. Wobei ich auch C nicht so gut kenne, 
aber auf den ATMegas hatte ich immer genug Platz :)

von Karl H. (kbuchegg)


Lesenswert?

Nur so als erste Anregung in C

Disclaimer: Der Code ist einfach runtergetippt ohne Rücksicht auf 
Optimierungen. Insbesondere würde sich der Code mächtig vereinfachen, 
wenn bei den Zahlen die Einerstelle an der Arrayposition 0 wäre. Aber 
dann wären die Strings nicht mehr so einfach zu lesen :-)
1
#include <stdio.h>
2
#include <string.h>
3
4
typedef char LongNum[14];
5
6
LongNum Bits[] = { "0000000000001",
7
                   "0000000000002",
8
                   "0000000000004",
9
                   "0000000000008",
10
                   "0000000000016",
11
                   "0000000000032",
12
                   "0000000000064",
13
                   "0000000000128",
14
                   "0000000000256",
15
                   "0000000000512",
16
                   "0000000001024",
17
                   "0000000002048",
18
                   "0000000004096",
19
                   
20
                   // .. to be continued
21
};
22
23
void Add( LongNum result, LongNum a, LongNum b )
24
{
25
  unsigned char i;
26
  char carry = 0;
27
  char digit;
28
  
29
  for( i = 0; i < 13; ++i ) {
30
    digit = a[12-i] + b[12-i] - '0' + carry;
31
    if( digit > '9' ) {
32
      digit -= 10;
33
      carry = 1;
34
    }
35
    else
36
      carry = 0;
37
    result[12-i] = digit;
38
  }
39
  result[13] = '\0';
40
}
41
42
void Calc( LongNum result , unsigned char Hex[5] )
43
{
44
  unsigned char i;
45
  unsigned char j;
46
  
47
  strcpy( result, "0000000000000" );
48
  
49
  for( i = 0; i < 5; ++i ) {
50
    for( j = 0; j < 8; ++j ) {
51
      if( Hex[4-i] & ( 1 << j ) )
52
        Add( result, result, Bits[ i * 8 + j ] );
53
    }
54
  }
55
}
56
57
int main()
58
{
59
  LongNum result;
60
  unsigned char Hex[] = { 0x00, 0x00, 0x00, 0x01, 0xFF };
61
62
  Calc( result, Hex );
63
  
64
  printf( "%s", result );
65
}

Die Tabelle der 2-er Potenzen darfst du selbst noch erweitern, bis du 
alle Zahlen bis zur Bitposition 40 hast :-)

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.