Störmledungsbaustein mit Pointer?!?

Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn die Daten nicht in der Instanz liegen kannst du mit einen DB-Zeiger
oder Any-Zeiger auf die Adresse zeigen. Ein DB-Zeiger ist 48 Bit lang, in
Byte 0-1 liegt die Datenbaustein Nr. als INT wert, aber nur wenn der
Bereichszeiger für Operandenbereich Global.-oder Instanzdaten enthält.
Im Byte 2-5 steht dann der Bereichszeiger.
Code:
FUNCTION_BLOCK "DB-Zeiger"
TITLE =Meldebaustein
VERSION : 0.1
 
VAR_INPUT
  pZeiger_Meldung : POINTER ; 
END_VAR
VAR_OUTPUT
  xtest : BOOL ; 
END_VAR
VAR_TEMP
  dTempAR1 : DWORD ; //Zwischenspeicher Adressregister 1
  dTempAR2 : DWORD ; //Zwischenspeicher Adressregister 2
  wTempDB_Nr : INT ; //DB Nr Meldung
  dTempAdresse : DWORD ; //Bereichszeiger Meldung
END_VAR
BEGIN
NETWORK
TITLE =Adressregister retten
      TAR1  #dTempAR1; 
      TAR2  #dTempAR2; 
NETWORK
TITLE =Meldung-Zeiger umladen
//Pointer-Zeiger umladen
      TAR2  ; //AR2 in Akku
      UD    DW#16#FFFFFF; //Bereichscodierung ausblenden
      L     P##pZeiger_Meldung; //Stardadresse "Meldung"
      +D    ; 
      LAR1  ; 
//DB-Nr Temp. zwischenspeichern
      L     W [AR1,P#0.0]; 
      T     #wTempDB_Nr; 
//Adresse Temp. zwischenspeichern
      L     D [AR1,P#2.0]; 
      T     #dTempAdresse; 
NETWORK
TITLE =Datenbaustein aufschlagen und Adressrgister stellen
//Meldung: Global, AR1 
      AUF   DB [#wTempDB_Nr]; 
      LAR1  #dTempAdresse; 
NETWORK
TITLE =hier kommst du jetzt
//hier jetzt deine Anweisungen
//ein bischen mußt du auch arbeiten
      U     DBX [AR1,P#0.0]; 
      =     #xtest; 
NETWORK
TITLE =Adressregister wieder herstellen
      LAR1  #dTempAR1; 
      LAR2  #dTempAR2; 
END_FUNCTION_BLOCK
 
das verstehe ich schon nur selbst wenn ich den folgenden Code verwende wird auch kein bit gesetzt...

Code:
      L     P##MELDUNG
      LAR1  
 
     U     #QUITTIERUNG
     S      [AR1,P#12.0]

der ganze quelltext befindet sich in einem fb und die varibale #meldung ist vom typ bool und liegt in der schnittstelle unter in_out

Hallo,
unter Berücksichtigung der bisherigen Beiträge und der Tatsache, dass diese in keiner Weise zielführend waren und dem oben dargestellten Beitrag würde ich mir im Moment NICHT zutrauen, hier qualifiziert weiterhelfen zu können.

@CrazyMC:
Mir würde es sehr helfen (und vielleicht den Anderen auch), wenn du einfach mal an Hand eines Beispiels zu verdeutlichen versuchst, was du zu tun beabsichtigst ... dann kommen wir hier vielleicht auch weiter ... ;)

Gruß
LL
 
Zuviel Werbung?
-> Hier kostenlos registrieren
den Code habe ich soweit eigentlich erstmal funktionstüchtig zumindest so wie ich es mir prinzipiell gedacht hatte...

Code:
FUNCTION_BLOCK FB 10
TITLE =
VERSION : 0.1
 
VAR_INPUT
  STOERUNG : BOOL ; 
  QUITTIERUNG : BOOL ; 
  MELDUNGSZEIT : TIME ; 
END_VAR
VAR_IN_OUT
  MELDUNG : POINTER ; 
END_VAR
VAR
  SFB_MELDUNGSZEIT_TON : SFB 4; 
  SFB_QUITTIERZEIT : SFB 4; 
  temp_DB_BIT : DWORD ; 
  temp_Meldung : BOOL ; 
  tmp_DB_BIT : DWORD ; 
  temp_Quit : BOOL ; 
  tmp_quit : BOOL ; 
  STOERUNGSSPEICHER : BOOL ; 
END_VAR
VAR_TEMP
  AR2_tmp : DWORD ; 
  AR1_tmp : DWORD ; 
  temp_DB_NR : INT ; 
END_VAR
BEGIN
NETWORK
TITLE =
      TAR1  #AR1_tmp; 
      TAR2  #AR2_tmp; 
NETWORK
TITLE =
      L     P##MELDUNG; // Andresse des Eingangs- Bits, aus Pointer lesen
      LAR1  ; // Adresspointer adressieren
      L     W [AR1,P#0.0]; // erstes Wort eines Pointers enthält DB-Nr.
      T     #temp_DB_NR; 
      L     W [AR1,P#4.0]; // Bitadresse von Pointer holen
      T     #tmp_DB_BIT; 
      L     #tmp_DB_BIT; 
      L     P#12.0; 
      +D    ; 
      T     #temp_DB_BIT; 
      AUF   DB [#temp_DB_NR]; 
NETWORK
TITLE =Störung
      U     #STOERUNG; 
      S     #STOERUNGSSPEICHER; 
      UN    #STOERUNG; 
      U     #QUITTIERUNG; 
      R     #STOERUNGSSPEICHER; 
NETWORK
TITLE =
 
      CALL #SFB_QUITTIERZEIT (
           IN                       := #tmp_quit,
           PT                       := T#2S,
           Q                        := #temp_Quit);
NETWORK
TITLE =Meldungszeit
 
      CALL #SFB_MELDUNGSZEIT_TON (
           IN                       := #STOERUNGSSPEICHER,
           PT                       := #MELDUNGSZEIT,
           Q                        := #temp_Meldung);
      AUF   DB [#temp_DB_NR]; 
      U     #temp_Meldung; 
      L     #tmp_DB_BIT; 
      LAR1  ; 
      S     DBX [AR1,P#0.0]; 
NETWORK
TITLE =
      U     #QUITTIERUNG; 
      L     #tmp_DB_BIT; 
      LAR1  ; 
      L     #temp_DB_BIT; 
      LAR2  ; 
      U     DBX [AR1,P#0.0]; //Störbit gesetzt
      S     DBX [AR2,P#0.0]; //Quittierbit setzen
      R     DBX [AR1,P#0.0]; //Störbit rücksetzen
      R     #temp_Meldung; 
NETWORK
TITLE =
 
      U     DBX [AR2,P#0.0]; //Quittierbit gesetzt
      UN    DBX [AR1,P#0.0]; //Störbit gesetzt
      =     #tmp_quit; 
NETWORK
TITLE =
      U     #temp_Quit; 
 
      R     DBX [AR2,P#0.0]; 
      R     #temp_Quit; 
NETWORK
TITLE =
      LAR1  #AR1_tmp; 
      LAR2  #AR2_tmp; 
END_FUNCTION_BLOCK

jetzt habe ich nur das problem wenn sich mehrere meldungen gleichzeitig aufrufen erscheint immer nur die, welche zuerst programmiert wurde :-|

Aufruf:

Code:
FUNCTION_BLOCK FB 150
TITLE =
VERSION : 0.1

VAR
  meldung1 : FB 10; 
  meldung2 : FB 10; 
  meldung3 : FB 10; 
  meldung4 : FB 10; 
END_VAR
BEGIN
NETWORK
TITLE =
      U     M    100.0; 
      =     L      0.0; 
      BLD   103; 
      U     M    200.0; 
      =     L      0.1; 
      BLD   103; 
      CALL #meldung1 (
           STOERUNG                 := L      0.0,
           QUITTIERUNG              := L      0.1,
           MELDUNGSZEIT             := T#5S,
           MELDUNG                  := DB190.DBX   24.0);
      NOP   0; 
NETWORK
TITLE =
      U     M    100.0; 
      =     L      0.0; 
      BLD   103; 
      U     M    200.0; 
      =     L      0.1; 
      BLD   103; 
      CALL #meldung2 (
           STOERUNG                 := L      0.0,
           QUITTIERUNG              := L      0.1,
           MELDUNGSZEIT             := T#7S,
           MELDUNG                  := DB190.DBX   25.0);
      NOP   0; 
NETWORK
TITLE =
      U     M    100.0; 
      =     L      0.0; 
      BLD   103; 
      U     M    200.0; 
      =     L      0.1; 
      BLD   103; 
      CALL #meldung3 (
           STOERUNG                 := L      0.0,
           QUITTIERUNG              := L      0.1,
           MELDUNGSZEIT             := T#9S,
           MELDUNG                  := DB190.DBX   26.0);
      NOP   0; 
NETWORK
TITLE =
      U     M    100.0; 
      =     L      0.0; 
      BLD   103; 
      U     M    200.0; 
      =     L      0.1; 
      BLD   103; 
      CALL #meldung4 (
           STOERUNG                 := L      0.0,
           QUITTIERUNG              := L      0.1,
           MELDUNGSZEIT             := T#11S,
           MELDUNG                  := DB190.DBX   27.0);
      NOP   0; 
END_FUNCTION_BLOCK
 
Zuletzt bearbeitet:
hey,

nimms mir nicht übel, aber der Baustein ist totaler Schrott!

... aber du wolltest ja wissen was nicht stimmt ;)

1. die Variablendeklaration ist ne 6
Was soll das tmp bzw. temp vor den statischen Variablen?
Das ist beim Lesen des Codes völlig verwirrend!

2. und viel schlimmer:
Nach dem Verbiegen von AR2 kann man nicht mehr (korrekt) symbolisch auf statische Variablen zugreifen.
-> #temp_Quit
Mich wundert ehrlich gesagt, dass deine CPU nicht in Stopp geht.

#temp_Quit muss indirekt beschrieben werden.
Dafür ist der Baustein aber auch nicht geeignet, da nicht Multiinstanzfähig.

Lass das AR2 doch weg, und nimm AR1+AR2-> AR1 (bei allen AR1 im FB, die auf den Instanz DB zeigen)
Danach adressierst du deine jetzigen AR2 Zugriffe mit AR1[p#12.0]
Das sollte auf den ersten Blick das gleiche sein.

Micha
 
Zuletzt bearbeitet:
nimms mir nicht übel, aber der Baustein ist totaler Schrott!

@CrazyMC,
da hat der Micha vollkommen recht, vlt. solltest du einen einfachen
FC erstellen, den du dann über die Schnittstelle mit ein paar Variablen
fütterst. Multinstanz, Adressregister, Pointer ist nicht das was man
mal eben so programmiert und durcheinander schmeißen kann.
Wenn man das nutzen will muss man sehr Diszipliniert arbeiten aber
das kann ich an deiner Handschrift nicht erkennen. Der FB10 kann und
wird auch nicht funktionieren.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
war ja auch nur nen ansatz und der grundgedanke... immerhin funktionierts ja für nur eine meldung. mein problem ist nur das wir eien derart große anzahl meldungen verwalten müssen die erst nach ablauf einer gewissen zeit gesetzt werden sollen das uns die timer nicht reichen werden - daher der gedanke ein paramtrierbarer baustein wo auch jeder dödel ein paar variablen dran schreibt und dann funktionierts...
 
Probiers mal so:

Code:
UNCTION_BLOCK FB 11
TITLE =Meldungen
AUTHOR : Micha
VERSION : 1.0
 
VAR_INPUT
  STOERUNG : BOOL ; 
  QUITTIERUNG : BOOL ; 
  MELDUNGSZEIT : TIME ; 
END_VAR
VAR_IN_OUT
  MELDUNG : POINTER ; 
END_VAR
VAR
  SFB_MELDUNGSZEIT_TON : "TON"; 
  SFB_QUITTIERZEIT : "TON"; 
  sbSTOERUNGSSPEICHER : BOOL ; 
END_VAR
VAR_TEMP
  tiDB : INT ; 
  tbMELDUNG : BOOL ; //=1: Meldezeit abgelaufen
  tbQUITT : BOOL ; //=1: Quittierzeit starten
END_VAR
BEGIN
NETWORK
TITLE =Pointer auswerten
      LAR1  AR2; 
      L     P##MELDUNG; 
      +AR1  ; 
      L     0; 
      L     DIW [AR1,P#0.0]; 
      ==I   ; 
      BEB   ; //Pointer zeigt nicht auf DB... ggf. reagieren
      T     #tiDB; 
      L     DIW [AR1,P#4.0]; 
      LAR1  ; 
NETWORK
TITLE =Meldung und Quittierung verarbeiten
      CALL #SFB_MELDUNGSZEIT_TON (
           IN                       := #STOERUNG,
           PT                       := #MELDUNGSZEIT,
           Q                        := #tbMELDUNG);
      CALL #SFB_QUITTIERZEIT (
           IN                       := #QUITTIERUNG,
           PT                       := T#3S,
           Q                        := #tbQUITT);
      AUF   DB [#tiDB]; 
      U     #QUITTIERUNG; 
      UN    #tbQUITT; 
      =     DBX [AR1,P#12.0]; 
      O     #QUITTIERUNG; 
      O     #tbQUITT; 
      R     #sbSTOERUNGSSPEICHER; 
      U     #tbMELDUNG; 
      S     #sbSTOERUNGSSPEICHER; 
      U     #sbSTOERUNGSSPEICHER; 
      =     DBX [AR1,P#0.0]; 
END_FUNCTION_BLOCK

Ich benutze nie Bitmeldungen, deshalb kann es sein dass die Quitteirphilosophie nicht euren Vorgaben entspricht.

Aber das Indirekte beschreiben der Variablen sollte klar werden.

Micha
 
so das wäre dann der auf unsere bedürfnisse geänderte baustein von micha...

Code:
FUNCTION_BLOCK FB 10
TITLE =Meldungen
AUTHOR : 
VERSION : 0.1

VAR_INPUT
  STOERUNG : BOOL ; 
  QUITTIERUNG : BOOL ; 
  MELDUNGSZEIT : TIME ; 
END_VAR
VAR_IN_OUT
  MELDUNG : POINTER ; 
END_VAR
VAR
  SFB_MELDUNGSZEIT_TON : SFB 4; 
  SFB_QUITTIERZEIT : SFB 4; 
  sbSTOERUNGSSPEICHER : BOOL ; 
  res_QUITT : BOOL ; //Start Reset Quittierbit
  HM_Quitt : BOOL ; //Hilfsmerker Quittierung
  HM_Meldung : BOOL ; //Hilfsmerker Meldung
END_VAR
VAR_TEMP
  tiDB : INT ; 
  tbMELDUNG : BOOL ; //=1: Meldezeit abgelaufen
  tbQUITT : BOOL ; //=1: Quittierzeit starten
END_VAR
BEGIN
NETWORK
TITLE =Pointer auswerten
      LAR1  AR2; 
      L     P##MELDUNG; 
      +AR1  ; 
      L     0; 
      L     DIW [AR1,P#0.0]; 
      ==I   ; 
      BEB   ; //Pointer zeigt nicht auf DB... ggf. reagieren
      T     #tiDB; 
      L     DIW [AR1,P#4.0]; 
      LAR1  ; 
NETWORK
TITLE =Störung
      U     #STOERUNG; 
      S     #sbSTOERUNGSSPEICHER; 
      UN    #STOERUNG; 
      U     #QUITTIERUNG; 
      R     #sbSTOERUNGSSPEICHER; 
NETWORK
TITLE =Meldung und Quittierung verarbeiten
      CALL #SFB_MELDUNGSZEIT_TON (
           IN                       := #sbSTOERUNGSSPEICHER,
           PT                       := #MELDUNGSZEIT,
           Q                        := #tbMELDUNG);
      CALL #SFB_QUITTIERZEIT (
           IN                       := #res_QUITT,
           PT                       := T#2S,
           Q                        := #tbQUITT);
      AUF   DB [#tiDB]; 
      U     #tbMELDUNG; 
      =     DBX [AR1,P#0.0]; //Störmeldungsbit setzen
      S     #HM_Meldung; 
      U     #QUITTIERUNG; 
      U     #HM_Meldung; 
      =     DBX [AR1,P#12.0]; //Quittierbit setzen
      S     #HM_Quitt; 
      U     #HM_Quitt; 
      UN    #tbMELDUNG; 
      =     #res_QUITT; 
      U     #tbQUITT; 
      R     #HM_Quitt; 
      R     #HM_Meldung; 
END_FUNCTION_BLOCK
 
Zurück
Oben