Autor Beitrag
daywalker0086
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 243


Delphi 2005 Architect
BeitragVerfasst: Mo 12.08.13 16:46 
Hallo Leute,
ich habe eine Gleitkommazahl z.Bsp. m:=116.0 (Wertebereich 4byte).
Diese soll über die serielle Schnittstelle übertragen werden. Dazu muss ich in diesem Fall den Wert 0x42e80000 übertragen wie hier auch durch umrechnen der Zahl 116.0 als Ergebnis gregstoll.dyndns.org...regstoll/floattohex/.
Die frage ist nun wie ich an die Werte komme also ich gehe davon aus das im Speicher der Variable m genau di eZeichenfolge steht, nur wie komme ich daran?

Grüße Christian
IhopeonlyReader
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Mo 12.08.13 16:52 
ich speicher steht das sicher nicht :D
dort stehen die einzelnen Bits...
falls du bit für bit lesen willst, kannst du folgendes machen
(cardinal ist z.B. 4 Byte groß)
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var X: Cardinal;
C: Byte;
begin
For C:=(8*4)-1 downto 0 do // 1 Byte = 8 bits deshalb 8*4.. -1, da bei 0 begonnen wird zu zählen
begin
if Boolean( X and (1 shl C)) then //bit an Stelle C+1 ist auf 1
else //auf ist 0
end;

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
daywalker0086 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 243


Delphi 2005 Architect
BeitragVerfasst: Mo 12.08.13 17:00 
Ich will ja nicht unbedingt bit für bit haben.
Ich habe eine Gleitkommazahl vom typ real, und muss diese Zahl per serielle Schnittstelle übertragen. Der Senderoutine kann ich aber nur einzelne Bytes übergeben. Das heißt Wenn ich eine Real Zahl habe, welche 4 byte groß ist, wie kann ich dann die einzelnen 4 bytes an die serielle Schnittstelle übergeben?
jfheins
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 918
Erhaltene Danke: 158

Win 10
VS 2013, VS2015
BeitragVerfasst: Mo 12.08.13 17:04 
Aber sicher steht das im Speicher ;-)

Kann deine Senderoutine auch Pointer+Länge? Oder nur Bytearrays?

Besonders einfach ginge es, indem du ein ByteArray mit absolute auf den gleichen Speicher zeigen lässt, wie deine Single-Variable.

Real ist übrigens obsolet. Benutze double oder single stattdessen - in diesem Fall single, da du ja genau vier Bytes haben möchtest.
IhopeonlyReader
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Mo 12.08.13 17:08 
achso :D
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
var X: Cardinal;
    B: Array[1..4of Byte;
begin
X := $FFFFFFF0;
B[1] := X shr (8*3);  // X shr 24 = $FF
B[2] := X shr (8*2); // X Shr 16 = $FF
B[3] := X shr (8*1); //X Shr 8 = $FF
B[4] := Byte(X and 255); // oder einfach nur Byte(X); = $F0
end;

B[1] enthält die ersten 8 Bit, B[2] die n ächsten 8...

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19326
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 12.08.13 17:13 
user profile icondaywalker0086 hat folgendes geschrieben Zum zitierten Posting springen:
Die frage ist nun wie ich an die Werte komme also ich gehe davon aus das im Speicher der Variable m genau di eZeichenfolge steht, nur wie komme ich daran?
Die Hexadezimaldarstellung interessiert den seriellen Port wenig. Dort musst du die Bytes hinschicken. Die Hexadezimaldarstellung bekommst du z.B. so:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
var
  a: Single;
begin
  a := 116.0;
  ShowMessage(IntToHex(PInteger(@a)^, 8));
Je nachdem welche Komponente du für den Zugriff auf den seriellen Port benutzt, ist das etwas unterschiedlich, aber normalerweise gibt es dort eine Funktion Write oder so ähnlich zum Schreiben, der du einen Pointer und die Datengröße übergeben kannst. Den Pointer auf die Daten bekommst du mit dem @.
daywalker0086 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 243


Delphi 2005 Architect
BeitragVerfasst: Mo 12.08.13 17:34 
Also mal eine Rückmeldung
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var X: Cardinal;
C: Byte;
begin
For C:=(8*4)-1 downto 0 do // 1 Byte = 8 bits deshalb 8*4.. -1, da bei 0 begonnen wird zu zählen
begin
if Boolean( X and (1 shl C)) then //bit an Stelle C+1 ist auf 1
else //auf ist 0
end;

funktioniert nicht da X hier cardinal ist, ich aber ein real Wert habe.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
var
  a: Single;
begin
  a := 116.0;
  ShowMessage(IntToHex(PInteger(@a)^, 8));


Da steht bei mir im Dialog nur 00000000.

EDIT: Ok zeigt das richtige an, hatte a noch als real deklariert.

Also bis jetzt noch keine Lösung.
Hier mal meine Senderoutine damit ihr seht wie ich Daten über die serielle verschicke:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
    daten[0]:=$06//Adresse der Switchbox im Netzwerk
    daten[1]:=$10//Kommando für Programmierug der SB
    daten[2]:=$06//Länge der Nachricht ohne CRC minus 7
    daten[3]:=wr_anzahl;
    daten[4]:=(sw1); //C3
    daten[5]:=maske_berechnen(1);
    
    for i:=0 to 5 do
    begin
      prog_finish := 0;
      sendstr:=sendstr+inttohex(daten[i],2);
    end;
serialp1.SendString(hextostr(sendstr));

Die Komponente ist SerialNG von DomIS.
www.domis.de/cms/ind...amp;mid=3&ceid=7
daywalker0086 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 243


Delphi 2005 Architect
BeitragVerfasst: Mo 12.08.13 17:48 
So hab es jetzt so gelöst:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
procedure TForm1.Button5Click(Sender: TObject);
var
  a: Single;
  wert:string;
  wert_byte: array[1..4of string;
begin
  a := 116.5;
  wert:= IntToHex(PInteger(@a)^, 2);
  wert_byte[1]:= copy(wert,0,2);
  showmessage(wert_byte[1]);
  wert_byte[2]:=copy(wert,3,2);
  showmessage(wert_byte[2]);
  wert_byte[3]:= copy(wert,5,2);
  showmessage(wert_byte[3]);
  wert_byte[4]:= copy(wert,7,2);
  showmessage(wert_byte[4]);

end;

Jetzt hab ich im Array wert_byte jedes einzelne Byte drin und kann es so über die serielle Schnittstelle ausgeben.

Jetzt die Frage: gehts noch eleganter/einfacher?
MeierZwoo
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 94
Erhaltene Danke: 11

Win 7, DOS5
Delphi 2007 Architect, BP7/TP5, LISP, PS
BeitragVerfasst: Mo 12.08.13 18:10 
Mich würde grade bei Gleitkommatypen als erstes interessieren, ob die Gegenseite mit den Bytes überhaupt etwas anfangen kann. Auf der Empfängerseite kann ja ein ganz anderes Programm, durch einen völlig anderen Compiler oder auch nur einer anderen Compiler-Version erstellt die Bytes lesen und sich wundern, was das soll.

Denn die Gegenseite muß ja den exakt selben Datentyp verwenden, um die Bytes dann wieder in der richtigen Form in den Speicher zu schreiben ... und zu interpretieren. Und da kann schon ein Versionswechsel, oder eine andere Plattform (32bit, 64bit) alles zunichte machen.

Deshalb ist bei DFÜ der Normalfall, die Werte in Strings umzuwandeln und so zu senden ... es sei denn, es handelt sich auf exakt aufeinander abgestimmte Hardware mit abgestimmter Firm- und Software, wie z.B. im Meß- und Regelwesen.
IhopeonlyReader
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Mo 12.08.13 18:41 
user profile icondaywalker0086 hat folgendes geschrieben Zum zitierten Posting springen:
Also mal eine Rückmeldung
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var X: Cardinal;
C: Byte;
begin
For C:=(8*4)-1 downto 0 do // 1 Byte = 8 bits deshalb 8*4.. -1, da bei 0 begonnen wird zu zählen
begin
if Boolean( X and (1 shl C)) then //bit an Stelle C+1 ist auf 1
else //auf ist 0
end;

funktioniert nicht da X hier cardinal ist, ich aber ein real Wert habe.

dein ernst? dann mach halt
X als real und anstatt in der schleife 8*4 schreibste 8*8.. (real ist doch 8 Byte groß oder?)

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
IhopeonlyReader
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Mo 12.08.13 18:46 
mal alles auf real umgeschrieben
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
var X: Real;
    B: Array[1..8of Byte;
    C: Byte; //Counter
    HilfX: Real;
begin
//x setzten auf was für einen wert auch immer
For C := 7 downto 0 do
  B[8-C] := X shr (8*C)
end

//und wieder zusammensetzten
X := 0;
For C:=7 downto 0 do
  begin
  HilfX := B[C];
  HilfsX := HilfsX shl (8*C);
  X := X or HilfsX;
  end;


Moderiert von user profile iconMartok: Code- durch Delphi-Tags ersetzt

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19326
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 12.08.13 20:43 
Warum um alles in der Welt friemelst du da mit Strings herum, wenn du gar keinen String schicken willst? Die genannte Komponente hat den Befehl SendData...
ausblenden Delphi-Quelltext
1:
2:
3:
4:
var
  a: Single;

serialp1.SendData(@a, SizeOf(a));
Und um die Bytes alle zu schicken könntest du ein array of Byte benutzen.
mandras
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 433
Erhaltene Danke: 107

Win 10
Delphi 6 Prof, Delphi 10.4 Prof
BeitragVerfasst: Mo 12.08.13 21:31 
jaenickes Methode ist die kürzeste,

verständlicher ist vielleicht folgendes wenn man doch auf einzelne Bytes zugreifen muß:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure TForm1.Button1Click(Sender: TObject);
var a:single;
    b:array[0..3of byte absolute a;
begin
 a:=116;
 // danach ist:
 // b[0]=0, b[1]=0, b[2]=$e8, b[3]=$42
end;
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6395
Erhaltene Danke: 149

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Di 13.08.13 08:18 
Und wer noch weiß, was ein Record ist, kann es auch über einen varianten Record machen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var
  a : record
    case Boolean of
      True  : (s : Single);
      False : (b : Array[0..3of Byte);
    end;
...
a.s := 116.5;

Dann steht in a.b Byte-Darstellung.

Aber ich würde auch die Variante von Jaenicke nehmen. :wink: