TIA Erkennenen ob in Bool-Struct min. eine Variable = true

Hier mal eine AWL Quelle für ein classic 3000er / 400er CPU in TIA.
Bitsum für beliebig grosse DB.

Die Zahl der gesetzte Bits kannst du im Programm benutzen.
Vergleich auf > Null.

Code:
FUNCTION_BLOCK "Bitsumme"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
   VAR_INPUT
      DBNR : Int;
   END_VAR

   VAR_OUTPUT
      Anzahl_Bits : DInt;
   END_VAR

   VAR_TEMP
      DBNR_t : Int;
      Pointer_daten_bit_t : DWord;
      SchleifenZaehler_T : DInt;
      Bitzaehler_t : DInt;
   END_VAR


BEGIN
NETWORK
TITLE =
      L #DBNR                     ;//Indirektes Öffenen des Datenbausteines über In Parameter
      T #DBNR_t;
      AUF DB[ #DBNR_t];
//******************************************************************************** ***********
      LAR1 P#0.0                     ;//Initialisierung des Datenbitpointers
//******************************************************************************** ***********
      L DINT#0                       ;//Initialisierung des Bitzaehlers
      T #Bitzaehler_t;
//******************************************************************************** ***********
      L DBLG                      ;//auslesen der Datenbausteinlänge in Byte
      L DINT#8                       ;//multiplikationfaktor Byte nach Bit
      *D;
next:      T #SchleifenZaehler_T       ;//Vorspannen des Schleifenzaehlers in DINT,da die Schleife grösser als 32767 sein Könnte
      CLR                             ;//Erzwingen VKE=0
      U DBX[ AR1, P#0.0];
      SPBN m001                      ;//wenn Bit=0 Springe
      L DINT#1                       ;//Zaehlen wenn ein Bit=1
      L #Bitzaehler_t;
      +D;
      T #Bitzaehler_t;
m001:      +AR1 P#0.1                     ;//Pointererhöhung für nächsten Schleifendurchlau
      L #SchleifenZaehler_T       ;//dekrementierung SchleifenZaehler_T um 1
      L DINT#1;
      -D;
      L DINT#1;
      >=D;
      SPB nex2                      ;// Rücksprung in Schleife wenn noch nicht alle Bits des DB auf 1 Geprüft
      SPA m002;
nex2:      TAK;
      SPA next;
m002:      NOP 0;
//******************************************************************************** ***********
      L #Bitzaehler_t             ;// Übergabe der Temporär gezaehlten 1=Bit an Output
      T #Anzahl_Bits;


END_FUNCTION_BLOCK
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das gleiche in eine SCL variant für die 1500er

Code:
FUNCTION_BLOCK "BITSUM"
TITLE = BITSUM
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : 'v.Berkel'
FAMILY : Algemein
VERSION : 16.0
//BITSUM from any DB
   VAR_INPUT
      DB_IN { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : DB_ANY;   // Any DB
   END_VAR

   VAR_OUTPUT
      "Bits SET > 0" { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // More then 0 Bits SET
      "Number_of_Bits SET" { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;   // Number of SET Bits
   END_VAR

   VAR
      Attribute_DB { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Byte;   // Attribute of DB
      DB_Length { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : UDInt;   // Length of DB
      Retval { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;   // Return value
      Countvalue { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;   // Countvalue
      Countvalue_start { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;   // Countvalue_start
      Countvalue_end { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;   // Countvalue_end
   END_VAR


BEGIN
    #Retval := ATTR_DB(REQ := true, DB_NUMBER := #DB_IN, DB_LENGTH => #DB_Length, ATTRIB => #Attribute_DB);
    
    #"Number_of_Bits SET" := 0;
    #Countvalue_start     := 0;
    #Countvalue_end       := (UDINT_TO_INT(#DB_Length) - 1);
    
    FOR #Countvalue := #Countvalue_start TO #Countvalue_end DO
        #"Number_of_Bits SET" := #"Number_of_Bits SET" + BITSUM(BYTE_TO_DWORD(PEEK(area := 16#84, dbNumber := #DB_IN, byteOffset := #Countvalue)));
    END_FOR;
    
    #"Bits SET > 0" := #"Number_of_Bits SET" > 0;
END_FUNCTION_BLOCK
 
Ich habe allerdings das Problem, dass er den Zugriff auf das Doppelwort nicht zulassen möchte?

Anhang anzeigen 59544
Die Syntax "...DBD0" ist falsch. Vielleicht klärst Du uns mal auf welche SPS Du verwendest oder schaust selber in der TIA-Hilfe nach der richtigen Syntax für den direkten Zugriff auf DB-Doppelworte. In S7-300/400 musst (oder musstest) Du schreiben "...DD0" und in S7-1200/1500 (oder generell in TIA?) musst Du PEEK() verwenden.

PS: Ich habe es nicht ausprobiert, nur schnell in der TIA-Hilfe V15.1 nachgesehen, Thema: Variablen in globalen Datenbausteinen adressieren
Anscheinend ist "DBD0" zulässig, allerdings muß dann wohl auch der DB-Name absolut angegeben werden, z.B. %DB1.DBD0
Gemischt DB-Name symbolisch und Adresse absolut geht wohl nicht.

Harald
 
Zuletzt bearbeitet:
Ok, in Step7 Classic schluckt der Compiler beides ( das DD war mir tatsächlich unbekannt )
Offiziell dokumentiert ist meines Wissens nur die Variante DD. Das DBD wurde vielleicht irgendwann mal undokumentiert eingebaut, vielleicht weil der Support zu oft genervt wurde von Programmierern die die Dokumentation nicht lesen (können)?

Man könnte die eine Zeile in Step7 classic programmieren und als Quelle in TIA importieren, da würde man sehen wie TIA das haben will.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Offiziell dokumentiert ist meines Wissens nur die Variante DD. Das DBD wurde vielleicht irgendwann mal undokumentiert eingebaut, vielleicht weil der Support zu oft genervt wurde von Programmierern die die Dokumentation nicht lesen (können)?

Harald
Wie gesagt, ich kenne es nicht anders als DBD. Vermutlich weil ich aus der AWL Ecke komme. DD gehört für meinen Wissensstand zur S5.

Aber wieder was gelernt.
 
Das hat sich ja jetzt wohl geklärt. :D

Der Vollständigkeit halber:
Ich nutze eine S7 1500 als CPU (1512SP).

Mir war nur nicht ganz klar nach welchem Stichwort ich denn genau suche.
Ein passendes Stichwort wäre "Slice-Zugriff".
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Es gibt auch noch eine Möglichkeit das ganze symbolisch zu lösen: mit AT
Ungefähr so: Du könntest einen FC schreiben, dem Du das Struct mit den 128 BOOL als INPUT übergibst und den INPUT mittels AT-Sicht mit 4 DWORD überlagern, dann kannst Du die DWORD symbolisch adressieren. Da würde es sich anbieten, das Struct als PLC-Datentyp (UDT) zu deklarieren, da wird die Deklaration im FC einfacher.

Harald
 
Ich denke, dass ich meine Lösung so lasse wie am Anfang vorgeschlagen. Einfach weil sie sehr einfach ist.

Danke allerdings für den Vorschlag. Die AT-Sicht war mir bis gerade eben noch nicht bekannt. Sehr interessant. (y)
 
Zurück
Oben