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
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!
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.
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.
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!
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
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
@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 :)
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
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.
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!
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 :-)
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 :)
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
typedefcharLongNum[14];
5
6
LongNumBits[]={"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
voidAdd(LongNumresult,LongNuma,LongNumb)
24
{
25
unsignedchari;
26
charcarry=0;
27
chardigit;
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
voidCalc(LongNumresult,unsignedcharHex[5])
43
{
44
unsignedchari;
45
unsignedcharj;
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
intmain()
58
{
59
LongNumresult;
60
unsignedcharHex[]={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 :-)