Adresse von Formaloperanden ermitteln

Katzi

Level-2
Beiträge
7
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo, ich habe folgendes Problem:

Habe mir einen FC geschrieben, der einen binären Zustand auswertet (Meldung, Warnung, ...).
Damit ich dem FC nur 1 Bit übergeben muss (IN_OUT), greife ich auf diverse Hilfsmerker(Datenbits) indirekt zu, indem ich mir die Adresse des Formaloperanden auslese (Netzwerk 1, 1. Anweisung) und Offsets dazuaddiere.

Code:
FUNCTION FC 21 : VOID
TITLE =Antrieb: Meldung
FAMILY : Antrieb
VERSION : 1.0


VAR_INPUT
  Sign : BOOL ;    //Feldsignal Fehler (1=Fehler)
  Meldung_ist_Alarm : BOOL ;    //Meldung ist Alarm (1=Antrieb wird abgeschaltet, 0=Nur Warnung)
END_VAR

VAR_IN_OUT
  Meldung : BOOL ;    //Meldung
  Antrieb : UDT 11;    
END_VAR

VAR_TEMP
  adresse_Meldungen : DINT ;    
  adresse_Alarme : DINT ;    
  adresse_Warnungen : DINT ;    
  adresse_FLM : DINT ;    
  adresse_FL : DINT ;    
  adresse_Meld_gesp : DINT ;    
END_VAR

BEGIN
NETWORK
TITLE =Adressen der Bits für die Alarmbehandlung ermitteln
//Folgende Adressen ergeben sich aus dem Aufbau des UDT11!!
//
//Die Beschaltung der Meldung von aussen muss ein Bit aus dem Bereich "Meldungen" 
//sein --> UDT11, Offset 12!!

      L     P##Meldung; // Adresse der Meldung
      T     #adresse_Meldungen; 
      LAR1  ; // Dient nur zur Kontrolle, welche Adresse "übergeben" wird
      L     P#4.0; 
      +D    ; 
      T     #adresse_Alarme; // 4 Bytes dahinter: Alarme
      L     P#4.0; 
      +D    ; 
      T     #adresse_Warnungen; // 8 Bytes dahinter: Warnungen
      L     P#4.0; 
      +D    ; 
      T     #adresse_FLM; // 12 Bytes dahinter: Flankenmerker
      L     P#4.0; 
      +D    ; 
      T     #adresse_FL; // 16 Bytes dahinter: Flanken
      L     P#4.0; 
      +D    ; 
      T     #adresse_Meld_gesp; // 20 Bytes dahinter: Meldungen gespeichert

NETWORK
TITLE =Meldung aufbereiten

      U     #Sign; 
      =     #Meldung; // Störmeldung
      FP    DBX [#adresse_FLM]; 
      =     DBX [#adresse_FL]; // Flanke Störmeldung gekommen

      U     #Meldung; 
      U     #Meldung_ist_Alarm; 
      =     DBX [#adresse_Alarme]; // Störmeldung schaltet Antrieb ab

      U     #Meldung; 
      UN    #Meldung_ist_Alarm; 
      =     DBX [#adresse_Warnungen]; // Störmeldung schaltet Antrieb NICHT ab

      U     #Antrieb.Schnittstelle.Quitt; 
      R     DBX [#adresse_Meld_gesp]; 
      U     DBX [#adresse_FL]; 
      U     DBX [#adresse_Alarme]; 
      S     DBX [#adresse_Meld_gesp]; // gespeicherte Meldung

END_FUNCTION
Wenn ich nun dem FC als Parameter z.B.: M12.1 übergebe, verwendet er die M16.1, M20.1, M24.1, usw. als Hilfsmerker (vorausgesetzt im Netwerk 2 wird DBX durch M ersetzt) --> funktioniert.
Wenn ich aber ein Datenbit übergebe (z.B: DB201.DBX10.0), dann funktioniert das mit dem Auslesen der Adresse des Formaloperanden nicht mehr.

Ich weiß nicht warum.

Wäre dankbar, wenn mir jemand helfen könnte.
 
es fehlt die information, welcher datenbaustein.

Wenn du damit das Netzwerk 2 meinst: Richtiger DB ist aufgeschlagen.

Das Problem fängt schon bei der 1. Zeile im 1. Netzwerk an:
Beim Merker taucht im Adressregister (LAR1) wirklich M12.1 auf, wobei beim Datenbit (egal welches) nur V21.0 auftaucht. --> Was bedeutet V21.0 im Adressregister?
 
V weist auf die vorherigen Lokaldaten hin.
das wird so nix, weil dir bei deinem pointer 2byte fehlen, nämlich die, in denen die DB-nummer steht.
 
... wie wäre es, die fragliche Variable als Pointer zu definieren ? Dann kämen doch die benötigten Info's mit ...

Gruß
LL

das meinte ich mit ANY


so sieht der aufruf mit Datenbaustein aus, wie du siehst, wird er schon vorher aufgemacht und nicht übergeben... was du liest, ist das lokalbit, das für die beschaltung des FCs benutzt wird, im aufrufbeispiel die 24.1
es würde also im baustein ein V24.1 geladen ...
Code:
*
      BLD   1
      =     L     24.0
      AUF   DB    20
      U     DBX    0.0
      =     L     24.1

      L     0
      T     LW    25
      L     P#L 20.0
      T     LD    27
      UC    FC    21
            P#E 10.0
            P#E 10.1
            P#L 24.1
            P#L 25.0
      U     L     24.1
      AUF   DB    20
      =     DBX    0.0
      BLD   2
 
Nein - nein ... ich meinte tratsächlich POINTER und nicht ANY. Der Pointer hätte den Vorteil, dass er nicht ganz so breit ist wie der ANY nur halt keinen Bereich übergeben kann - das war hier ja aber auch gar nicht gefordert ...

Gruß
LL
 
Nein - nein ... ich meinte tratsächlich POINTER und nicht ANY. Der Pointer hätte den Vorteil, dass er nicht ganz so breit ist wie der ANY nur halt keinen Bereich übergeben kann - das war hier ja aber auch gar nicht gefordert ...

Gruß
LL

hast ja recht... :rolleyes:

und dann kann man schön auswerten:

Code:
*
      L     P##pIn
      LAR1

      L     W [AR1,P#0.0]
      L     0
      <>I   
      SPBN  db2
      TAK   
      T     #wDB1
      SET   
      =     #xDB1
      SPA   db3
db2:  CLR   
      =     #xDB1

und entsprechend reagieren...

ANY hätte den vorteil, den datentyp überprüfen zu können... aber ist ja nicht notwendig
 
so sieht der aufruf mit Datenbaustein aus, wie du siehst, wird er schon vorher aufgemacht und nicht übergeben

das kann man sich doch zu nutze machen... funktioniert allerdings nur, solange du nur ein datenbaustein-bit bzw. alles aus dem selben DB an IN und IN/OUT benutzt... nur die bitadresse bekommste so immer noch nicht rüber...

Code:
*
      L     DBNO                        // letzten offenen Globaldatenbaustein ...
      T     #wDbnoSave
      AUF   DB [#wDbnoSave]

eieiei ... das ist ja ganz böse....
 
Zuletzt bearbeitet:
so müßte es gehen, ABER schön ist anders ...

Code:
*
      [B][COLOR="Red"]AUF   DB    20[/COLOR][/B]
      CALL  FC    21
       Sign             :=E10.0
       Meldung_ist_Alarm:=E10.1
       Meldung          :=[B][COLOR="red"]DBX0.0[/COLOR][/B]
       Antrieb          :=#antrieb

Code:
*
      AUF   DB    20
      BLD   1
      =     L     24.0
      L     0
      T     LW    25
      L     P#L 20.0

      T     LD    27
      UC    FC    21
            P#E 10.0
            P#E 10.1
           [B] [COLOR="red"]P#DBX 0.0[/COLOR][/B]
            P#L 25.0
      BLD   2
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
@Katzi

2 Fragen:

1. Warum machst du die Auswertung nicht gleich im Antriebs FB/FC?
Wenn ich richtig verstanden habe, dann wird dort dein UDT versorgt.

2. Wie ist der UDT aufgebaut?

Micha
 
@Katzi
Warum machst du die Auswertung nicht gleich im Antriebs FB/FC?
Wenn ich richtig verstanden habe, dann wird dort dein UDT versorgt.

Weil ich ein Modulares Bausteinsystem aufbaue, bei dem nur das aufgerufen wird, was vom Antrieb auch benötigt wird.
- Um Resourcen zu sparen
- Um nicht einen Megagrossen FB beschalten zu müssen (vor grosssen FB's haben viele Leute Angst ...)
 
ok. wenn du das so machen willst ist das deine Sache.
Übersichtlicher ists sicher nicht.

Wie sieht der UDT denn aus?
Die Logik sagt mir, dass darin das Bit "Meldung" steckt.
(1) Ist das richtig ?

Willst du den FC21 für jeden Antrieb aufrufen, oder deinen Eingang multiplexen?

Falls du FC21 für jeden Antrieb einmal aufrufst und (1) richtig ist, dann kannst du dir den IN/OUT "Meldung" sparen.
Die Adresse hast du dann schon.

Micha
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie sieht der UDT denn aus?
Die Logik sagt mir, dass darin das Bit "Meldung" steckt.
(1) Ist das richtig ?

Willst du den FC21 für jeden Antrieb aufrufen, oder deinen Eingang multiplexen?

Ja, im UDT stecken die Meldungen (bis zu 32).
Daher kann der FC21 für jeden Antrieb mehrmals für verschieden Meldungen aufgerufen werden.
 
ok. dann ist es ganz einfach das UDT indirekt anzusprechen.
Du übergibst ja den UDT.

Schreib einfach mal als erste 2 Zeilen in deinem FC 21
Code:
u antrieb.meldungen
clr

und schon ist der richtige DB offen.
AR1 steht am Anfang des UDT.

Danach sparst du dir die vielen Lokaldoppelwörter und arbeitest mit AR1 + Offset.

Micha
 
Danke Jungs für eure Tipps.

Folgendermassen habe ich das jetzt in den Griff bekommen:

Code:
FUNCTION FC 21 : VOID
TITLE =Antrieb: Meldung

VAR_INPUT
  Sign : BOOL ;    //Feldsignal Fehler (1=Fehler)
  Meldung_ist_Alarm : BOOL ;    //Meldung ist Alarm (1=Antrieb wird abgeschaltet, 0=Nur Warnung)
END_VAR
VAR_IN_OUT
  Meldung : POINTER ;    //Meldung
  Antrieb : UDT 11;    
END_VAR
VAR_TEMP
  DB_Nummer : INT ;    
  adresse_Meldungen : DINT ;    
  adresse_Alarme : DINT ;    
  adresse_Warnungen : DINT ;    
  adresse_FLM : DINT ;    
  adresse_FL : DINT ;    
  adresse_Meld_gesp : DINT ;    
END_VAR
BEGIN
NETWORK
TITLE =Adressen der Bits für die Alarmbehandlung ermitteln
//Folgende Adressen ergeben sich aus dem Aufbau des UDT11!!
//
//Die Beschaltung der Meldung von aussen muss ein Bit aus dem Bereich "Meldungen" 
//sein --> UDT11, Offset 12!!
      L     P##Meldung; // Adresse des Pointers (Zeigt auf Lokaldaten des aufrufenden FC)
      LAR1  ; // Lokaldaten des Aufrufenden FC ins Adressregister, um an die "echten" Adressen zu kommen

      L     W [AR1,P#0.0]; // DB-Nummer von Pointer holen
      T     #DB_Nummer; 

      L     D [AR1,P#2.0]; // Bitadresse von Pointer holen

      T     #adresse_Meldungen; // Adresse der Meldung
      L     P#4.0; 
      +D    ; 
      T     #adresse_Alarme; // 4 Bytes dahinter: Alarme
      L     P#4.0; 
      +D    ; 
      T     #adresse_Warnungen; // 8 Bytes dahinter: Warnungen
      L     P#4.0; 
      +D    ; 
      T     #adresse_FLM; // 12 Bytes dahinter: Flankenmerker
      L     P#4.0; 
      +D    ; 
      T     #adresse_FL; // 16 Bytes dahinter: Flanken
      L     P#4.0; 
      +D    ; 
      T     #adresse_Meld_gesp; // 20 Bytes dahinter: Meldungen gespeichert

NETWORK
TITLE =Meldung aufbereiten

      AUF   DB [#DB_Nummer]; 

      U     #Sign; 
      U     #Antrieb.Schnittstelle.Ctrl_VLT; // Steuerspannung
      =     DBX [#adresse_Meldungen]; // Störmeldung
      FP    DBX [#adresse_FLM]; 
      =     DBX [#adresse_FL]; // Flanke Störmeldung gekommen

      U     DBX [#adresse_Meldungen]; 
      U     #Meldung_ist_Alarm; 
      =     DBX [#adresse_Alarme]; // Störmeldung schaltet Antrieb ab

      U     DBX [#adresse_Meldungen]; 
      UN    #Meldung_ist_Alarm; 
      =     DBX [#adresse_Warnungen]; // Störmeldung schaltet Antrieb NICHT ab

      U     #Antrieb.Schnittstelle.Quitt; // Störungsquittierung
      R     DBX [#adresse_Meld_gesp]; 
      U     DBX [#adresse_FL]; 
      U     DBX [#adresse_Alarme]; 
      S     DBX [#adresse_Meld_gesp]; // gespeicherte Meldung

END_FUNCTION

@SPSKILLER

und schon ist der richtige DB offen.
AR1 steht am Anfang des UDT.
Das ist richtig, aber man weiss immer noch nicht das genaue Bit, das dem FC von aussen übergeben wurde.
 
Zurück
Oben