123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- FUNCTION_BLOCK "Ringpuffer"
- TITLE =Ringpuffer (FIFO) mit 32-bit breiten Elementen
- VERSION : 0.1
- VAR_INPUT
- eingabe : BOOL ;
- ausgabe : BOOL ;
- eingabe_wert : DWORD ;
- reset : BOOL ;
- END_VAR
- VAR_OUTPUT
- ausgabe_wert : DWORD ;
- ueberlauf : BOOL ;
- unterlauf : BOOL ;
- fuellstand : INT ;
- END_VAR
- VAR
- fm_eingabe : BOOL ;
- fm_ausgabe : BOOL ;
- anzahl_belegt : INT ;
- ptr_eingabe : DWORD ;
- ptr_ausgabe : DWORD ;
- elemente : ARRAY [0 .. 31 ] OF DWORD ;
- END_VAR
- VAR_TEMP
- max_anzahl_elemente : INT ;
- zaehler : INT ;
- END_VAR
- BEGIN
- NETWORK
- TITLE =Konstanten definieren
- L 32; // Groesse des "elemente" Arrays
- T #max_anzahl_elemente;
- NETWORK
- TITLE =Ringpuffer entladen
- U #ausgabe; // "ausgabe" positive Flanke?
- FP #fm_ausgabe;
- SPBN end1; // Nein? Dann Ende.
- L #anzahl_belegt;
- L 0;
- ==D ; // anzahl_belegt == 0?
- SPBN nunt; // ... dann kein Unterlauf
- SET ;
- = #unterlauf; // ... sonst Unterlauf anzeigen
- L 0;
- T #ausgabe_wert;
- SPA end1; // Und Ende.
- nunt: L P##elemente;
- L #ptr_ausgabe;
- +D ; // AR1 = element_0 + ptr_ausgabe
- LAR1 ; // AR1 zeigt auf das erste belegte Element
- L D [AR1,P#0.0];
- T #ausgabe_wert; // ausgabe_wert = erstes belegtes Element
- L 0; // Element nullen. (Nicht unbedingt noetig)
- T D [AR1,P#0.0];
- L #anzahl_belegt;
- L 1;
- -D ; // anzahl_belegt -= 1
- T #anzahl_belegt;
- L #ptr_ausgabe;
- L P#4.0;
- +D ; // ptr_ausgabe += 4
- T #ptr_ausgabe;
- L #max_anzahl_elemente;
- L P#4.0;
- *D ; // akku = Pointer auf Ringende
- L #ptr_ausgabe;
- >D ; // ptr_ausgabe < Ringende
- SPB end0; // ... dann Ende
- L P#0.0; // ... sonst ptr_ausgabe = P#0.0
- T #ptr_ausgabe;
- end0: CLR ;
- = #ueberlauf; // Fehleranzeigen zuruecksetzen
- = #unterlauf;
- end1: NOP 0;
- NETWORK
- TITLE =Ringpuffer beladen
- U #eingabe; // "eingabe" positive Flanke?
- FP #fm_eingabe;
- SPBN end3; // Nein? Dann Ende.
- L #anzahl_belegt;
- L #max_anzahl_elemente;
- <D ; // anzahl_belegt < max_anzahl?
- SPB nueb; // ... dann kein Ueberlauf
- SET ;
- = #ueberlauf; // ... sonst Ueberlauf anzeigen
- SPA end3; // Und Ende.
- nueb: L P##elemente;
- L #ptr_eingabe;
- +D ; // AR1 = element_0 + ptr_eingabe
- LAR1 ; // AR1 zeigt auf das erste freie Element
- L #eingabe_wert;
- T D [AR1,P#0.0]; // Erstes freies Element = eingabe_wert
- L #anzahl_belegt;
- L 1;
- +D ; // anzahl_belegt += 1
- T #anzahl_belegt;
- L #ptr_eingabe;
- L P#4.0;
- +D ; // ptr_eingabe += 4
- T #ptr_eingabe;
- L #max_anzahl_elemente;
- L P#4.0;
- *D ; // akku = Pointer auf Ringende
- L #ptr_eingabe;
- >D ; // ptr_eingabe < Ringende
- SPB end2; // ... dann Ende
- L P#0.0; // ... sonst ptr_eingabe = P#0.0
- T #ptr_eingabe;
- end2: CLR ;
- = #ueberlauf; // Fehleranzeigen zuruecksetzen
- = #unterlauf;
- end3: NOP 0;
- NETWORK
- TITLE =Reset-Signal verarbeiten
- U #reset;
- SPBN nrst;
- // Statische Variablen und Ausgaenge nullen
- L 0;
- T #ausgabe_wert;
- T #fuellstand;
- T #anzahl_belegt;
- T #ptr_eingabe;
- T #ptr_ausgabe;
- CLR ;
- = #ueberlauf;
- = #unterlauf;
- // Alle Elemente nullen.
- // Dies ist nicht unbedingt notwendig, aber zur Fehlersuche sinnvoll.
- L #max_anzahl_elemente;
- next: T #zaehler;
- L 1;
- -D ;
- L P#4.0;
- *D ;
- L P##elemente;
- +D ;
- LAR1 ;
- L 0;
- T D [AR1,P#0.0];
- L #zaehler;
- LOOP next;
- nrst: NOP 0;
- NETWORK
- TITLE =Fuellstand ausgeben
- L #anzahl_belegt;
- T #fuellstand;
- END_FUNCTION_BLOCK
- DATA_BLOCK "DB_Ringpuffer"
- "Ringpuffer"
- BEGIN
- END_DATA_BLOCK
- ORGANIZATION_BLOCK OB 1
- VAR_TEMP
- OB1_EV_CLASS : BYTE; // Bits 0-3 = 1 (Coming event), Bits 4-7 = 1 (Event class 1)
- OB1_SCAN_1 : BYTE; // 1 (Cold restart scan 1 of OB 1), 3 (Scan 2-n of OB 1)
- OB1_PRIORITY : BYTE; // Priority of OB execution
- OB1_OB_NUMBR : BYTE; // 1 (Organization block 1, OB 1)
- OB1_RESERVED_1 : BYTE;
- OB1_RESERVED_2 : BYTE;
- OB1_PREV_CYCLE : INT; // Cycle time of previous OB 1 scan (milliseconds)
- OB1_MIN_CYCLE : INT; // Minimum cycle time of OB 1 (milliseconds)
- OB1_MAX_CYCLE : INT; // Maximum cycle time of OB 1 (milliseconds)
- OB1_DATE_TIME : DATE_AND_TIME; // Date and time OB 1 started
- END_VAR
- BEGIN
- U "clock_100ms"
- = E 0.0
- U "clock_200ms"
- = E 0.1
- L L#31337
- T ED 2
- U A 0.0
- = E 0.2
- CALL "Ringpuffer", "DB_Ringpuffer" (
- eingabe := E 0.0,
- ausgabe := E 0.1,
- eingabe_wert := ED 2,
- reset := E 0.2,
- ausgabe_wert := AD 2,
- ueberlauf := A 0.0,
- unterlauf := A 0.1,
- fuellstand := AW 6,
- )
- L ED 2
- L AD 2
- L AW 6
- END_ORGANIZATION_BLOCK
|