Array of byte in array of word umwandeln

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Benutzeravatar
KoBraSoft
Beiträge: 125
Registriert: So 6. Jun 2021, 09:57
OS, Lazarus, FPC: die zu Zeit aktuellen Versionen, überwiegend Linux
CPU-Target: 64Bit 32 Bit
Kontaktdaten:

Array of byte in array of word umwandeln

Beitrag von KoBraSoft »

Hallo,
ich habe eine Funktion geschrieben (siehe unten) um Daten aus einer Steuerung mittels Modbus TCP zu lesen.
Insgesamt funktioniert die Funktion, außer dass die Bytes in den Words des Arrays "MyTaw" die falsche Reihenfolge haben.
Die Umwandlung geschieht mit der Deklaration "array of byte absolute MyTaw".
Leider treffen die Bytes nicht in der Reihenfolge ein wie sie im array of word abgelegt werden sollen. (Byteorder?)
Natürlich kann ich die Bytes einzeln in die Words schreiben, ungefähr so:

Code: Alles auswählen

For I := 0 to ...
MyTaw[I] := abAntwort[I*2+1] shl 8 + abAntwort[I*2]
Aber das finde es unelegant. Kennt jemand eine elegantere Lösung?

Code: Alles auswählen

type
  Taw = array of word;    

....

function ReadHoldingRegistersTCP(sIPAdresse, sPort: String; wStartAdr, wCount:word; var MyTaw:Taw): Boolean;
var
  con         : TTCPBlockSocket;
  abFrage     : array [0..11] of byte;
  abAntwort   : array of byte absolute MyTaw;
begin
  SetLength(abAntwort, wCount*2+10);
  abFrage[0] := 0;  // Transaction Identifier
  abFrage[1] := 1;  // Transaction Identifier
  abFrage[2] := 0;  // Protocoll Identifier: immer 00 00  Modbus-Protokoll
  abFrage[3] := 0;  // Protocoll Identifier: immer 00 00  Modbus-Protokoll
  abFrage[4] := 0;  // Length Hi
  abFrage[5] := 6;  // Length Low
  abFrage[6] := 1;  // Unit Identifier
  abFrage[7] := 3;  // Function code
  abFrage[8] := hi(wStartAdr);                           // Startaddresse Hi Byte
  abFrage[9] := lo(wStartAdr);                           // Startaddresse Low Byte
  abFrage[10] := hi(wCount);                              // Anzahl Daten Hi Byte
  abFrage[11] := lo(wCount);                              // Anzahl Daten Low Byte
  con:=TTCPBlockSocket.Create;

  try
    con.Connect(sIPAdresse,sPort);
    con.SendBuffer(@abFrage,12);
    Result := (con.RecvBufferEx(@abAntwort[0],Length(abAntwort),150) = wCount*2+9);
    abAntwort := copy(abAntwort,9,100);
    SetLength(MyTaw,wCount);
  finally
    con.free;
  end;
end;   
Konrad

www.KoBraSoft.de

Mathias
Beiträge: 6964
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Array of byte in array of word umwandeln

Beitrag von Mathias »

Was wird vertauscht, die ganze Array oder nur die beiden Bytes im Word ?
Wen es nur die einzelnen Byte im Word sind, gibt es Swap(),

https://www.freepascal.org/docs-html/rt ... /swap.html
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
KoBraSoft
Beiträge: 125
Registriert: So 6. Jun 2021, 09:57
OS, Lazarus, FPC: die zu Zeit aktuellen Versionen, überwiegend Linux
CPU-Target: 64Bit 32 Bit
Kontaktdaten:

Re: Array of byte in array of word umwandeln

Beitrag von KoBraSoft »

Die beiden Bytes im Word (im Array of word) sind vertauscht.
Swap geht nicht mit Arrays. Das

Code: Alles auswählen

For I := 0 to ...
swap(MyTaw[I])
funktioniert auch nicht. Keine Ahnung warum.
Konrad

www.KoBraSoft.de

Mathias
Beiträge: 6964
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Array of byte in array of word umwandeln

Beitrag von Mathias »

Dies ist eine function.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

icho2099
Beiträge: 48
Registriert: Fr 21. Feb 2020, 19:17
OS, Lazarus, FPC: Win10/64
CPU-Target: 64 Bit
Wohnort: Osterholz-Scharmbeck

Re: Array of byte in array of word umwandeln

Beitrag von icho2099 »

Swap() ist ja auch eine Function, keine Procedure.

Code: Alles auswählen

MyTaw[i] := Swap(MyTaw[i]);

MmVisual
Beiträge: 1581
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 4 FPC 3.2.2)
CPU-Target: 32/64Bit

Re: Array of byte in array of word umwandeln

Beitrag von MmVisual »

Ich würde das Tauschen in der Siemens Steuerung machen. Einerseits haben die bereits die optimierten Befehle drin, zum anderen muss man ohnehin das Senden-Array dort aufbauen und zum dritten ist Siemens so ziemlich die einzige Steuerung weltweit die bei der Kommunikation mit anderen Dingen ein SWAP braucht.

Man kann in Lazarus den Speicher (RAM) auf mehrere Variablen überlagern, so kann man z.B. relativ einfach Bytes empfangen und daraus dann ein Float Wert erzeugen:

Code: Alles auswählen

Var bArr: Array Of Byte[0..7];
wVArr: Array Of Word[0..3]     absolute bArr;
fVArr: Array Of Single[0..1]   absolute bArr;
Beim Empfang der einzelnen Bytes könnte man den Swap direkt durchführen:

Code: Alles auswählen

bArr[RxPos XOr 1] := NeuesByte;
RxPos += 1;
Damit hat man die Daten in bArr empfangen und kann die mit wVArr[xyr] direkt benutzen.

Das geht natürlich auch Umgekehrt beim Senden:

Code: Alles auswählen

TxByte := bArr[TxPos XOr 1];
TxPos += 1;
EleLa - Elektronik Lagerverwaltung - www.elela.de

Benutzeravatar
KoBraSoft
Beiträge: 125
Registriert: So 6. Jun 2021, 09:57
OS, Lazarus, FPC: die zu Zeit aktuellen Versionen, überwiegend Linux
CPU-Target: 64Bit 32 Bit
Kontaktdaten:

[Gelöst] Array of byte in array of word umwandeln

Beitrag von KoBraSoft »

MmVisual hat geschrieben: Sa 8. Jun 2024, 10:23 Ich würde das Tauschen in der Siemens Steuerung machen. Einerseits haben die bereits die optimierten Befehle drin, zum anderen muss man ohnehin das Senden-Array dort aufbauen und zum dritten ist Siemens so ziemlich die einzige Steuerung weltweit die bei der Kommunikation mit anderen Dingen ein SWAP braucht.
Ist keine Siemens Steuerung, es ist ein ESP32, die Bibliothek heißt modbus-esp8266. Die Bytes in der Steuerung tauschen ist eine gute Idee. Werde ich aber nicht machen, von zu viel C bekomme ich Kopfschmerzen :)

Man kann in Lazarus den Speicher (RAM) auf mehrere Variablen überlagern, so kann man z.B. relativ einfach Bytes empfangen und daraus dann ein Float Wert erzeugen:
Du meintest wahrscheinlich " und daraus dann ein Word Wert erzeugen". Mit Float wird das wahrscheinlich nicht funktionieren. (Ich bin mir aber nicht sicher.)
So was in der Art hatte ich ursprünglich vor. Werde jetzt aber die Bytes beim übertragen vom Array of byte in array of word tauschen.
Konrad

www.KoBraSoft.de

MmVisual
Beiträge: 1581
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 4 FPC 3.2.2)
CPU-Target: 32/64Bit

Re: Array of byte in array of word umwandeln

Beitrag von MmVisual »

Mit dem Schlüsselwort "absolute" kann man Variablen überlagern und mit einem anderen Typ auf den gleichen Speicher zugreifen.
Bei diesem Trick, den ich gezeigt hatte ist das Verständnis von "absolute" wichtig.
EleLa - Elektronik Lagerverwaltung - www.elela.de

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6855
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Array of byte in array of word umwandeln

Beitrag von af0815 »

In einer Simatik was swappen ist genauso lustig wie absolute Adressierung. Es wird mit den neuen Programmieroberflächen immer mehr versteckt und mit Strucured Text, bist du eh schon fast bei einer Mischung von Pascal und Java.

Und bei Modbus, nicht vorher an den Daten herummurksen, das macht Diagnosen mit Tools nur schwerer. Swappen im Pascalcode kostet im Aufwand nicht viel und wenn man sich die Funktionen richtig herrichtet ist das kein Problem.

Ich verwende Modbus und Simatik Protokoll laufend im Beruf und habe mir abgewöhnt auf der (virtuellen) SPS Seite herumzumurksen. Ist so eine Diskussion wie Punkt und Komma.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Antworten