Step 7 Bitadresse in einem DB mit Ganzzahl berechnen

Fritz4

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

Ich habe einen DB mit 1000 Bit Variablen als Fehlernummern angelegt. Zusätzlich zum "normalen absoluten" Setzen eines einzelnen Bits im Programm möchte ich nun mit einer Funktion eine Ganzzhal laden und das entsprechende Bit einzeln berechen und es dann setzen. (z.B L 100 => S DB5.DBX 12.3)
Kann mir jemand helfen wie ich das machen kann?

Gruß und Danke im Voraus

Fritz4
 
Moin,

100 / 8 Bit ergibt 12,5 -> abgerundet auf Ganzzahl = 12
12 ist also schon mal deine Byte-Adresse.
100 mod 8 ergibt 4 -> das sind deine Bits die noch auf das Byte "addiert" werden müssen
Also Byte 12 Bit 4 -> und da die Bits bei 0 Anfangen ergibt sich 12.3 als Adresse.

Alternativ kannst du aber auch deine 1000 Bits in deinem DB in ein Array of Bool stecken und dann direkt mit myBoolArray[100] arbeiten. Das wäre meine Empfehlung dazu.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
DBX12.3 ist das 100ste Bit von oben begonnen wenn ich richtig gerechnet hab oder. So meinst du das nehm ich an.
Ich würde das mit registerindirekter Adressierung machen. Ungefähr so
Code:
L #Fehlernummer
L 8
/I 
T #Byteadresse
TAK // Rest im Akku 2
T #Bitadresse

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

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

So in der Richting. Hab grad kein Step7 zur Hand zum testen
Lg
 
Hallo Zusammen

Vielen Dank Howard und TP-Inc für die super schnellen Antworten.
Ich werde Eure Vorschläge nachher Ausprobieren.

Gruß
Fritz4
 
Code:
L #Fehlernummer     //z.B. 100
L P#0.0             //Anfangsadresse des Bitfelds (P##mYBitfeld bei TEMP/STAT, P#DBX0.0 geht auch)
+D
LAR1

SET
AUF #FehlerDB
S DBX [AR1, P#0.0]  //= geht auch

Wenn das Bitfeld bei DBX0.0 anfängt reicht sogar schon das:
Code:
L #Fehlernummer     //z.B. 100
LAR1

SET
AUF #FehlerDB
S DBX [AR1, P#0.0]  //= geht auch

Funktioniert natürlich nur wenn die Fehler-Bits byteweise aufsteigend organisiert sind und nicht etwa wordweise wie die WinCCflex-Bitmeldungen.

Harald
 
Ganz kurz ein paar Code-Fraqmente von mir:

Code:
//*** Adresse berechnen (Bytes vertauschen)
BIT := NUMMER_INTERN - 1;
IF (BIT MOD 16) < 8 
   THEN TEMP_INT := BIT + 8;
   ELSE TEMP_INT := BIT - 8;
END_IF;

//*** ByteIndex, BitIndex für Siemens-HMI mit vertauschten Bytes
ByteIndex := TEMP_INT DIV 8;
BitIndex  := TEMP_INT MOD 8;

//*** ByteIndex mit nicht vertauschten Bytes
ByteIndexNormal := BIT DIV 8;
     
//*** Störung nichtspeichernd im DB ablegen
STOERMELDE_DB.DX[ByteIndex, BitIndex] := SM_INTERN;
 
Zuviel Werbung?
-> Hier kostenlos registrieren
...eine Ganzzhal laden und das entsprechende Bit einzeln berechen und es dann setzen. (z.B L 100 => S DB5.DBX 12.3)

Guten Morgen zusammen,

bin zufällig auf das Forum gestoßen und auch gleich fündig geworden.
Ich habe ein ähnliches Problem, nur gerade umgekehrt.
In einem DB, 150 Bytes groß, werden einzelne Bits zur Visualisierung einer Fehlermeldung gesetzt.
Wie bekomme ich wieder eine Ganzzahl raus?
DBX0.0 = 1
DBX0.1 = 2
...usw

Vielen Dank an alle!

Grüße
 
Ich habe ein ähnliches Problem, nur gerade umgekehrt.
In einem DB, 150 Bytes groß, werden einzelne Bits zur Visualisierung einer Fehlermeldung gesetzt.
Wie bekomme ich wieder eine Ganzzahl raus?
DBX0.0 = 1
DBX0.1 = 2
...usw
Deine Aufgabenstellung beruht auf "die Nummer des niedrigsten gesetzten Bits ermitteln". Das kann man z.B. so machen:
- mit einer Schleife i = 0..1199 suchen ob myBitfeld gesetzt ist und bei Fund die Suche abbrechen ---> i+1 ist dann Deine Ganzzahl
- oder Wordweise/DWordweise durchsuchen und mit ENCO die Nummer des niedrigsten gesetzten Bits des (D)Words ermitteln
- weitere Algorithmen

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Zurück zum Thema:
eine Ganzzhal laden und das entsprechende Bit einzeln berechen und es dann setzen. (z.B L 100 => S DB5.DBX 12.3)
Anstatt registerindirekter Adressierung mit AR1 oder AR2 kann man auch etwas besser lesbare speicherindirekte Adressierung verwenden:
Code:
L #Fehlernummer
+ -1                  //weil das Array ab DBX0.0 mit Fehlernummer 1 beginnt
T #tempNummer         //DWord in TEMP

SET
AUF "FehlerDB"
S DBX [#tempNummer]   //= geht auch

Oder vollsymbolisch in SCL:
Code:
"FehlerDB".myBitfeld[Fehlernummer - 1] := TRUE;

Man könnte bei dem Fehler-Bitfeld den ersten Eintrag an DBX0.0 unbenutzt lassen (und das Bitfeld als Array [0..999] deklarieren anstatt Array [1..1000]), dann kann man für die Adressberechnung "Fehlernummer" direkt verwenden und muß nicht 1 subtrahieren, und dann führt Fehlernummer=0 auch nicht zu einem Zugriffsfehler.

Harald
 
Ganzzahl aus Bitadresse

Hallo Harald,

danke für deine Antwort. Ich muss aber nochmal nachfragen:
Was bedeutet myBitfeld?
In dem Bereich von 150 Bytes können auch mehrere Bits sitzen. Anhand der letzten 10 Bits müssen die Ganzzahlen ermittelt werden.
Ich hoffe, ich erkläre es verständlich.

Grüße


quote_icon.png
Zitat von bmwled Ich habe ein ähnliches Problem, nur gerade umgekehrt.
In einem DB, 150 Bytes groß, werden einzelne Bits zur Visualisierung einer Fehlermeldung gesetzt.
Wie bekomme ich wieder eine Ganzzahl raus?
DBX0.0 = 1
DBX0.1 = 2
...usw
Deine Aufgabenstellung beruht auf "die Nummer des niedrigsten gesetzten Bits ermitteln". Das kann man z.B. so machen:
- mit einer Schleife i = 0..1199 suchen ob myBitfeld gesetzt ist und bei Fund die Suche abbrechen ---> i+1 ist dann Deine Ganzzahl
- oder Wordweise/DWordweise durchsuchen und mit ENCO die Nummer des niedrigsten gesetzten Bits des (D)Words ermitteln
- weitere Algorithmen

Harald
 
Was bedeutet myBitfeld?

das i-te Element des Arrays "myBitfeld" (Beispielname für irgendein "mein Bitfeld")

In dem Bereich von 150 Bytes können auch mehrere Bits sitzen. Anhand der letzten 10 Bits müssen die Ganzzahlen ermittelt werden.
:confused: Dann mußt Du mal genauer erklären was Du willst.

Du hast einen DB, wo Du ab Adresse DBX0.0 bis DBX149.7 150 * 8 = 1200 Bits als BOOL deklariert hast (jedes Bit einzeln als BOOL deklariert?). Das entspricht einem "Bitfeld : ARRAY [1..1200] OF BOOL". Wenn es tatsächlich so deklariert ist, dann kann man DBX0.0 als Bitfeld[1] ansprechen, das DBX0.1 als Bitfeld[2], das DBX0.2 als Bitfeld[3] ... Anstatt der festen Indexnummer kann man auch eine Indexnummer in eine Variable i speichern und dann die Array-Elemente indirekt ansprechen: Bitfeld - das spricht das Element an, dessen Nummer in i drinsteht, bei i = 10 also Bitfeld[10] (das ist DBX1.1)

Du brauchst jetzt einen Programmcode, der die Nummer (den Index i) eines gesetzten Bits als Ganzzahl zurückgibt:
- bei (Bitfeld[1]) DBX0.0=1 soll 1 rauskommen
- bei (Bitfeld[2]) DBX0.1=1 soll 2 rauskommen
- bei (Bitfeld[3]) DBX0.2=1 soll 3 rauskommen
- ...

Was soll rauskommen wenn, DBX0.1 und DBX0.2 beide gleichzeitig 1 sind (und DBX0.0=0)? (üblicherweise will man da die Nummer des niederwertigsten Bits wissen --> also von DBX0.1 --> also 2)
Was sind "letzte 10 Bits"?

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... Was sind "letzte 10 Bits"? ...
Ich warte mit Spannung auf die Auflösung ... das hat bestimmt nicht mit der Anordnung der Bits zu tun, sondern mit der Reihenfolge, in der die Bits gesetzt wurden?
Von wegen
In einem DB, 150 Bytes groß, werden einzelne Bits zur Visualisierung einer Fehlermeldung gesetzt.
Wie bekomme ich wieder eine Ganzzahl raus?

;o)
Gruss, Heinileini

 
Hallo zusammen,

ich beantworte mal die Fragen:

Was soll rauskommen wenn, DBX0.1 und DBX0.2 beide gleichzeitig 1 sind (und DBX0.0=0)? (üblicherweise will man da die Nummer des niederwertigsten Bits wissen --> also von DBX0.1 --> also 2)


Der Leitrechner kann mit Bits nichts anfangen, er stellt nur die Fehlermeldungen dar. Das heißt wenn:

DBX0.0 = 0
DBX0.1 = 1
DBX0.2 = 1

Dann bräuchte ich im Ganzzahl-Register eine 2 und eine 3.


Was sind "letzte 10 Bits"?

Es sollen maximal 10 Ganzzahlen bzw. Fehlermeldungen ermittelt werden, sprich wenn 15 Fehler aktiv sind stehen im Ganzzahl-Register nur 10 Ganzzahlen drin.

In einem DB, 150 Bytes groß, werden einzelne Bits zur Visualisierung einer Fehlermeldung gesetzt.
Wie bekomme ich wieder eine Ganzzahl raus?


In der Tat etwas ungeschickt ausgedrückt, "eine Ganzzahl" pro Fehlermeldung. ;)

Du brauchst jetzt einen Programmcode, der die Nummer (den Index i) eines gesetzten Bits als Ganzzahl zurückgibt:
- bei (Bitfeld[1]) DBX0.0=1 soll 1 rauskommen
- bei (Bitfeld[2]) DBX0.1=1 soll 2 rauskommen
- bei (Bitfeld[3]) DBX0.2=1 soll 3 rauskommen

Exakt. :) :s12:


Schon mal vielen Dank für eure Beteiligung.

Grüße
 
Zuletzt bearbeitet:
Dann bräuchte ich im Ganzzahl-Register eine 2 und eine 3
[...]
Es sollen maximal 10 Ganzzahlen bzw. Fehlermeldungen ermittelt werden, sprich wenn 15 Fehler aktiv sind stehen im Ganzzahl-Register nur 10 Ganzzahlen drin.
Das geht so nicht. Im AKKU kann nur eine Zahl stehen. Dein "Register" muß ein Array sein (oder eine Liste falls der Leitrechner das versteht).

Du müsstest ein Ergebnis-"Array of Ganzzahl" mit 10 Elementen ([1..10] oder [0..9]) haben und dann die Nummern der bis zu (max) 10 gesetzten Bits nacheinander in die 10 Array-Elemente eintragen (also bei den Tipps Beitrag #11 nicht nach dem ersten gefundenen Bit aufhören sondern weitersuchen). Wenn weniger als 10 Bits gesetzt sind, dann in die unbenutzten Array-Elemente 0 eintragen (vor der Suche alle 10 initialisieren oder nach dem letzten gefundenen Bit nur die restlichen Elemente). An den Leitrechner übergib eine Kopie des Ergebnis-Arrays. Wie sieht die Anforderung/Dokumentation des Leitrechners aus, wie will er die 10 Zahlen haben?

Wenn mehr als 10 Fehler gleichzeitig aktiv sind - welche 10 sollen dann gemeldet werden? Am einfachsten ist die 10 niederwertigsten Bits.

Harald
 
... Wenn mehr als 10 Fehler gleichzeitig aktiv sind ...

Welche Rolle spielt überhaupt die Zeit? Kein(e) Zeitstempel, wann die Meldung aufgetreten (und wieder verschwunden ist)?
Wie "zeitnah" werden die Nummern an den Leitrechner gesendet?
Gibt es eine Priorisierung der Meldungen (je kleiner die Nummer, desto "wichtiger" die Meldung)?
Länger anstehende Meldungen werden immer wieder dem Leitrechner mitgeteilt, bis sie nicht mehr anstehen oder durch "wichtigere" Meldungen verdrängt werden?
Mir will wohl einleuchten, dass in der SPS (und ggfs im Leitrechner) eine Form der Pufferung stattfindet (Array, FIFO, ...), um bei einer Häufung von Meldungen den Engpass Schnittstelle zu beherrschen, aber für einen Abbruch der Berichterstattung nach der jeweils 10. Meldung spricht doch wohl nur, dass diese Lösung progammtechnisch verlockend scheint?
Gruss, Heinileini
 
Zeitstempel etc. spielen keine Rolle.
Priorisierung ist je kleiner, je wichtiger.
Länger anstehende Meldungen werden bis sie quittiert werden dem Leitrechner gemeldet.
10 Meldungen sind programmtechnisch ausreichend... ;)
 
Zurück
Oben