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!?
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.
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!?
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
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
>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)
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!
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.
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.
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
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.
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.
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.
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...
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_tintToBCD(uint32_tinput)
2
{
3
uint32_tres=0;
4
uint32_tfactor=1;
5
while(intput>0){
6
uint32_trem=input%10;
7
intput=input/10;
8
res=rem*factor;
9
factor*=16;
10
}
11
returnres;
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)
>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...)
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
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.