Step 7 Bitadresse in einem DB mit Ganzzahl berechnen

Zuviel Werbung?
-> Hier kostenlos registrieren
Ich vermute, die Daten werden zyklisch übertragen, z.B. die SPS stellt die Daten/Werte abholbereit zur Verfügung und der Leitrechner pollt zyklisch sämtliche Kommunikationsvariablen, und für die Information welche Fehler gerade anstehen ist nur großzügig Platz/Adressen für 10 Werte vereinbart ("kommt fast nie vor"). Platz für mehr Werte kostet Speicher und Performance.

Länger anstehende Meldungen werden bis sie quittiert werden dem Leitrechner gemeldet.
10 Meldungen sind programmtechnisch ausreichend... ;)
... oder bis >= 10 höherpriore Meldungen anstehen, weil dann für die Meldung kein Platz mehr im Protokoll ist.

Harald
 
Hallo zusammen

Ich sag nochmal Danke für die schnellen Antworten.
Ich hab die Variante von PN/DP gewählt. Funktioniert so wie ich es brauche.

Bei der Variante von TP-Ink funktioniert bei mir was nicht mit dem zusammenstellen des Pointes obwohl die Ergebnissen Byte und Bit-Adresse passen.

L #Byteadresse
SLD 3
L #Bitadresse
UD // Pointer basteln
LAR1 // ins AR1

AUF #FehlerDB
S DBX [AR1, P#0.0]

Ja klar, /I muss /D heißen, hab ich bemerkt :-)

Also, vielen Dank
 
Nun wieder zu bmwled seine Fehlernummern (hier ist mittlerweile ein Durcheinander, daß sich sogar der originale Fragesteller Fritz4 bei den falschen Beiträgen bedankt)
Der Leitrechner hält ein ARRAY[1..10] "INT" dafür bereit.
Korrekt, die 10 niederwertigsten Fehler sollen dann gemeldet werden.
Das kannst Du ungefähr so machen (nicht getestet, und keine Ahnung wieviele ms die Schleife mit 1200 Durchläufen dauert):
Code:
FUNCTION FCxxx : VOID
VAR_INPUT
  ErrMsgBytes : ARRAY[1..150] OF BYTE;
  ErrBitFeld AT ErrMsgBytes : ARRAY[1..1200] OF BOOL;
END_VAR
VAR_OUTPUT
  ErrActive : ARRAY[1..10] OF INT;  [COLOR="#008000"]//Ergebnis-Array mit max 10 Nummern aktiver Fehler[/COLOR]
END_VAR
VAR_TEMP
  tmpErrActive : ARRAY[1..10] OF INT;
  i : INT;
  n : INT;
END_VAR

  [COLOR="#008000"]//gesetztes Fehlerbit suchen und dessen Nummer in Fehlernummern-Array eintragen[/COLOR]
  [COLOR="#008000"]//Fehlerbit 1..1200 entspricht Fehlernummer 1..1200[/COLOR]
  n := 1;  [COLOR="#008000"]//Index in Fehlernummern-Array (1..10)[/COLOR]
  FOR i := 1 TO 1200 DO  [COLOR="#008000"]//Index in FehlerBitfeld (1..1200)[/COLOR]
    IF ErrBitFeld[i] THEN    [COLOR="#008000"]//FehlerBit gesetzt?[/COLOR]
      tmpErrActive[n] := i;  [COLOR="#008000"]//Fehlernummer in Fehlernummern-Array eintragen[/COLOR]
      n := n + 1;            [COLOR="#008000"]//Index auf nächsten Fehlernummern-Eintrag[/COLOR]
      IF n > 10 THEN
        EXIT;  [COLOR="#008000"]//FOR-Schleife verlassen weil bereits 10 1-Bits gefunden[/COLOR]
      END_IF;
    END_IF;
  END_FOR;

  [COLOR="#008000"]//restliche Fehlernummern löschen[/COLOR]
  [COLOR="#008000"]//(oder vor der FOR-Schleife alle 10 Nummern löschen)[/COLOR]
  WHILE n <= 10 DO
    tmpErrActive[n] := 0;
    n := n + 1;
  END_WHILE;

  [COLOR="#008000"]//Array mit den Fehlernummern (an Leitrechner) zurückgeben[/COLOR]
  ErrActive := tmpErrActive;

END_FUNCTION
In AWL kann man das zwar noch effizienter programmieren (weil der SCL-classic-Compiler ziemlich furchtbar kompiliert), der SCL-Code ist aber wesentlich besser verstehbar.

Harald
 
... hier ist mittlerweile ein Durcheinander, daß sich sogar der originale Fragesteller Fritz4 bei den falschen Beiträgen bedankt ...
Das sehe ich ganz locker. Das muss nämlich nicht bedeuten, dass wir Fritz4 durch die Beiträge völlig orientierungslos gemacht haben - es bedeutet wahrscheinlich, dass die "falschen" Beiträge sooo falsch gar nicht gewesen sein können. Den "Trittbrettfahrer" bmwled habe ich überhaupt nicht als störend empfunden. Der Thread ist beim Thema geblieben.
Funktion und UmkehrFunktion passen doch bestens zu einander, finde ich.
Wie oft hat man in diesem Forum schon erlebt, dass das vermeintliche ursprüngliche Thema durch viele Rückfragen so nach und nach zu einem ganz anderen Thema präzisiert wurde.
Das war hier nicht der Fall.
Gruss, Heinileini
 
Hallo,

danke für deine Bemühungen Harald, aber der Kunde erlaubt kein SCL.
Ich habe einen FC in AWL erstellt. Den Inhalt habe ich aus einem anderen Projekt.
Es funktioniert soweit auch aber nur mit der ersten Meldung.
Diese landet im DB173.DBW20. Dort habe ich ein ARRAY[1..10] erstellt.
Jetzt fehlt mir noch der Wiedereinsprung um die restlichen Meldungen auszulesen.
In DBW12 habe ich ein Hilfsdatenwort angelegt für den Zähler 1-10 Meldungen.
 
Zuletzt bearbeitet:
der Kunde erlaubt kein SCL
Unverständliches AWL ist aber erlaubt? ;)

Du könntest den SCL-Quelltext übersetzen und dann den erzeugten Baustein (FC) öffnen (im FUP/KOP/AWL-Editor: Datei > Öffnen), den AWL-Code in einen anderen FC kopieren und etwas aufhübschen (besonders die vielen unsinnigen TAK und unnötigen ITD eliminieren).
Oder versuchen, den SCL-Quelltext soweit möglich 1:1 in AWL nachprogrammieren.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Unverständliches AWL ist aber erlaubt? :wink:

Das sind die Regeln.

Die erste Meldung wird nun ausgelesen. Jetzt hänge ich am ablegen im Speicher.

Code:
   T     DB173.DBW    16       // Da steht der aktuelle Fehlercode   

   L     DB173.DBW    12       // Platz für Fehlercode im Speicher
      SLW   3
      LAR2  
      AUF   DB   173
      T     DBW [AR2,P#0.0]

In den DBW12 lade ich 20 (dort ist der Platz für den ersten Speicher, dann 22,24,usw.) rein.
Aber es steht nicht die Zahl drin, welche im Speicher steht.

Ist denn der grundlegende Aufbau vom Pointer so in Ordnung?
 
Zuletzt bearbeitet:
Als Vorlage der SCL-Quelltext für einen FC von #24
Code:
[COLOR="#0000FF"]  [COLOR="#006400"]//gesetztes Fehlerbit suchen und dessen Nummer in Fehlernummern-Array eintragen[/COLOR]
  n := 1;  [COLOR="#006400"]//Index in Fehlernummern-Array (1..10)[/COLOR]
  FOR i := 1 TO 1200 DO  [COLOR="#006400"]//Index in FehlerBitfeld (1..1200)[/COLOR]
    IF ErrBitFeld[i] THEN    [COLOR="#006400"]//FehlerBit gesetzt?[/COLOR]
      tmpErrActive[n] := i;  [COLOR="#006400"]//Fehlernummer in Fehlernummern-Array eintragen[/COLOR]
      n := n + 1;            [COLOR="#006400"]//Index auf nächsten Fehlernummern-Eintrag[/COLOR]
      IF n > 10 THEN
        EXIT;  [COLOR="#006400"]//FOR-Schleife verlassen weil bereits 10 1-Bits gefunden[/COLOR]
      END_IF;
    END_IF;
  END_FOR;

  [COLOR="#006400"]//restliche Fehlernummern löschen[/COLOR]
  WHILE n <= 10 DO
    tmpErrActive[n] := 0;
    n := n + 1;
  END_WHILE;

  [COLOR="#006400"]//Array mit den Fehlernummern (an Leitrechner) zurückgeben[/COLOR]
  ErrActive := tmpErrActive;[/COLOR]
in AWL übersetzt und von Hand optimiert und kommentiert:
Code:
[COLOR="#008000"]//für bessere Performance als SCL die Adresse des Aktualparameters IN:ErrMsgBytes
//schon vor der FOR-Schleife holen:[/COLOR]
      L     P##ErrMsgBytes              [COLOR="#008000"]//IN: ErrMsgBytes : ARRAY[1..150] OF BYTE;[/COLOR]
[COLOR="#008000"]//                                      //IN: ErrBitFeld AT ErrMsgBytes : ARRAY[1..1200] OF BOOL;[/COLOR]
      LAR1                              [COLOR="#008000"]//wird als POINTER an den FC übergeben[/COLOR]
      L     W [AR1,P#0.0]               [COLOR="#008000"]//POINTER: DB-Nr[/COLOR]
      T     #IN_ErrBitFeld_DB           [COLOR="#008000"]//(TEMP: Word)[/COLOR]
      L     D [AR1,P#2.0]               [COLOR="#008000"]//POINTER: Bereichsadresse[/COLOR]
      T     #IN_ErrBitFeld_Adr          [COLOR="#008000"]//(TEMP: DWord)[/COLOR]

[COLOR="#006400"]//gesetztes Fehlerbit suchen und dessen Nummer in Fehlernummern-Array eintragen
//[/COLOR]  [COLOR="#0000FF"]n := 1;[/COLOR]  [COLOR="#006400"]//Index in Fehlernummern-Array (1..10)
//[/COLOR]  [COLOR="#0000FF"]FOR i := 1 TO 1200 DO[/COLOR]  [COLOR="#006400"]//Index in FehlerBitfeld (1..1200)[/COLOR]
      L     1
      T     #n                          [COLOR="#008000"]//(TEMP: Int)[/COLOR]
      T     #i                          [COLOR="#008000"]//(TEMP: Int)[/COLOR]

[COLOR="#008000"]// FOR i .. TO 1200 DO[/COLOR] 
MFOR: L     #i
      L     1200
      <=I
      SPBN  MWHI

[COLOR="#008000"]//Adresse IN:ErrBitFeld[i] berechnen[/COLOR]
      L     #i
      +     -1                          [COLOR="#008000"]//weil IN:ErrBitFeld[] mit Index 1 beginnt[/COLOR]
      L     #IN_ErrBitFeld_Adr          [COLOR="#008000"]//Adresse des Aktualparameters IN:ErrBitFeld[] [/COLOR]
      +D
      LAR1                              [COLOR="#008000"]//Adresse IN:ErrBitFeld[i][/COLOR]

[COLOR="#006400"]//    [COLOR="#0000FF"]IF ErrBitFeld[i] THEN[/COLOR]    //FehlerBit gesetzt?[/COLOR]
      AUF   DB [#IN_ErrBitFeld_DB]
      U      [AR1,P#0.0]
      SPBN  EFOR                        [COLOR="#008000"]//zu END_IF; END_FOR;[/COLOR]

[COLOR="#006400"]//      [COLOR="#0000FF"]tmpErrActive[n] := i;[/COLOR]  //Fehlernummer in Fehlernummern-Array eintragen[/COLOR]
      L     #n
      +     -1                          [COLOR="#008000"]//weil tmpErrActive[] mit Index 1 beginnt[/COLOR]
      SLD   4                           [COLOR="#008000"]//tmpErrActive ist ein INT-Array[/COLOR]
      L     P##tmpErrActive             [COLOR="#008000"]//Anfangsadresse tmpErrActive[][/COLOR]
      +D
      LAR1                              [COLOR="#008000"]//Adresse tmpErrActive[n][/COLOR]

      L     #i
      T     LW [AR1,P#0.0]              [COLOR="#008000"]//tmpErrActive[n] := i;[/COLOR]

[COLOR="#006400"]//      [COLOR="#0000FF"]n := n + 1;[/COLOR]            //Index auf nächsten Fehlernummern-Eintrag
//      [COLOR="#0000FF"]IF n > 10 THEN[/COLOR]
//        [COLOR="#0000FF"]EXIT;[/COLOR]  //FOR-Schleife verlassen weil bereits 10 1-Bits gefunden
//      [COLOR="#0000FF"]END_IF;[/COLOR][/COLOR]
      L     #n
      +     1
      T     #n
      L     10
      >I
      SPB   MWHI                        [COLOR="#008000"]//EXIT FOR[/COLOR]

[COLOR="#006400"]//      [COLOR="#0000FF"]END_IF;[/COLOR]
//    [COLOR="#0000FF"]END_IF;[/COLOR]
//  [COLOR="#0000FF"]END_FOR;[/COLOR] ---> i++[/COLOR]
EFOR: L     #i
      +     1
      T     #i
      SPA   MFOR                        [COLOR="#008000"]//zurück zu FOR ...[/COLOR]

[COLOR="#006400"]//restliche Fehlernummern löschen
//  [COLOR="#0000FF"]WHILE n <= 10 DO[/COLOR][/COLOR]
MWHI: L     #n
      L     10
      <=I
      SPBN  MRET                        [COLOR="#008000"]//zu END_WHILE;

//[/COLOR]    [COLOR="#0000FF"]tmpErrActive[n] := 0;[/COLOR]
      L     #n
      +     -1                          [COLOR="#008000"]//weil tmpErrActive[] mit Index 1 beginnt[/COLOR]
      SLD   4                           [COLOR="#008000"]//tmpErrActive ist ein INT-Array[/COLOR]
      L     P##tmpErrActive             [COLOR="#008000"]//Anfangsadresse tmpErrActive[][/COLOR]
      +D
      LAR1                              [COLOR="#008000"]//Adresse tmpErrActive[n][/COLOR]

      L     0
      T     LW [AR1,P#0.0]              [COLOR="#008000"]//tmpErrActive[n] := 0;[/COLOR]

//    [COLOR="#0000FF"]n := n + 1;[/COLOR]
      L     #n
      +     1
      T     #n
      SPA   MWHI                        [COLOR="#008000"]//zurück zu WHILE ...
//[/COLOR]  [COLOR="#0000FF"]END_WHILE;[/COLOR]

[COLOR="#006400"]//Array mit den Fehlernummern (an Leitrechner) zurückgeben
//  [COLOR="#0000FF"]ErrActive := tmpErrActive;[/COLOR][/COLOR]
MRET: L     P##ErrActive                [COLOR="#008000"]//OUT: ErrActive : ARRAY[1..10] OF INT;[/COLOR]
      LAR1                              [COLOR="#008000"]//wird als POINTER an den FC übergeben[/COLOR]
      L     W [AR1,P#0.0]               [COLOR="#008000"]//POINTER: DB-Nr[/COLOR]
      T     #OUT_ErrActive_DB           [COLOR="#008000"]//(TEMP: Word)[/COLOR]
      AUF   DB [#OUT_ErrActive_DB]
      L     D [AR1,P#2.0]               [COLOR="#008000"]//POINTER: Bereichsadresse (OUT_ErrActive_Adr)[/COLOR]
      LAR1

[COLOR="#008000"]//kopieren mit SFC20 BLKMOV ist nicht möglich! 
//deshalb mit AR2 kopieren: " *LAR1 <-- *LAR2 "[/COLOR]
      LAR2  P##tmpErrActive             [COLOR="#008000"]//tmpErrActive : ARRAY[1..10] OF INT[/COLOR]

      L     LD [AR2,P#0.0]              [COLOR="#008000"]//von tmpErrActive ...[/COLOR]
      T     D [AR1,P#0.0]               [COLOR="#008000"]//nach ErrActive ...[/COLOR]

      L     LD [AR2,P#4.0]
      T     D [AR1,P#4.0]

      L     LD [AR2,P#8.0]
      T     D [AR1,P#8.0]

      L     LD [AR2,P#12.0]
      T     D [AR1,P#12.0]

      L     LD [AR2,P#16.0]
      T     D [AR1,P#16.0]
Durch die manuelle Optimierung des SCL-V5.3.6-Kompilates ist der AWL-Code vermutlich ca. 50% schneller als der vom SCL-Compiler erzeugte Code und mit Kommentaren noch relativ gut verstehbar.

Die Schnittstelle des obigen FC:
Code:
VAR_INPUT
  ErrMsgBytes : ARRAY[1..150] OF BYTE;
END_VAR
VAR_OUTPUT
  ErrActive : ARRAY[1..10] OF INT;  [COLOR="#008000"]//Ergebnis-Array mit max 10 Nummern aktiver Fehler[/COLOR]
END_VAR
VAR_TEMP
  tmpErrActive : ARRAY[1..10] OF INT;
  i : INT;
  n : INT;
  IN_ErrBitFeld_DB : WORD;
  IN_ErrBitFeld_Adr : DWORD;
  OUT_ErrActive_DB : WORD;
END_VAR

Harald
 
In den DBW12 lade ich 20 (dort ist der Platz für den ersten Speicher, dann 22,24,usw.) rein.
Aber es steht nicht die Zahl drin, welche im Speicher steht.

Ist denn der grundlegende Aufbau vom Pointer so in Ordnung?
Solche unsymbolische absolute Adressierung ist nicht schön, aber (noch) möglich.
Wenn schon dann mache das besser so:
Code:
   T     DB173.DBW    16       // Da steht der aktuelle Fehlercode

   L     DB173.DBW    12       // Platz für Fehlercode im Speicher: 20, 22, 24 ...
   SLD   3                     // --> P#20.0, P#22.0, P#24.0 ...
   LAR2
   L     DB173.DBW    16       // aktueller Fehlercode
   T     DBW [AR2,P#0.0]
oder
Code:
   T     DB173.DBW    16       // Da steht der aktuelle Fehlercode

   L     DB173.DBW    12       // Index für Fehlercode im Array: 1, 2, 3, 4 ... 10
   +     -1                    // Array beginnt mit Index 1
   SLD   4                     // --> P#0.0, P#2.0, P#4.0 ... P#18.0
   L     P#20.0                // (P#DBX20.0 geht auch) das ARRAY[1..10] beginnt bei DB173.DBW20
   +D                          // --> Adresse ARRAY[Index] : P#20.0, P#22.0, P#24.0 ...
   LAR2
   L     DB173.DBW    16       // aktueller Fehlercode
   T     DBW [AR2,P#0.0]

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Harald,

hab das ganze jetzt mal von dir eingespielt und getestet.
Funktioniert einwandfrei und das gleich mit dem ersten Schuss. :s12:

Die Zykluszeit steigt bei 1200 Einträgen von 18 auf 21ms.
Hab den Bereiche noch auf 800 Einträge gekürzt und jetzt sind es noch 20ms. Perfekt!
 
Zurück
Oben