Forum: PC-Programmierung hex-Wert inkrementieren ohne a.f


von James (Gast)


Lesenswert?

hi,
ich programmiere mit c# und versuche gerade einen Wert von 0 bis 0x10000 
zu inkrementieren, ohne dass die Werte 0xA bis 0xF beachtet werden.

ich muss also nach 0x09 den Umbruch auch 0x10 machen, das aber für 10er, 
100er und 1000er.

Mein erster Versuch war mit einem if (x == 0x9) x=0x10, aber wie mache 
ich das bei den 1000er? dann muss ich die Zahl in 10er, 100er und 1000er 
zerlegen!?
Das wird dann recht groß mit mehreren "if's" verschachtelt, geht das 
auch 'irgendiwe' eleganter!?

von Peter II (Gast)


Lesenswert?

warum zählst du nicht einfach ein int hoch?

0 1 2 3 4 5 6 7 8 9 10 11 12

und schreibst dann 0x davor?

von Vlad T. (vlad_tepesch)


Lesenswert?

James schrieb:
> hi,
> ich programmiere mit c# und versuche gerade einen Wert von 0 bis 0x10000
> zu inkrementieren, ohne dass die Werte 0xA bis 0xF beachtet werden.

auf deutsch:
du willst mit BCD-Zahlen zählen/rechnen.

von James (Gast)


Lesenswert?

Verstehe ich nicht!
wenn ich eine Zahl inkrementiere wird aus 9 doch 10. 10 in hex sind 0xA 
und das steht in meiner Variable. ich frage jetzt ab und zähle 
entsprechend 6 dazu, denke aber dass es "schneller" oder sauberere gehen 
muss!?
1
if ((SerNo & 0xF) == 0xA)
2
   SerNo += 6;
3
4
if ((SerNo & 0xF0) == 0xA0)
5
   SerNo += 0x60;
6
7
if ((SerNo & 0xF00) == 0xA00)
8
   SerNo += 0x600;

von James (Gast)


Lesenswert?

Vlad Tepesch schrieb:
>auf deutsch:
>du willst mit BCD-Zahlen zählen/rechnen.

RICHTIG, BCD war das Stichwort, danke!

von Vlad T. (vlad_tepesch)


Lesenswert?

die frage ist doch, was willst du erreichen.
Intern mit BCD zu rechnen ist quatsch.
MAch deine Rechnerreien und Zählerreihen ganz normal und konvertiere die 
Zahl für die Ausgabe

von Stefan N. (stefan_n)


Lesenswert?

In C# BCD verwenden zu wollen verstehe ich wirklich nicht. Was hast du 
vor? Irgend ein Gerät ansprechen, welches dieses Format braucht oder 
irgendein merkwürdiges Dateiformat?

Wenn es nicht C# wäre hätte ich ja gesagt inline ASM und DAA :D

von Robert L. (lrlr)


Lesenswert?

>Intern mit BCD zu rechnen ist quatsch.

(ist ja vermutlich eher eine Hausaufgabe)

aber für "irgendwas" wurde BCD mal erfunden

ich erinnere mich auch schwach an CPUs die das direkt unterstützten 
(C64?? oder ein taschenrechner, weiß ich jetzt nicht mehr)

früher war
>und konvertiere die
>Zahl für die Ausgabe

nämlich "sehr" aufwändig...
(bei BCD natürlich easy)

von James (Gast)


Lesenswert?

Das ganze rührt daher dass ich hier ein paar (einige!?) Geräte habe, 
deren Seriennummer auch die Deviceadresse an einem Bussystem ist.

Die Geräteadresse wurde damals zwar dezimal einprogrammiert, aber als 
Hex-wert abgespeichert. Nach der Seriennummer 0x9 kommt also die 
Seriennummer 0x10.

Wenn ich nun die Geräte ansprechen möchte, muss ich zuerst deren 
Seriennummer suchen. (Die Teile sind sehr alt und das Typenschild kann 
man z.T. nicht mehr lesen).

Also schließe ich die Geräte einzeln an den bus an und lass' mein 
Programm nach der Seriennummer suche.
Jedes Gerät wird einzeln angesprochen und ich warte auf eine Antwort.

Bei der Suche wäre es eignetlich egal die Werte 0xA bis 0xF auch 
abzuscannen, wenn ich aber 0xA bis 0xF aus der Suche heraus nehme, spare 
ich mir über die Hälfte der Zeit!

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Nun, dann zähle dezimal, erzeuge einen String aus der Dezimalzahl und 
konvertiere den wiederum in einen Int, aber hexadezimal interpretiert.

Also:

int x = 1234 -> "1234" -> 0x1234

Oder besuch das Internet, ob da vielleicht jemand eine C#-Klasse für 
BCD-Arithmetik geschrieben hat.

von Helmut L. (helmi1)


Lesenswert?

Mach es dir nicht zu kompliziert.

Du nimmst deine Integer und wandelst sie nach ASCII String.

z.B mit itoa

Dann hast du deinen ASCII String. Bei den einzelnen Ziffern im ASCII 
Format loescht du die oberen 4Bits und schon hast du deine BCD Zahlen. 
Die Frage ist jetzt nur noch ob sie je einzeln in einem Byte stehen oder 
zu zweit im gepackten Format.

Und kein Sorge dein PC macht das schneller als du die aussenden kannst 
zu dem Geraet.

von James (Gast)


Lesenswert?

alles klar, dann mach ich das mit dem String.

Es geht mir nicht um die Geschwindigkeit sondern um die Lesbarkeit.
Das alte Programm läuft noch unter DOS und ich habe nur den Bustrace, 
keinen sourcecode.

Nun möchte ich selbige Funktion unter Win implementieren.
Vermutlich muss ich dann in ein paar Jahren nochmal hin und schauen wie 
ich es damals (also heute!?) gemacht habe....


Andere steigen schon auf Win8 um und ich muss noch mit MS DOS arbeiten 
:-(



...wobei, unter DOS habe ich wenigstens noch eine ordentliche 
Umschaltzeit bei RS232, bei Win7 benötige ich jetzt einen 
USB-Seriell-Wandler...

Grüße

von Peter II (Gast)


Lesenswert?

James schrieb:
> bei Win7 benötige ich jetzt einen
> USB-Seriell-Wandler...

warum das? Win7 kannst genau mit echten COM ports umgehen.

von James (Gast)


Lesenswert?

Ich benütze einen 485-Wandler und die Umschaltzeiten von Rx zu Tx sind 
eher willkürlich als definiert.
Ausserdem hat heute nicht jeder PC noch eine serielle Schnittstelle.

Dem USB-Seriell-Wandler kann ich elegant mitteilen dass er nach dem 
Senden von 12 Bytes sofort wieder auf Empfangen schalten soll, so geht 
mir die Antwort nicht verloren.

An der seriellen Schnittstelle meines PCs habe ich die meisten 
Antworttelegramme verloren weil das Umschalten von Tx auf Rx zu lange 
gedauert hat.
Windows macht das irgendwann mal wenn sonst nichts anderes ansteht, bis 
dahin sind dann aber schon 2 oder 3 Bytes verloren gegangen. der µC in 
der Gegenstelle ist etwas zu schnell.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

James schrieb:
> Ich benütze einen 485-Wandler und die Umschaltzeiten von Rx zu Tx sind
> eher willkürlich als definiert.

Das ist kein Problem, wenn man es richtig macht, d.h. eine 
USB-Seriell-Bridge mit Hardwareunterstützung für RS485 verwendet. Dann 
muss man sich auf der Softwareseite überhaupt nicht mehr um die 
Sender-/Empfänger-Umschaltung kümmern.

Ein Beispiel ist der altbekannte FT232; wie ein RS485-Treiber an den 
anzuschließen ist, damit die vollautomatische 
Sender-/Empfänger-Umschaltung funktioniert, ist im Datenblatt 
beschrieben.

Nein, die Kombination fertig gekaufter USB-RS232-Wandler mit daran 
angeschlossenem RS232-zu-RS485-Wandler ist hier nicht verwendbar, weil 
da die vom FT232 vorgesehene Steuerleitung nicht herausgeführt wird.

von Peter II (Gast)


Lesenswert?

James schrieb:
> An der seriellen Schnittstelle meines PCs habe ich die meisten
> Antworttelegramme verloren weil das Umschalten von Tx auf Rx zu lange
> gedauert hat.

also mein Wandler macht das von selber, da muss ich nicht umschalten. 
Habe auch noch nie Daten verloren.

von James (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Das ist kein Problem, wenn man es richtig macht, d.h. eine
> USB-Seriell-Bridge mit Hardwareunterstützung für RS485 verwendet. Dann
> muss man sich auf der Softwareseite überhaupt nicht mehr um die
> Sender-/Empfänger-Umschaltung kümmern.


Sowas ähnliches habe ich jetzt ja!
mein alter (serieller) 232-485-Wandler konnte das nicht, das war rein 
nur hardware mit einem MAX485. nun habe ich mir aus einer vorhandenen 
Platine mit MSP430 und FTDI selbst einen Wandler gebastet. Da war aus 
einem anderen Projekt schon fast alles fertig und ich musste nur noch 
die Telegrammlänge anpassen. Der Rest geht als COM an den PC.

Nur wollte ich jetzt, wenn ich schon was neues mache, nicht auf das alte 
Steckenpferd der seriellen Schnittstelle setzen sondern am PC gleich per 
USB heraus fahren, das ist für die Zukunft sicherlich sinnvoller...

von Vlad T. (vlad_tepesch)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Also:
>
> int x = 1234 -> "1234" -> 0x1234

warum über String funktionen?

so eine umrechnung lässt sich doch leicht aus dem Ärmel schütteln:
1
uint32_t intToBCD(uint32_t input)
2
{
3
  uint32_t res=0;
4
  uint32_t factor = 1;
5
  while(intput>0){
6
    uint32_t rem = input%10;
7
    intput = input/10;
8
    res = rem*factor;
9
    factor *= 16 ;
10
  }
11
  return res;
12
}
(hoffe ich hab jetzt keinen Denkfehler drin, aber das Prinzip sollte 
klar sein.
ich lese eine Dezimalstelle (Rest von Div10) und konvertiere sie in eine 
hexadezimalstelle (*faktor)

von Robert L. (lrlr)


Lesenswert?

>warum über String funktionen?

weil er Rechenpower ohne ende hat
da nimmt man code bei dem man nicht nachdenken muss und
einfach zu lesen ist
man schließt damit die Ungewissheit eines "Denkfehlers" aus...

(wenn man schon den "besten"/schnellsten code haben will, dann würde ich 
in diesem fall, so wie vom TO gefrag, das inkrementieren um eins machen,
das ist WESENTLICH schneller als die ganzen divisionen in deinem 
code...)

von Reinhard Kern (Gast)


Lesenswert?

James schrieb:
> nicht auf das alte
> Steckenpferd der seriellen Schnittstelle setzen sondern am PC gleich per
> USB heraus fahren

Deswegen kannst du ja trotzdem sowas wie den FTDI einsetzen, nur eben im 
Gerät - das ist um einiges einfacher als einen USB-Stack im Controller 
zu implementieren, du kannst die Software im wesentlichen 
weiterbenutzen. Kommt auf den Controller an, aber ich vermute mal stark, 
dass der vorhandene keinen USB-Anschluss hat.

Ausserdem ist ev. zu beachten, dass du mit USB längst nicht so weit 
kommst wie mit RS485, normalerweise 5m.

Gruss Reinhard

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Vlad Tepesch schrieb:
> warum über String funktionen?

Weil hier in C# programmiert wird, und --wie ich gerade an anderer 
Stelle von einem Java-Programmierer mitbekomme-- so etwas selten die, 
sagen wir mal, Nähe zur Realität bietet, die die nicht-String-Variante 
fordert.

Wenn die nicht-String-Variante so auch in C# umsetzbar ist, ist gut, 
dann kann (und sollte) man das natürlich so machen.

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.