Step 7 Bitfolge (Array) in Dezimalzahl wandeln

TimeOUT

Level-1
Beiträge
125
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Forum,

ich habe ein Array [0..7] OF BOOL und möchte nun die enthaltene Bitfolge in eine Dezimalzahl wandeln.
Dabei ist Bit 7 das LSB und 0 das MSB.

Beispiel:
BITFOLGE[0] := 0
BITFOLGE[1] := 0
BITFOLGE[2] := 0
BITFOLGE[3] := 0
BITFOLGE[4] := 1
BITFOLGE[5] := 0
BITFOLGE[6] := 0
BITFOLGE[7] := 1

--> Dezimalzahl = 9

Gibt es da von Siemens aus eine Konvertierungsfunktion o.Ä.?
Ich programmiere in AWL.

Danke für die Tipps

Gruß
TimeOut
 
Etwas Fertiges kann ich mir nicht vorstellen, in SCL würde mir da etwas Schickes einfallen. In AWL sähe das dann nicht mehr so schick aus - du müßtest dir ja eine Schleife erstellen (oder Wert für Wert aufaddieren).

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Larry,

Im Moment mach ich es quasi ganz stur mit:

Code:
 L     0
      T     #code


      U     #BIT_Code[7]
      L     1
      L     #code
      +I    
      T     #code


      U     #BIT_Code[6]
      L     2
      L     #code
      +I    
      T     #code


      U     #BIT_Code[5]
      L     4
      L     #code
      +I    
      T     #code


      U     #BIT_Code[4]
      L     8
      L     #code
      +I    
      T     #code

Wie genau kann ich darum eine Schleife programmieren? SIMATIC lässt keine #Variable, welche ich hochzähle bzw. runter zählen lasse, als Index für BIT_Code[#Variable] zu.

Gruß
timeout
 
Du könntest die Bits schieben oder rotieren und dann immer das LSB auswerten für Deine Addition.
Dein Array ist ja nichts Anderes als ein Byte, auf welches Du zugreifen kannst.
Kannst Du denn nicht sofort "anders herum" einlesen (7=MSB/0=LSB)? Dann kannst Du direkt das Byte auslesen...
Oder Du schreibst sie aus dem Array per Zuweisung in ein Byte, richtig herum geordnet, und verwendest dann das Byte...
 
Das Problem bei dir ist, dass die Bit-Reihenfolge im Grunde falsch herum ist.

Du bildest dir eine Hilfsvariable als Multiplikator und setzt die zunächst auf 1.
Du bildest dir einen Pointer auf das niedrigste Bit im Array (Bitfolge[0]) und lädst diese Adresse. Wenn TRUE dann addierst du auf dein Ergebnis die Hilfsvariable.
Nun erhöhst du den Pointer um 1 und die Hilfsvariable schiebst du um ein nach links (danach hat sie als Wert 2).
Nun lädst du die neue Pointeradresse und wenn TRUE dann addierst du auf dein Ergebnis die Hilfsvariable.
Usw.
Kannst du das als Code umsetzen ?

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie bilde ich nochmal einen Pointer auf das niederwertigste Bit im Array (Bitfolge[7]) und lade dann die Adresse?

Ich muss mir die Pointer FAQ nochmal anschauen.. das verstehe ich noch nicht so ganz :(

Gruß
timeout
 
Vll. so, ist aber ungeteste

Code:
[COLOR=#333333]VAR
BITFOLGE : ARRAY[0..7] OF BOOL;
BITFOLGE_WERT : INT;
END_VAR

VAR_TEMP
tBYTE : BYTE;
tBYTE_BITS AT tBYTE : ARRAY[0..7] OF BOOL;
END_VAR

tBYTE_BITS[0] := BITFOLGE[7]; //alternativ per Schleife zuweisen[/COLOR]
[COLOR=#333333]tBYTE_BITS[1] := BITFOLGE[6];
[/COLOR][COLOR=#333333]tBYTE_BITS[2] := BITFOLGE[5];
[/COLOR][COLOR=#333333]tBYTE_BITS[3] := BITFOLGE[4];
[/COLOR][COLOR=#333333]tBYTE_BITS[4] := BITFOLGE[3];
[/COLOR][COLOR=#333333]tBYTE_BITS[5] := BITFOLGE[2];
[/COLOR][COLOR=#333333]tBYTE_BITS[6] := BITFOLGE[1];
[/COLOR][COLOR=#333333]tBYTE_BITS[7] := BITFOLGE[0];

BITFOLGE_WERT := BYTE_TO_INT(tBYTE);[/COLOR]
 
Im Moment mach ich es quasi ganz stur mit:

Code:
 L     0
      T     #code


      U     #BIT_Code[7]
      L     1
      L     #code
      +I    
      T     #code


      U     #BIT_Code[6]
      L     2
...
Ich kann mir nicht vorstellen, dass der Code so funktioniert, da Lade- und Transferbefehle nicht VKE-abhängig sind. Demzufolge werden immer alle Bitstellen addiert, egal ob das zugehörige Bit des Arrays 0 oder 1 ist.




Vll. so, ist aber ungeteste

Code:
[COLOR=#333333]tBYTE_BITS[0] := BITFOLGE[7]; //alternativ per Schleife zuweisen[/COLOR]
[COLOR=#333333]tBYTE_BITS[1] := BITFOLGE[6];
...[/COLOR]
Hat nur einen Haken:
Ich programmiere in AWL.
;)
 
Wie bilde ich nochmal einen Pointer auf das niederwertigste Bit im Array (Bitfolge[7]) und lade dann die Adresse?

Ich muss mir die Pointer FAQ nochmal anschauen.. das verstehe ich noch nicht so ganz :(

Hallo,
nicht das niederwertigste sondern das niedrigste - also von der Speicheradresse her - das wäre dann Bitfolge[0] ...

Code:
L 0
T #meinOutWert
L 128
T #meinBitwert
L p##Bitfolge
LAR1

Loop: U [AR1 , p#0.0]
         spbn nAkt

         L #meinOutWert
         L #meinBitwert
         +I
         T #meinOutWert

nAkt: L #meinBitwert
         SRW 1   
         T #meinBitwert

         L p#0.1
         +AR1

         L #meinBitwert
         L 0
         <>I
         SPB Loop
... ungetestet ... könnte aber zum Ziel führen ...

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Leute,

erstmal vielen Dank für die zahlreichen Tipps und Code snippets.
@hucki:
Ich kann mir nicht vorstellen, dass der Code so funktioniert, da Lade- und Transferbefehle nicht VKE-abhängig sind. Demzufolge werden immer alle Bitstellen addiert, egal ob das zugehörige Bit des Arrays 0 oder 1 ist.

Damit hast Du recht ;)
War mir so nicht bewusst. Jetzt weiß ich aber wieso es nicht funktioniert hat :)

Meine derzeitige Lösung ist ähnlich dem Vorschlag von JSEngineering/hub.

Allerdings werde ich mir den Vorschlag von Larry und dem Pointer nochmal zu Gemüte führen, wenn ich den Baustein optimiere.

Viele Grüße
Timeout
 
War mir so nicht bewusst. Jetzt weiß ich aber wieso es nicht funktioniert hat :)
Wenn Du auch Deine eigene obige Variante weiter verfolgen möchtest, musst Du zwischen jeder Bitabfrage und dem folgenden Ladebefehl einen bedingten Sprung einfügen, der Dich bei ungesetztem Bit unter Auslassung der Addition zur nächsten Bitabfrage befördert:
Code:
      L     0
      T     #code

      U     #BIT_Code[7]
      [COLOR=#00ff00]SPBN[/COLOR]  [COLOR=#00ff00]Bit6[/COLOR]
      L     1
      L     #code
      +I    
      T     #code

[COLOR=#00ff00]Bit6:[/COLOR] U     #BIT_Code[6]
      [COLOR=#00ff00]SPBN[/COLOR]  [COLOR=#00ff00]Bit5[/COLOR]
      L     2
...
 
Hallo,

tut mir leid, dass ich den Thread nochmal auspacke, aber ich habe noch eine Frage bzgl. der Pointer.

Ich versuche mich gerade in die Thematik einzuarbeiten indem ich ein 6 Byte langes Array (BYTE_CODE) in ein 48 Bit langes Array (BIT_CODE) zu konvertieren versuche.

Das ganze versuche ich mit der Hilfe von 2 Pointern zu realisieren.
Ich erstelle zunächst ein Pointer auf die Anfangsadresse des BYTE-Arrays und speicher mir die Adresse weg. Anschließend erstelle ich den Pointer auf das BIT-Array und speicher mir ihn weg.

Jetzt frage ich die einzelnen Bitwerte im BYTE-Array ab und setze, wenn TRUE das BIT im BIT-ARRAY (so zumindest der Plan)
Anschließend inkrementiere ich beide Pointer.

Hier mein Code:

Code:
      L     0      T     #SCHLEIFENCOUNTER
      L     P##BYTE_CODE
      T     #PTR_BYTE
      L     P##BIT_CODE
      T     #PTR_BIT




_nxt: SET   
      LAR1  #PTR_BYTE


      U     DIX [AR1,P#0.0]
      SPBN  nAkt


// Setze Bits in BIT_CODE


      LAR1  #PTR_BIT                    // Setze Bit
      S     DIX [AR1,P#0.0]




nAkt: SET                               // Inkrementiere Quell-Pointer
      LAR1  #PTR_BYTE
      +AR1  P#0.1
      T     #PTR_BYTE


      LAR1  #PTR_BIT                    // Rücksetze Bit
      R     DIX [AR1,P#0.0]


      LAR1  #PTR_BIT                    // Inkrementiere Ziel-Pointer
      +AR1  P#0.1
      T     #PTR_BIT






      L     #SCHLEIFENCOUNTER
      L     1
      +I    
      T     #SCHLEIFENCOUNTER


      L     #SCHLEIFENCOUNTER
      L     47
      ==I   
      SPBN  _nxt

Leider funktioniert es wider erwartend nicht :p

Was vergesse/übersehe ich?
Hat es etwas mit dem Schieben um 3 Bit zu tun?

Viele Grüße
TimeOut
 
Hey,

ich dachte das Erhöhen erfolgt durch:

Code:
LAR1  #PTR_BYTE
+AR1  P#0.1
T     #PTR_BYTE

??

Aber wenn ich es, wie in deinem Vorschlag erwähnt, probiere funktioniert es leider trotzdem nicht.
 
Für welche CPU soll Dein Code sein?
Wo liegen Deine Arrays BYTE_CODE und BIT_CODE? Wie sind sie deklariert?
Programmierst Du einen FC oder einen FB? Beim indirekten Zugriff auf eigene Multiinstanz-Adressen in FB muß der Multiinstanz-Offset aus AR2 beachtet werden.
Wie wird der DI-DB geöffnet - ist das der Instanz-DB des FB mit Deinem Code?
Willst Du wirklich nur das Zielbit Setzen wenn das Quellbit gesetzt ist oder willst Du nicht eigentlich den Wert des Quellbits in das Zielbit kopieren, egal ob es 1 oder 0 ist? Für's Kopieren gibt es die = Operation.

Tipp: Statt umständlicher und fehlerträchtiger Pointer-Akrobatik kann man zum Kopieren der 6 Byte auch den SFC20 BLKMOV benutzen.
Wenn man es unbedingt mit Einzel-Operationen machen will, dann ist es in FB "schöner", statt registerindirekter Adressierung (mit AR..) die speicherindirekte Adressierung mit Pointer in TEMP-DWORD (LD) zu benutzen. Da kann man beliebig viele Pointer benutzen und spart sich das dauernde Umladen des AR1-Registers und muß AR2 nicht anfassen.
Beispiel:
Code:
AUF DB [#Quell_DB]  //(kann eventuell entfallen)
U DBX [#PTR_BYTE]   //Quell-Bit lesen
AUF DI [#Ziel_DB]   //(kann eventuell entfallen)
= DIX [#PTR_BIT]    //in Ziel-Bit kopieren

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@T E :
Das Erhöhen des AR-Registers funktioniert so - vollkommen korrekt ... und wo wird das so erhöhte Register wieder in deine Pointer-Variable zurück geschrieben ...?

Was passiert denn so ...
Wird der FB in einem anderen Baustein integriert ?

Gruß
Larry
 
Hi,

also ich programmiere einen FB. Keine Multiinstanz. Die Daten liegen allesamt im Instanzdatenbaustein.
Der FB wird auch nirgendwo integriert.

Also das der SFC20 das so hinbekommt wusste ich nicht. Allerdings kann ich mit der Darstellung nicht gescheit weiter arbeiten.

Bsp: BYTE_CODE[0] := B#16#0C

daraus macht der SFC20:
BIT_CODE[0] :=FALSE
BIT_CODE[1] :=FALSE
BIT_CODE[2] :=TRUE
BIT_CODE[3] :=TRUE
BIT_CODE[4] :=FALSE
BIT_CODE[5] :=FALSE
BIT_CODE[6] :=FALSE
BIT_CODE[7] :=FALSE


allerdings brauche ich diese darstellungsweise:

BIT_CODE[0] :=FALSE
BIT_CODE[1] :=FALSE
BIT_CODE[2] :=FALSE
BIT_CODE[3] :=FALSE
BIT_CODE[4] :=TRUE
BIT_CODE[5] :=TRUE
BIT_CODE[6] :=FALSE
BIT_CODE[7] :=FALSE

Liegt einfach an der darauf folgenden Weiterverarbeitung der BIT-Werte.
Deshalb wollte ich das ganze mit den Pointer so "hinbiegen".

@Larry

Wird das erhöhte Register nicht hier wieder in die Variable zurückgeschrieben?

Code:
LAR1  #PTR_BIT                    // Inkrementiere Ziel-Pointer      
+AR1  P#0.1
 T     #PTR_BIT <-- Hier??

Ich denke wenn ich den Wert 0x0C vorher um 4 nach links rotiere (sprich: die 4 niederwertigen mit den 4 höherwertigen Bits tauschen) und dann den SFC20 darauf anwende, dass mir der dann die richte Bitfolge generiert.
Muss das später mal probieren.

Gruß
Timeout
 
Zuletzt bearbeitet:
@TO:
Ja ... rotieren (4 ×) wäre das Mittel der Wahl ...

In deinem Code-Schnipsel verwendest du "T" -der würde den Akku 1 transferieren - nicht aber das AR1 - das könnte dann nur der Befehl TAR1 ...

Gruß
Larry
 
Zurück
Oben