Quantcast
Channel: SPS-Forum - Automatisierung und Elektrotechnik
Viewing all articles
Browse latest Browse all 46422

FIFO Funktionsblock in CoDeSys 2.3 - weil einfach nicht einfach einfach ist...

$
0
0
Ich bin mir nicht sicher ob der Thread hier richtig ist, möglicherweise gehört er eher in "Programmierstrategien" oder auch den "Stammtisch"...

Beflügelt von diesem Thread habe ich mir gedacht ich ersetze den sonntäglichen Mittagsschlaf dadurch dass ich mir mal einen FB bastele der ähnlich funktioniert wie die Funktionen die ich seit Jahren von RSLogix gewohnt bin... Pustekuchen :shock:

Wenn man sich auf einen bestimmten Datentypen einschießt ist das ja alles noch recht überschaubar, zumal wenn man mit fest definierten Array-Längen arbeitet. Will ich aber nicht.
Deklarationen in der Form
Code:

length: INT;
foo: ARRAY[0..length] OF DINT;

werden in der verwendeten Version 2.3.9 mit kopfschütteln seitens CoDeSys quittiert. Alles klar, ich habe schon mal von Pointern gehört, die Siemens Leute brauchten dazu glaube ich AWL, aber wie funktionierts in CoDeSys?
[F1] gedrückt und den Mund nicht mehr zubekommen, die Hilfe ist einen Lacher wert *ROFL* Ich bins gewohnt nicht unbedingt an die Hand genommen zu werden, aber da kam ich mir schon etwas allein gelassen vor.

Hürde Nummer 1 ist genommen, Datentypen schießen mir ins Hirn, ich will nicht viel, aber wenigstens alles was in 32 Bit ausgedrückt werden kann mit einem FB verarbeiten...
REAL in DWORD kopieren? No Señor...

Hat sich da in Version 3 etwas getan? Ich würde gern die Länge des ersten Elements in Bytes ermitteln, den Pointer dann entsprechend positionieren und die benötigte Anzahl an Bytes umladen / einfügen / schreiben etc. Da ich dem Pointer ja schon einen Datentyp zuweisen muss definiere ich damit ja schon die Anzahl der zu bearbeitenden Bits... Wahrscheinlich gibt es dazu eine ganz einfache Lösung, Ideen? Anregungen? Fehler? Man werfe mir Schlagworte um die Ohren, ich kann Google benutzen...
Da ich beruflich zum Glück noch die Finger davon lassen darf belasse ich es jetzt mal dabei, falls jemand mal lachen möchte folgt unten noch ein wenig Code, das ganze kann ein Element in den (bis zu 32766 Elemente langen) FIFO-Speicher laden, ein Element aus dem FIFO-Speicher entladen, automatisch ein Element entladen wenn der Speicher voll ist (Laufspeicher für Historien etc.), have fun :mrgreen:

Code:

FUNCTION_BLOCK FIFO
VAR_INPUT
 LoadValue:  POINTER TO DWORD;
 UnloadValue:  POINTER TO DWORD;
 FirstElement:  POINTER TO DWORD;
END_VAR
VAR
 i:      INT;
 Size:    UDINT;
 DestPointer:  POINTER TO DWORD;
 SourcePointer:  POINTER TO DWORD;
END_VAR
VAR_IN_OUT
 Ctrl: ST_CTRL;
END_VAR

Size :=  SIZEOF(FirstElement^);
IF Ctrl.Full AND Ctrl.Autounload AND Ctrl.Load THEN
 SourcePointer := FirstElement + ((Ctrl.Position - 1) * Size);
 UnloadValue^ := SourcePointer^;
 Ctrl.Position := Ctrl.Position - 1;
END_IF;
IF Ctrl.Load AND (Ctrl.Position < Ctrl.Length) THEN
 Ctrl.Done := FALSE;
 FOR i := (Ctrl.Position) TO 1  BY -1 DO
  DestPointer := FirstElement + (i * Size);
  SourcePointer := FirstElement + ((i-1) * Size);
  DestPointer^ := SourcePointer^;
 END_FOR;
 FirstElement^ := LoadValue^;
 Ctrl.Position := Ctrl.Position + 1;
 Ctrl.Done := TRUE;
END_IF;
IF Ctrl.Unload AND (Ctrl.Position > 0) THEN
 Ctrl.Done := FALSE;
 SourcePointer := FirstElement + ((Ctrl.Position - 1) * Size);
 UnloadValue^ := SourcePointer^;
 SourcePointer^ := 0;
 Ctrl.Position := Ctrl.Position - 1;
 Ctrl.Done := TRUE;
END_IF;
IF Ctrl.Position = 0 THEN
 Ctrl.Empty := TRUE;
ELSE
 Ctrl.Empty := FALSE;
END_IF;
IF Ctrl.Position < Ctrl.Length THEN
 Ctrl.Full := FALSE;
ELSE
 Ctrl.Full := TRUE;
END_IF;




Aufruf:

Code:

PROGRAM PLC_PRG
VAR
 AddElement:  BOOL;
 RemoveElement:  BOOL;
 FIFO:  FIFO;
 BufferCtrl: ST_CTRL;
 Value:  DINT;
 Buffer:  ARRAY[0..15] OF DINT;
 Unload: DINT;
END_VAR

BufferCtrl.Enable := TRUE;
BufferCtrl.Autounload := TRUE;
BufferCtrl.Length := 16;
BufferCtrl.Load := AddElement;
BufferCtrl.Unload := RemoveElement;
FIFO(
 LoadValue:= ADR(Value),
 UnloadValue := ADR(Unload),
 FirstElement:= ADR(Buffer[0]),
 Ctrl := BufferCtrl);
IF BufferCtrl.Done THEN
 AddElement := FALSE;
 RemoveElement := FALSE;
END_IF;


Viewing all articles
Browse latest Browse all 46422


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>