Zuviel Werbung? - > Hier kostenlos beim SPS-Forum registrieren

Ergebnis 1 bis 6 von 6

Thema: Ringpuffer in SCL mit Zeigern programmieren

  1. #1
    Registriert seit
    14.10.2014
    Beiträge
    13
    Danke
    6
    Erhielt 1 Danke für 1 Beitrag

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo zusammen,


    Ich programmiere in SCL mit TIA und möchte auf einen Ringpuffer mit Hilfe von Zeiigern zugreifen. Aus C kenne ich es, dass man Zeiger erstellen kann, die auf eine Struktur zeigen.

    Ich habe zum Beispiel folgende Struktur, aus der ich mir einen Array mit z.B. 15 Elementen mache:

    Code:
    typedef struct bsp_struct
    {    
        struct bsp_struct *forward_ptr;
        int messwert;
        int mess_nr;
    }Bsp_Struct;
    Dann erstelle ich mir von dieser Struktur einen Pointer

    Code:
    Bsp_Struct *struct_ptr;

    Nun kann ich dem struct_ptr eine Adresse zuweisen, wo der Ringpuffer anfangen soll.

    Code:
    struct_ptr = (Bsp_Struct*)LIST_ORIGIN;

    Nachdem ich dann meinen Ringpuffer initialisiert habe, kann ich mit Hilfe des Pfeil-Operators (->) auf die verschieden Elemente der Struktur zugreifen, also z.B.:

    Code:
    struct_ptr->messwert = 42;
    struct_ptr->mess_nr = 2;
    Wenn ich auf das nächste Element des Ringpuffers zugreifen will, lasse ich den struct pointer auf das nächste element zeigen, usw.

    Code:
    struct_ptr = struct_ptr->forward_ptr;

    Gibt es bei Siemens auch die Möglichkeit in einer ähnlichen Art und Weise auf die Elemente einer Struct in einem Ringpuffer zuzugreifen oder geht das nur mit Offsets? Bei größeren Strukturen wird das nämlich schnell mal unübersichtlicht.
    Zitieren Zitieren Ringpuffer in SCL mit Zeigern programmieren  

  2. #2
    Registriert seit
    19.07.2010
    Beiträge
    1.289
    Danke
    213
    Erhielt 267 Danke für 233 Beiträge

    Standard

    klar geht das. ich hab mal was getippt um einen Fehler zu finden.

    Code:
    FUNCTION_BLOCK "FB_DiagTuer" 
    
    // In diesem FB werden Signale und Zustände mitgeloggt, die dazu
    // führen könnten, dass die Hubtür geöffnet oder geschlossen wird.
    
    
    // Bausteinparameter
    VAR_INPUT
        // Eingangsparameter
        E_Tuer_offen : BOOL; // Endlage Tür offen
        E_Tuer_geschl : BOOL; // Endlage Tür geschlossen
        A_Tuer_oeffnen : BOOL; // Ansteuerung Tür öffnen
        A_Tuer_schliesen : BOOL; // Endlage Tür schließen
        Schrittnummer : INT;
        LS_Teil_vorhanden : BOOL;
        FIFO_P1_belegt : BOOL;
        FIFO_P2_belegt : BOOL;
        FIFO_P3_belegt : BOOL;
        FIFO_P4_belegt : BOOL;
        FIFO_P5_belegt : BOOL;
        FIFO_P6_belegt : BOOL;
        FIFO_Lack_Begonngen : BOOL;
        FIFO_Trocknung_iO : BOOL;
        Leerpos_takten : BOOL;
        Schaltleiste_betaetigt : BOOL;
        Tisch_takten : BOOL;
        Anzahl_Lackzyklen : int;
        Soll_Lackzyklen : int;
    END_VAR
    
    VAR_IN_OUT
        // Durchgangsparameter
    END_VAR
    
    VAR_OUTPUT
        // Ausgangsparameter
    
    END_VAR
     
    VAR_TEMP
        // temporäre Variablen
        tmp_int : INT;
    END_VAR
    VAR
        // statische Variablen
        FHV_Tuer_offen : BOOL;
        FHV_Tuer_geschl : BOOL;
        Zeiger_oeffnen : INT;
        Zeiger_schliesen : INT;
        Puffer_oeffnen : ARRAY [1..500] OF STRUCT
            Zeitstempel : DT;
            Schrittnummer : INT;
            A_Tuer_oeffnen : BOOL;
            A_Tuer_schliesen : BOOL;
            LS_Teil_vorhanden : BOOL;
            FIFO_P1_belegt : BOOL;
            FIFO_P2_belegt : BOOL;
            FIFO_P3_belegt : BOOL;
            FIFO_P4_belegt : BOOL;
            FIFO_P5_belegt : BOOL;
            FIFO_P6_belegt : BOOL;
            FIFO_Lack_Begonngen : BOOL;
            FIFO_Trocknung_iO : BOOL;
            Leerpos_takten : BOOL;
            Schaltleiste_betaetigt : BOOL;
            Anzahl_Lackzyklen : BYTE;
            Soll_Lackzyklen : BYTE;
        END_STRUCT;
        Puffer_schliesen : ARRAY[1..500] OF STRUCT
            Zeitstempel : DT;
            Schrittnummer : INT;
            A_Tuer_schliesen : BOOL;
            A_Tuer_oeffnen : BOOL;
            Tisch_takten : BOOL;
        END_STRUCT;
        
    END_VAR
    
        // Zeiger Bereichsüberwachung
        IF Zeiger_oeffnen < 1 OR Zeiger_oeffnen > 500 THEN
            Zeiger_oeffnen := 1;
        END_IF;
        
        // Daten in Ringpuffer schreiben wenn Tür geöffnet wird
        IF NOT E_Tuer_geschl AND FHV_Tuer_geschl THEN
            tmp_int := READ_CLK(CDT := Puffer_oeffnen[Zeiger_oeffnen].Zeitstempel);
            Puffer_oeffnen[Zeiger_oeffnen].Schrittnummer := Schrittnummer;
            Puffer_oeffnen[Zeiger_oeffnen].A_Tuer_schliesen := A_Tuer_schliesen;  
            Puffer_oeffnen[Zeiger_oeffnen].A_Tuer_oeffnen := A_Tuer_oeffnen;  
            Puffer_oeffnen[Zeiger_oeffnen].LS_Teil_vorhanden := LS_Teil_vorhanden;  
            Puffer_oeffnen[Zeiger_oeffnen].FIFO_P1_belegt := FIFO_P1_belegt;  
            Puffer_oeffnen[Zeiger_oeffnen].FIFO_P2_belegt := FIFO_P2_belegt;  
            Puffer_oeffnen[Zeiger_oeffnen].FIFO_P3_belegt := FIFO_P3_belegt;  
            Puffer_oeffnen[Zeiger_oeffnen].FIFO_P4_belegt := FIFO_P4_belegt;  
            Puffer_oeffnen[Zeiger_oeffnen].FIFO_P5_belegt := FIFO_P5_belegt;  
            Puffer_oeffnen[Zeiger_oeffnen].FIFO_P6_belegt := FIFO_P6_belegt;  
            Puffer_oeffnen[Zeiger_oeffnen].FIFO_Lack_Begonngen := FIFO_Lack_Begonngen;
            Puffer_oeffnen[Zeiger_oeffnen].FIFO_Trocknung_iO := FIFO_Trocknung_iO;  
            Puffer_oeffnen[Zeiger_oeffnen].Leerpos_takten := Leerpos_takten;  
            Puffer_oeffnen[Zeiger_oeffnen].Schaltleiste_betaetigt := Schaltleiste_betaetigt;
            Puffer_oeffnen[Zeiger_oeffnen].Anzahl_Lackzyklen := INT_TO_BYTE(Anzahl_Lackzyklen);
            Puffer_oeffnen[Zeiger_oeffnen].Soll_Lackzyklen := INT_TO_BYTE(Soll_Lackzyklen);
             // Zeiger inkementieren
            Zeiger_oeffnen := Zeiger_oeffnen + 1;
        END_IF;
        // Flankenhilfsvariable sichern
        FHV_Tuer_geschl := E_Tuer_geschl;
        
            // Zeiger Bereichsüberwachung
        IF Zeiger_schliesen < 1 OR Zeiger_schliesen > 500 THEN
            Zeiger_schliesen := 1;
        END_IF;
        
        // Daten in Ringpuffer schreiben wenn Tür geöffnet wird
        IF NOT E_Tuer_offen AND FHV_Tuer_offen THEN
            tmp_int := READ_CLK(CDT := Puffer_schliesen[Zeiger_schliesen].Zeitstempel);
            Puffer_schliesen[Zeiger_schliesen].Schrittnummer := Schrittnummer;
            Puffer_schliesen[Zeiger_schliesen].A_Tuer_schliesen := A_Tuer_schliesen;  
            Puffer_schliesen[Zeiger_schliesen].A_Tuer_oeffnen := A_Tuer_oeffnen;  
            Puffer_schliesen[Zeiger_schliesen].Tisch_takten := Tisch_takten;  
             // Zeiger inkementieren
            Zeiger_schliesen := Zeiger_schliesen + 1;
        END_IF;
        // Flankenhilfsvariable sichern
        FHV_Tuer_offen := E_Tuer_offen;
    
    END_FUNCTION_BLOCK
    Kannst dir ja mal anschauen.
    mfG Aventinus

  3. #3
    Registriert seit
    22.06.2009
    Ort
    Sassnitz
    Beiträge
    11.184
    Danke
    923
    Erhielt 3.290 Danke für 2.659 Beiträge

    Standard

    Hallo Wurzel2,

    das was Du da in C hast ist kein Ringpuffer sondern eine verkettete Liste.
    Das sind zwei wesentlich verschiedene Varianten zum Speichern von Daten.
    Welche meinst Du tatsächlich?


    Datenstrukturen, welche dynamisch ihre Größe ändern, sind in SPS eher unerwünscht und werden in SCL so gut wie nicht unterstützt und sind nur mit hohem Aufwand "hintenrum" programmierbar. Typisierte Zeiger wie in C gibt es nicht. Auf Elemente einer Struktur mit dynamischer Anfangsadresse symbolisch zugreifen geht nur durch Umkopieren des Speicherbereiches auf eine Struktur mit beim Compilieren bekannter Anfangsadresse.

    Harald
    Es ist immer wieder überraschend, wie etwas plötzlich funktioniert, sobald man alles richtig macht.

    FAQ: Linkliste SIMATIC-Kommunikation über Ethernet

  4. Folgender Benutzer sagt Danke zu PN/DP für den nützlichen Beitrag:

    Wurzel2 (09.01.2015)

  5. #4
    Wurzel2 ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    14.10.2014
    Beiträge
    13
    Danke
    6
    Erhielt 1 Danke für 1 Beitrag

    Standard

    Hi,
    danke für die Antworten. Schade, dass es typisierte Zeiger nicht gibt. Das wollte ich wissen.
    Was ich im Prinzip haben will, ist ein Array mit einer festen Anzahl an Elementen, die nacheinander beschrieben werden sollen. Wenn das letzte Element des Arrays beschrieben wurde, soll als nächstes das erste Element wieder beschrieben werden, usw. Momentan mache ich das so ähnlich wie in Aventinus' Vorschlag. Nur wäre es für mich praktisch über einen Pointer auf die Daten zuzugreifen und nicht über den Index. So könnte ich mir einiges an Umkopieren von Daten sparen. Aber gut, wenn es das nicht gibt, dann muss ich wohl so auskommen
    Geändert von Wurzel2 (09.01.2015 um 07:51 Uhr)

  6. #5
    Registriert seit
    02.06.2006
    Beiträge
    223
    Danke
    7
    Erhielt 41 Danke für 35 Beiträge

    Standard

    Pointer gibt es in Step 7 schon. Aber wie PN/DP schrieb keine verkettete Listen wie in c. Dynamische Array gibt es in Step 7 auch nicht. Daher muss die Größe der betreffenden Struktur vorgegeben sein. Daher ist es eigentlich egal ob man dann über Index oder Pointer arbeitet. Das einzige was man machen kann ist einen neuen DB erzeugen zur Datenspeicherung durch das SPS Programm.
    Aber das habe ich in der Praxis noch nicht gesehen. Wenn halt dann wieder jemand an der Anlage arbeitet hat der halt Unterschiede beim Offline/ Online Bausteinvergleich.

  7. #6
    Registriert seit
    24.04.2013
    Beiträge
    309
    Danke
    23
    Erhielt 160 Danke für 88 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hi

    es gibt in der kleinen Welt der Simatic keine Zeiger und keine dynamische Speicherverwaltung. Kein new, Kein delete. Aber so wie Aventinus vorschlägt, mache ein Feld und verwende die Indices wie Zeiger.

    Jetzt gibt es noch einen Freiheitsgrad. Legst du das Feld statisch im FB an oder global in einem DB?

    Statisch im FB hat den Vorteil, dass du davon mehrere Instanzen haben kannst und jede für sich im Ring herum rotiert. Dadurch, dass du alle Zugriffe im FB kapselst, kommt der Puffer nicht so leicht durcheinander. Nachteil, du musst die Struktur rein/raus kopieren, was entsprechend Zeit kostet, wenn die Struktur groß ist.

    Global im DB hat den Vorteil, dass du jetzt von überall in den Puffer langen kannst, es muss nicht mehr kopiert werden. Aber jetzt wird es schwierig mehrere Puffer zu verwalten. Das erfordert Konvention und noch mehr Disziplin -- geht also in einem Projekt wo mehrere dran arbeiten praktisch schief.

    So Wurzel2 und jetzt kommt es drauf an: Welche CPU soll denn verwendet werden. Bei AS300/400 gibt es so gruselige Sachen wie POINTER und ANY. Mit denen kann ein AWL-Freak tausend tolle Kunststücke machen ... durch brennende Reifen springen und gleichzeitig dem Baby die Windeln wechseln. Bei 1200/1500 kommt statt dessen VARIANT. Auch ein ganz fürchterliches Ding. Auf der einen Seite kann man mit VARIANT mehr machen als mit ANY, auf der anderen Seite darf man es nicht global ablegen.

    Der POINTER ist ein Zeiger, der nicht weiß auf was er zeigt. Also in C sowas wie void*.
    Der ANY ist ein Zeiger, der manchmal weiß auf was er zeigt. Versorgt man einen ANY mit einem ARRAY[ 1..99 ] of BYTE, dann weiß er, dass er auf 99 Bytes zeigt. Aber gerade bei Strukturen vergisst er den Strukturtyp. Versorgt man einen ANY mit einem ARRAY[ 1..99 ] of UDT21, dann weiß er, dass er auf n Bytes zeigt. Wobei n := 99*sizeof(UDT21).
    Der VARIANT ist ein Zeiger, der genau weiß worauf er zeigt. Aber das nutzt so wenig, denn so richtig damit umgehen lassen sie uns nicht. Statt eine vernünftigen Syntax, die sauber zwischen Referenz (C: &) und Dereferenz (C: *) unterscheidet muss man mit einem seltsamen Sack von Funktionen hantieren (die allerdings alle keine Bausteinaufrufe sind sondern vom Compiler in Befehlsfolgen abgebildet werden) und manches funktioniert irritierend implizit.

    Wo soll die Reise denn hingehen?

    'n schön' Tach auch
    HB

Ähnliche Themen

  1. Step 7 Ringpuffer mit SCL
    Von SKNGO im Forum Simatic
    Antworten: 2
    Letzter Beitrag: 28.01.2014, 09:38
  2. Baustein mit SCL programmieren
    Von mr_spooner im Forum Simatic
    Antworten: 10
    Letzter Beitrag: 20.11.2008, 09:19
  3. Kurs Programmieren mit S7-SCL
    Von Grollmus im Forum Werbung und Produktneuheiten
    Antworten: 0
    Letzter Beitrag: 16.09.2008, 09:23
  4. Simatic S7-200 mit S7-SCL programmieren?
    Von Davood im Forum Simatic
    Antworten: 7
    Letzter Beitrag: 19.06.2008, 19:37
  5. Antworten: 3
    Letzter Beitrag: 04.02.2008, 20:09

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •