Step 7 Bit in Wort nach Integer

Chris_Rgb

Level-2
Beiträge
39
Reaktionspunkte
2
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

nur eine kurze Frage, bevor ich mir selbst eine Funktion zusammen baue ;)
Gibt es einen Standardbaustein der aus der Stelle, an der in einem Wort ein Bit gesetzt ist einen Int macht.

zum Verständniss

Wort: / Int:
0000 0000 0000 0100 / 3
0000 0000 0010 0000 / 6
0000 0000 1010 0000 / 0

Ich will nur das Rad nicht neu erfinden;)

Gruß
Christian
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
[COLOR=#333333]*
[/COLOR]      L     16                          //16 bits hat ein INT
next: T     #iLoopCount                 //in Schleifenzähler laden
      L     #iInput                     //die eine INT-Zahl
      L     W#16#1                      //mit einer 0000 0000 0000 0001
      UW                                //UND-Verknüpfen
      L     0                           //auf 0
      ==I                               //vergleichen
      SPBN  [COLOR=#417394]bit[/COLOR]                         //wenn nicht 0 ist ein [COLOR=#417394]bit[/COLOR] gefunden wurden
      L     #iInput                     //die eine INT-Zahl
      SRW   1                           //um eine Stelle nach rechts
      T     #iInput                     //speichern
      L     #iLoopCount                 //Schleifenzähler
      LOOP  next                        //dekrementieren und erneut durchlaufen
      SPA   end                         //kein [COLOR=#417394]bit[/COLOR] gefunden - abbruch
[COLOR=#417394]bit[/COLOR]:  L     #iLoopCount                 //nach [COLOR=#417394]bit[/COLOR] gefunden steht hier die [COLOR=#417394]position[/COLOR]
      L     -1                          //also fast
      *I                                //y = -1 * x + 17
      +     17
      T     #iBitPosition               //position speichern 
[COLOR=#333333]end:  NOP   0[/COLOR]

aus http://www.sps-forum.de/simatic/20638-fifo-bit.html#post141770
 
Zuletzt bearbeitet:
Er meint wohl, wenn mehrere Bits gesetzt sind, soll 0 angezeigt werden. Vielleicht ist das seine Fehlermeldung, wenn der Integer den Wert Null hat.
 
Danke für die schnellen Antworten,

das ganze ist für eine Typvorgabe, die ich als Bit in einem Wort bekomme, aber als Integer in einer Matrix vergleichen muss.
und wenn mehr als ein Typ vorgegeben wird, stimmt was nicht;).
Werd mir dann wohl mit der Vorlage von vierlagig selber was basteln.
Ich wollte nur nicht die ganzen Standard Bibliotheken durchsehen um dann doch nichts zu finden

Gruß
Christian
 
und wenn mehr als ein Typ vorgegeben wird, stimmt was nicht;).
Da hilft Dir wohl der Klassiker von Thomas_v2.1, wenn Du den vor dem Code von vierlagig einfügst:
Also wenn die Eingangsdatenbits im Wort vorliegen:

Code:
      L     #IN_WORD
      DTR   
      L     DW#16#7FFFFF
      UD    
      L     L#0
      <>D   
      =     #Fehler
Das Bit #Fehler ist immer dann gesetzt wenn mehr als ein Bit im Wort gesetzt ist.

Das wär doch mal eine schöne Prüfungsfrage. Wie und wieso funktioniert das? :rolleyes:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Da hilft Dir wohl der Klassiker von Thomas_v2.1, wenn Du den vor dem Code von vierlagig einfügst:
Ich glaube diese abgewandelte Variante hatte ich auch schonmal irgendwo geposted, aber direkt kommt man zu der Bit-Position mit folgendem:
Code:
      L     #IN_WORD 
      DTR   
      SRD   23
      L     126
      -I  
      T     #iBitPosition
Quasi ein sehr eingeschränkter Zweierlogarithmus.
 
Ich glaube diese abgewandelte Variante hatte ich auch schonmal irgendwo geposted, aber direkt kommt man zu der Bit-Position.
:shock: Wow... Wie ich das gesehen hab blieb der Kiefer kurzzeitig unten..

Ich hab mit dem Codeschnippsel ein wenig herumgespielt und zwar für folgende Anwendung...

Ich brauch in einem meiner Standard-FBs eine Funktion damit ich die Adresse des gesetzten Bits in einem DWORD als Integer zurück bekomme.
Beispiel: Bit 0.7 -> Wert 7; Bit 1.5 -> Wert 15; Bit 3.6 -> Wert 36.

Bis jetzt hatte ich eine "unschöne" Konstruktion mit SRD -> Prüfung ob Bit gesetzt -> wenn nicht dann Schleife....

Ich hab deinen Code mal hergenommen und es funktioniert ganz gut:
CreateAddr_2.png

Leider ergibt sich wenn Bit 3.7 gesetzt ist ein Fehler...
CreateAddr_3.png

Natürlich könnte ich diesen Fall einfach eindämmen in dem ich das Bit 3.7 zuvor separat Prüfe.. so ala...
Code:
L     #IN_DWORD
L     128                         //Maske Bit 3.7
UD    
U     <>0
SPBN  N37

L     37
T     #Addr_INT
BEA   

N37:  NOP   0
//Hier Kommt der Rest
Wäre an sich ja nicht so schlimm, ich muss ja den Fall wenn kein Bit gesetzt ist auch manuell abfangen, wären also 2 Fälle zum abfangen...

Ich Frage mich jedoch ob ein einen intelligenteren Weg gäbe...

Für mich ist ja schon wundersam das nach DWORD->REAL->Sub 126 ... was brauchbares rauskommt. :ROFLMAO:
Quasi ein sehr eingeschränkter Zweierlogarithmus.

Egal.. dein Codeteil hat mir jedenfalls geholfen...
 
Wäre an sich ja nicht so schlimm, ich muss ja den Fall wenn kein Bit gesetzt ist auch manuell abfangen, wären also 2 Fälle zum abfangen...

Ich Frage mich jedoch ob ein einen intelligenteren Weg gäbe...

Bei DWORD muss du das Vorzeichenbit ausmaskieren, da DTR von DINT, also vorzeichenbehaftet den Datentyp wandelt.
Das könntest du z.B. mit
SLD 1
SRD 24

erledigen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Gibt es einen Standardbaustein der aus der Stelle, an der in einem Wort ein Bit gesetzt ist einen Int macht.
Ja, gibt es: TI-S7-Lib: FC96 "ENCO"

Bis jetzt hatte ich eine "unschöne" Konstruktion mit SRD -> Prüfung ob Bit gesetzt -> wenn nicht dann Schleife....
Macht Siemens in dem ENCO-Baustein auch so.

Harald
 
Code:
L     #IN_DWORD
L     128                         //Maske Bit 3.7
UD    
U     <>0
SPBN  N37

L     37
T     #Addr_INT
BEA   

N37:  NOP   0
//Hier Kommt der Rest
Tips:
Bei Wordverknüpfungen mit Konstanten kann die Konstante direkt in der Operation angegeben werden, z.B. "UD DW#16#80".
Will man nur ein einzelnes Bit testen, dann ist es schneller und kürzer, das Bit in das Statusbit A1 zu schieben oder zu rotieren. (Bei Rotieren kann man sogar den AKKU-Inhalt weiterverwenden, weil keine Bits "weggelöscht" werden.)
Wenn man abhängig vom Ergebnis ==0 oder <>0 springen will, dann braucht man nicht das Statusbit A1 ins VKE holen und dann VKE-abhängig springen, sondern kann direkt abhängig von A1 mit SPZ oder SPP springen.

Harald
 
Macht Siemens in dem ENCO-Baustein auch so
Ja stimmt, ENCO geht auch, ist auch vermutlich besser wenn der TE diese verwendet. Mit der Formel von Thomas scheint es ein paar Probleme zu geben... Dazu später.
Mit Schleifen hab ich natürlich kein Problem, wenn es mir einen Arbeits-Vorteil verschafft schreib ich eine. ;)
Die SPS hat eh genug Leistung.

Tips:
1: Bei Wordverknüpfungen mit Konstanten kann die Konstante direkt in der Operation angegeben werden, z.B. "UD DW#16#80".
2: Will man nur ein einzelnes Bit testen, dann ist es schneller und kürzer, das Bit in das Statusbit A1 zu schieben oder zu rotieren
3: ... sondern kann direkt abhängig von A1 mit SPZ oder SPP springen.
Danke für die Tipps, hab sie gleich mal alle angewandt...
1: Wusste ich absolut nicht! Steht zwar in der Hilfe aber... :roll: Sehr praktisch weil man für den Maskierwert den AKKU1 nicht ändern muss, bzw. AKKU2 nicht verliert.
Das hätte ich schon öfters gebraucht.
2: Wusste ich so halb. Mit Rotieren kann man ENCO sehr einfach nachprogrammieren.... Siehe unten.
3: Die verschiedenen Sprungoperationen kenn ich, hatte mir aber abgewöhnt diese zu verwenden damit der Code für die Kollegen leichter zu lesen ist. Wenn klar da steht (L 0 - >I - SPB) kapiert das jeder auf Anhieb. Mittlerweile hab ich die Möglichkeit die verweden schon fast wieder vergessen... :ROFLMAO:

Mit RDLA und A1 lässt sich ENCO sehr einfach realisieren...
Get_BitNUM_Working.jpg

Ich hatte mich dann noch mit der Formel von Thomas ein wenig weiter gespielt. Mit einem Wort funktioniert sie tadellos, bei einem DWORD gibt's ein merkwürdiges Verhalten. Setzt man alle Bits bis 2.7 stimmt das Ergebnis noch, setzt man dann zusätzlich das Bit 3.0 dann gibt's einen Wertesprung... komisch...
Get_BitAdress_1_Err.jpg

Danach hab ich die Funktion nochmal so umgeschrieben das das DWORD getrennt als 2 Worte behandelt wird. Das liefert dann auch wirklich für alle Werte die korrekte Zahl von 0-37 zurück...
Get_BitAdress_2_Working.jpg
Naja, so schön is nicht... :roll:
Die Variante ENCO oder RLDA ist aber wahrscheinlich nach Jahren wieder einfacher zu verstehen. Sonst hab ich wieder das Erlebnis...
"Was zum ***** hast du dir den dabei gedacht?!?!?"... :ROFLMAO:

Fazit: Lustiges Gedankenexperiment, Viele Wege führen nach Rom, manche sind nur geiler... :twisted:

PS: Jetzt aber genug vom Bitwi**en...


---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
UPDATE: PN/DP hat ein Siemens-FAQ gefunden in dem dieser Algorithmus pikfein erläutert wird. Da steht dann auch drin warum man ihn nicht für DWORD verwenden kann....
Maskieren vom niederwertigsten oder höchstwertigen gesetzten Bit in WORD und DWORD Variablen.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
Zuletzt bearbeitet:
Zurück
Oben