Array in FB mit Größe als Parameter

Heimchen

Level-1
Beiträge
6
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi,

ist es möglich, einem FB bei der Deklaration einen Parameter so zu übergeben, dass dieser innerhalb des FB als Größe für ein Array herhalten kann?
Zum Hintergrund: ich möchte einen Buffer-FB erstellen, wobei ich aber nicht pauschal 1000bytes o.ä. reservieren möchte. Denn mal brauche ich große Buffer und mal sehr kleine. Bisher deklariere ich das Array extern und übergebe die Größe und Startadresse. Dabei kann ich aber nicht absichern, dass die Größe tatsächlich der Größe des Arrays entspricht. Außerdem muss der übergeordnete Block zwei Variablen deklarieren.

Gruß, Heimchen
 
Genau so mach ich es ja. Aber wie ich schon geschrieben hab, kann ich mich innerhalb des FBs nicht gegen Pufferüberläufe schützen.

Dass Arraygrößen nur Konstanten sein dürfen, weiß ich. Kann man vielleicht irgendwie erreichen, dass ich eine Konstante erst bei der Deklaration festlegen kann?
 
Hallo, was willst du den genau mit dem FB erreichen?

Soll das Array nur zwischengespeichert werden oder musst du an dem Puffer etwas ändern.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Der FB hat einen Input uiSize. In dem FB soll ein Array-Puffer angelegt werden, mit eben der Größe uiSize. Im Betrieb wird der Puffer als FIFO mit neuen Werten gefüllt üder die dann der Mittelwert berechnet wird. Der Mittelwert wird dann wieder ausgegeben.
 
Hallo,

dann kannst du doch mit Pointern arbeiten.

Als Eingang übergibst du die Größe und Adresse deines Arrays.

In dem Baustein greifst du dann auf den Inhalt deines Arrays mit Hilfe der Pointer zu.
 
Wie bereits geschrieben: das tue ich, habe dann aber in meinem FB nicht die Möglichkeit, einen Buffer Overrun zu verhindern. Oder kann ich irgendwie überprüfen, ob die übergebene Größe und das adressierte Array zusammenpassen?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn du dem FB folgendes übergibst z.B.:
Code:
(*Deklaration*)
VAR_INPUT
	Size_Array	: UINT;
	ADR_Array	: POINTER TO REAL;
END_VAR
VAR
	i: INT;
	Summe: REAL;
	MW: REAL;
END_VAR
(*FB-Anweisungen im ST*)
Summe:=0;
FOR i:=0 TO Size_Array	DO
	Summe:=Summe+ADR_Array^;
	ADR_Array:=ADR_Array+1;
END_FOR

MW:=Summe/Size_Array;
kannst du eigentlich keinen Überlauf erzeugen. Wenn du eine Kontrolle machen willst z.B.: Begrenzung - musst du eine Abfrage vor der Berechnung einfügen.

PS: habs noch nicht auf Richtigkeit geprüft
 
Zuletzt bearbeitet:
Und wenn der Nutzer des FB dann sowas macht:
Code:
arBuffer : ARRAY [1..20] OF REAL;
avgAverage(..., prBuffer:=ADR(arBuffer), uiSize:=500);
Genau davor möchte ich mich schützen. Auch wenn's eigentlich der Fehler von dem andern ist...

PS: REAL-Pointer muss man um 4 erhöhen.
 
OK, das mit dem 4 erhöhen, ist eine Fehler ;-)

Aber, das jemand deinen Baustein falsch ansteuert kann man nicht verhindern.
Dann liegt der Fehler beim Programmierer, alles kann man nicht berücksichtigen.

Evtl. könntest du eine Plausibilitätsprüfung machen.
 
Bei codesys gibt es eine Funktion "check range" (oder so ähnlich), such mal im Handbuch danach.
Mit dieser Funktion kannst du den Fall der Indexüberschreitung seperat behandeln.

Vielleicht hilft es dir, was besseres fällt mir so spontan nicht ein.
 
Anstatt des ARRAY könnte man zur Laufzeit einen DB mit entsprechender Größe erzeugen und durch indirekte Adressierung auf die REALs (oder was auch immer) zugreifen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Malloc gibt es nicht bei der SPS

Was Du machen möchtest, gibt es nicht auf einer CoDeSys (oder anderer) SPS. Und das ist gewollt so.

In der IT nennt man das Memory allocieren (malloc in C). Sobald man Memory dynamisch reserviert und wieder freigibt, kann man für nix mehr garantieren, weder dafür, dass man den Speicher bekommt, noch für die Zykluszeit.

Bei fester Speichervergabe kann der Compiler überprüfen, dass die Hardware nicht an ihre Grenzen stösst und das Reservieren des Speichers kostet keine Zykluszeit.

Bei der dynamischen Speichervergabe könnte es sein, dass mehr Speicher angefordert wird als vorhanden und was dann? Zusätzlich gibt es noch das Problem der Memory Fragmentation aber dazu mal im Internet suchen.
 
Bei codesys gibt es eine Funktion "check range" (oder so ähnlich), such mal im Handbuch danach.
Mit dieser Funktion kannst du den Fall der Indexüberschreitung seperat behandeln.

Vielleicht hilft es dir, was besseres fällt mir so spontan nicht ein.
Es gibt die Funktion CheckBounds. In der Hilfe findest du wie die funktioniert, das funktioniert aber auch nicht, wenn man mit Pointer in einen Array reingreift, hilft daher für diesen Fall nicht weiter. Leider gibt es zu dem Typ keine Laufzeitinformation, das heisst, es ist prinzipiell nicht möglich zu wissen, auf was ein Pointer zeigt.
 
Zurück
Oben