Autor Beitrag
adina83
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 29



BeitragVerfasst: Do 28.07.11 19:27 
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:

ausblenden 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..65of TVarTab;



Wie kann ich diese Typdeklaration mit unterschiedlichen Variablentypen erstellen.
Besten Dank im voraus.


Moderiert von user profile iconNarses: Topic aus VCL (Visual Component Library) verschoben am Fr 29.07.2011 um 00:40
motion
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 295

XP, Linux
D7 Prof
BeitragVerfasst: Do 28.07.11 20:15 
Meinst Du variante Records?
Google mal nach "variant records" bzw. "records with variant parts".
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: 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.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
adina83 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 29



BeitragVerfasst: 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.

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Fr 29.07.11 13:23 
ausblenden volle Höhe 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
    //Result := ControllerMemory[...];
end;

function ReadByte(Offset: Integer): Byte;
var
    M: TMemorySegment;
begin
    M := GetSegmentByOffset(Offset);
    Offset := Offset - M.BaseAddr;
    If not M.Valid[Offset] Then
    Begin
        //Lesen vom Controller, Update im Memory Segment
    end;
    Restul := M.Data[Offset];
end;

function WriteByte(Offset: Integer; Value: Byte);
begin
    //Analog zum Lesen
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 + 1shl 8;
                If Result >= 32768 Then
                    Result := Result - 65536;
            end;
        int32be:
            begin
                Result := ReadByte(V.Offset) shl 24 + ReadByte(V.Offset + 1shl 16 + ReadByte(V.Offset + 2shl 8 + ReadByte(V.Offset + 3);
            end;
        int32le:
            begin
                Result := ReadByte(V.Offset) + ReadByte(V.Offset + 1shl 8 + ReadByte(V.Offset + 2shl 16 + ReadByte(V.Offset + 3shl 24;
            end;
        else
            Raise Exception.Create('Not Implemented!');
    end;
end;

Function GetUnsignedVar(V: TVariable): Integer;
begin
  //Analog zur Signed-Methode    
end;

//...


Nutzung dann im StringGrid zur Anzeige des Wertes:

ausblenden 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(1shl 32 - 1));

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
adina83 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 29



BeitragVerfasst: Fr 29.07.11 15:36 
Danke genau so etwas meinte ich.
Schönes WE.