Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Problem mit Variablentabelle
adina83 - Do 28.07.11 19:27
Titel: Problem mit Variablentabelle
Hallo ich soll die Daten eines Controllers auslesen und habe dafür eine Tabelle mit
Nr. ,Adresse, Variablenname, Beschreibung, und Variablentyp.
Der Variablentyp variert wiederum zwischen unsigned int 8, signed / unsigned int 16, unsigned int 32 Variablen.
Wie kann ich diese Tabelle in Delphi mittels type / struct ansprechen.
Wäre der Variablentyp (zb. word) konstant so würde ich ein type anlegen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| type TVarTab = record nr : word; adr : word; name : string; descr : string; val : word; end;
VarTab : array [0..65] of TVarTab; |
Wie kann ich diese Typdeklaration mit unterschiedlichen Variablentypen erstellen.
Besten Dank im voraus.
Moderiert von
Narses: Topic aus VCL (Visual Component Library) verschoben am Fr 29.07.2011 um 00:40
motion - Do 28.07.11 20:15
Meinst Du variante Records?
Google mal nach "variant records" bzw. "records with variant parts".
jaenicke - Do 28.07.11 20:40
Da ist dann die Größe des Records allerdings so groß wie die größte Variante.
Mir ist aber noch nicht klar wo eigentlich das Problem ist, wie die Daten ausgelesen werden sollen und was genau bei dem Record das Problem mit den Integerwerten ist. :gruebel:
Wenn aus einem Speicher der Record als ganzes ausgelesen werden soll, würde ich eher eine sinnvollere Lösung wählen und das Auslesen manuell machen. Dann sind unterschiedliche Typen auch kein Problem, wenn man weiß wann welche benutzt werden.
Oder meinst du das so, dass du diese Tabelle hast und an diesen Speicherstellen Daten auslesen willst? Dann verstehe ich auch nicht wo das Problem mit unterschiedlichen Typen ist.
BenBE - Do 28.07.11 21:47
Ich vermute mal (auf Grund fehlender Details), dass für die Software, die auf dem Controller läuft ein Mapfile bekannt ist, wo welche Variable im Speicher liegt. Anhand dieser Mapfile soll nun der Zustand des Kontrollers ausgelesen werden und der Inhalt der Variablen angezeigt werden.
Typisches Vorgehen: Man liest das Speicherabbild des Controllers soweit nötig vollständig aus (wenn man 20 Variablen hat, die beieinander liegen, aber paar Lücken aufweisen), liest man den Speicher vom Anfang der ersten Variable bis zum Ende der letzten inklusive der Lücken aus. Dieses Array of Byte betrachtete man nun unabhängig von der Variablen-Tabelle: Die Variablentabelle enthält nur Offset, Nr, Name, Desc UND den Datentyp.
Basierend auf Offset und Datentyp kann man sich dann eine Methode schreiben, die unter Angabe eines Speicherabbildes den Variablen-Wert ausliest oder setzt.
Kommt es auf Performance NICHT an, kann man für die Zugriffsmethoden Variants benutzen; benötigt man performance, schreibt man für den größten Datentyp (hier wahrscheinlich (un)signed Integer mit 32 Bit) eine Zugriffsmethode und nimmt für andere Datentypen eine entsprechende Konvertierung in der Zugriffsmethode vor.
adina83 - Fr 29.07.11 12:20
Danke für die Hinweise, war gestern leider nicht mehr online.
Die Adressen der Variablen werden mir auf Anfrage vom Controller mitgeteilt. Diese lese ich als erstes aus. Wieviel bytes ich ab einer Adresse auslesen muss sagt mir der Controller aber nicht. Das geht aus einem Protokoll hervor was mir vorliegt. Es kann durchaus möglich sein das die Adressen
weit auseinander liegen und somit macht es keinen Sinn die Lücken dazwischen zu Lesen (Performance-Gründe). Bsp.
Ich hab drei Variablen mit je drei Adressen aber unterschiedlichem Variablentyp (u16, s16, u32,). Somit müsste ich von Adresse 1 u 2 den 16Bit-Wert lesen und entspr interpretieren und von Adresse 3 den 16Bit-Wert und den nachfolgenden 16Bit-Wert und mir daraus einen 32Bit-Wert zusammenschieben.
Um die Variablen dann in einem Stringrid darzustellen wäre es vorteilhaft. Eine Struktur zu haben um über eine Schleife alle Werte mit Namen Bezeichnung und Adresse in dieses Stringgrid eintragen zu können. Wenn alle Variablen aus 16-Bit-Werten bestehen würden dann würde ich das wie folgt schreiben.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| with StringGrid_Eepdata do begin RowCount:=8+3; for i:=0 to 8 do begin Cells[0,i+1]:=inttostr(VarTab[i].nr); Cells[1,i+1]:=VarTab[i].name; Cells[2,i+1]:=inttostr(VarTab[i].adr); Cells[2,i+1]:=inttostr(VarTab[i].val); Cells[4,i+1]:=VarTab[i]einheit; end; end; |
Problem ist das es sich dabei um ungefähr 300 Variablen dreht die gelesen und geschrieben werden sollen und ich nicht jede Variable einzeln behandeln möchte.
Ich hoffe das Problem ist jetzt genauer dargestellt und nun heissts "Mittag".
BenBE - Fr 29.07.11 13:23
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97:
| type TVarType = (uint8, uint16be, uint16le, uint32be, uint32le, int8, int16be, int16le, int32be, int32le); TVariable = record Index: Integer; Offset: Integer; Name: String; Description: String; VarType: TVarType; end; TMemorySegment = record BaseAddr: Integer; SegmentSize: Integer; Data: Array of Byte; Valid: array of Boolean; end;
var ControllerMemory: array of TMemorySegment;
function IsSigned(VT: TVarType): Boolean; begin Result := VT in [int8, int16be, int16le, int32be, int32le]; end;
function GetSegmentByOffset(Addr): TMemorySegment; begin end;
function ReadByte(Offset: Integer): Byte; var M: TMemorySegment; begin M := GetSegmentByOffset(Offset); Offset := Offset - M.BaseAddr; If not M.Valid[Offset] Then Begin end; Restul := M.Data[Offset]; end;
function WriteByte(Offset: Integer; Value: Byte); begin end;
Function GetSignedVar(V: TVariable): Integer; begin Case V.VarType of uint8: Raise Exception.Create('Conflict in Signed/Unsigned'); uint16be: Raise Exception.Create('Conflict in Signed/Unsigned'); uint16le: Raise Exception.Create('Conflict in Signed/Unsigned'); uint32be: Raise Exception.Create('Conflict in Signed/Unsigned'); uint32le: Raise Exception.Create('Conflict in Signed/Unsigned'); int8: begin Result := ReadByte(V.Offset); If Result >= 128 Then Result := Result - 256; end; int16be: begin Result := ReadByte(V.Offset) shl 8 + ReadByte(V.Offset + 1); If Result >= 32768 Then Result := Result - 65536; end; int16le: begin Result := ReadByte(V.Offset) + ReadByte(V.Offset + 1) shl 8; If Result >= 32768 Then Result := Result - 65536; end; int32be: begin Result := ReadByte(V.Offset) shl 24 + ReadByte(V.Offset + 1) shl 16 + ReadByte(V.Offset + 2) shl 8 + ReadByte(V.Offset + 3); end; int32le: begin Result := ReadByte(V.Offset) + ReadByte(V.Offset + 1) shl 8 + ReadByte(V.Offset + 2) shl 16 + ReadByte(V.Offset + 3) shl 24; end; else Raise Exception.Create('Not Implemented!'); end; end;
Function GetUnsignedVar(V: TVariable): Integer; begin end;
|
Nutzung dann im StringGrid zur Anzeige des Wertes:
Delphi-Quelltext
1: 2: 3: 4:
| If IsSigned(V.VarType) Then SG.Cells[i, 3] := IntToStr(GetSignedValue(V)) else SG.Cells[i, 3] := Int64ToStr(GetUnsignedValue(V) and (Int64(1) shl 32 - 1)); |
adina83 - Fr 29.07.11 15:36
Danke genau so etwas meinte ich.
Schönes WE.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!