Quantcast
Channel: SPS-Forum - Automatisierung und Elektrotechnik
Viewing all articles
Browse latest Browse all 49737

Step 7 Optimierung Schleife mit Pointern, indirekter, bereichsübergreifender Zugriff

$
0
0
Hallo Forum,


("long time lurker, first time poster" - wie man so sagt)


ich habe es hier mit einer 315-2 PN/DP zu tun, bei der mein FB zum Datenschubsen mehrere ms Zykluszeit kostet (zwischen 1ms und 5ms, abhängig davon, wieviele Daten geschoben werden). Es gilt die Werte an den Adressen in einer Liste (wild gemischt: E, A, M, DB; SFC20/BLKMOV bringt hier nix) möglichst effizient (= schnell) in einen zusammenhängenden Bereich zu transferieren.


Mein aktueller Ansatz sieht so aus (kostet ca. 5ms für 1000 bytes):

(Vorbereitung auf die Schleife)

Code:

          AddressPointers  :  ARRAY [0..5999] OF BYTE; // 1000x: DWORD for pointer, WORD for DBnr
          xAddressPointer  : DWORD;
          ...
          // fülle AddressPointers mit 1000 Adressen im Format L W#16#81000000; L 10; SLD 3; L W#16#82000000; L 42; SLD 3; ...
          ...


          LAR1    P##AddressPointers;
          // Zeiger auf Anfang des Bereichs, an dem die gewünschten Adressen als DWORD (pointer) + WORD (DBnr) stehen
          TAR1    xAddressPointer;           


          LAR1    P##OutputData;
          TAR1    xOutputPointer;            // Zeiger auf Anfang des Zieldatenbereichs
          L      DNIO;
          T      xDINOStore;        // rette DI Nummer

(die Schleife)
Code:

          L        1000; // z.B. 1k Durchläufe (1000 Bytes)
schl:    T        xLoopCounter;
          L        W [AR1,P#4.0];          // DB Nummer ist WORD
          T        xDBNOStore;
          AUF      DB [xDBNOStore];
          L        D [AR1,P#0.0];                // Lade Zeiger im DWORD Format
          AUF      DI [xDINOStore];              // DI Nummer wieder herstellen
          LAR1;                                // DWORD Zeiger zu Adresse konvertieren
          L        B [AR1,P#0.0];              // Wert an der Adresse im ARR1 in AKKU1 laden
          LAR1    xOutputPointer;              //  Ausgabeadresse in ARR1 laden
          T        B [AR1,P#0.0];              // aktuellen Wert in AKKU1 in ARR1
          +AR1    P#1.0;                        // Ausgabeadresse in ARR1 um Länge von einem Byte weiter
          TAR1    xOutputPointer;              // Ausgabeadresse retten
          LAR1    xAddressPointer;            // aktuelle Startadresse der Zeigerdefinitionen laden
          +AR1    P#6.0;                          // aktuelle Startadresse der Zeigerdefinitionen laden um DWORD + WORD weiter schieben
          TAR1    xAddressPointer;            // aktuelle Startadresse der Zeigerdefinitionen retten
          L        xLoopCounter;
          LOOP    schl;




Da würde ich jetzt gerne so viele wie möglich Anweisungen einsparen - weiss aber nicht so recht, wie ich das gut und sicher tun kann. Ein Idee wäre "ARR2" auch zu verwenden, dann könnte ich im ARR1 nur die Zeiger zu den Eingangsdaten, und den Zeiger auf den Zieldatenbereich mit +AR2 schieben. Dass würde mir dann einige der LAR1 und TAR1 Anweisungen sparen. Allerdings weiss ich nicht, ob das wirklich sicher ist zu tun; in der Hilfe und im AWL Editor wird ja immer gewarnt, dass "+AR2" schlimme Nebeneffekte haben kann, und z.B. Anweisungen wie "L P#DB123.DBB 5" ggf. wiederum den AR2 verändern.




Was auch noch klasse wäre, wenn man sowas machen könnte; dass würde mir dann die Anweisungen ersparen, in ARR1 laden, retten, und wieder laden


Code:



L      W#16#83000000; // Maske für %M
L      100; // soll man %M 100.0 werden
SLD  3;
OD;
T      xZeiger;
L      MB [#xZeiger]; // Geht
L      B [#xZeiger];  // Geht NICHT; warum??? W#16#83 (die Info, dass es ein Merker ist) steht doch auch in xZeiger




Ich würde mich sehr über Eure Ideen und Anregungen (oder Lösungen :P) freuen!!


VG, Jürgen

Viewing all articles
Browse latest Browse all 49737