Step 7 Ringpuffer, Schieberegister Schwiriegkeiten

ChopinJunkie

Level-1
Beiträge
18
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich habe die hier im Forum diskutierten Themen bezüglich indirekter Adressierung gelesen und anhand der Anforderungen meiner Aufgabenstellung mir einen eigenen Funktionbaustein selbst gebastelt.
Nun funktioniert das gebrauchte Eintragen der Werte in einen DB mit einem Array von DINT
hier ist der Code dafür
Code:
      U     #bit_1
      UN    #bErase

      AUF   "Register_Puffer"           //schlägt einen DB mit einem ARRAY[1..20] of DINT auf
      L     #iAnzahl_Werte              //lädt aktuellen index, typ INT
      T     #dIndex

      L     #dIndex
      L     4                           //bildet ein Integer, das vielfach einem Doppelwort ist
      *D    
      SLD   3                           //bildet einen Pointer
      LAR1                              //speichert ins Adressregister 1

      L     #dTemp_data_in              //lädt den Wert vom typ DINT
      T     DBD [AR1,P#0.0]             //greift auf den DB ARRAY zu, schreibt den Wert unter Adresse des Pointers

Leider habe ich jetzt Probleme mit dem Schieben der Werte in DB Register, wenn ich den allerersten Wert löschen möchte. Mit diesem Code geht der CPU einfach ins STOP und verweist im Diagnosepuffer auf die letzte Zeile im oberen Code, nämlich wo der erste Schreibzugriff auf DB gescheht

Code:
     U     #bErase
//iAnzahl_Werte beinhaltet die nummer des letzten eintrages,
// dies kann auf seine adresse verweisen
      AUF   "Register_Puffer"
      L     #iAnzahl_Werte

//wir brauchen aber an der Stelle den zweitgeschriebenen Wert in der Tabelle
      L     1
      -I    
      T     #iDekrement

anf:  NOP   0
      L     #iAnzahl_Werte
      L     #iDekrement
      -I    
      T     #dIndex                     //schreibt die nummer des allerersten Eintrages

      L     #dIndex
      L     4
      *D    
      SLD   3                           //bildet einen Pointer
      LAR1                              //speichert ins Adressregister 1

      L     DBD [AR1,P#4.0]             //greift auf den nächsten nach allerersten Element zu
      T     DBD [AR1,P#0.0]             //überschreibt den Allerersten mit nachfolgendem Element

//hier ist eine Verschiebung des verweisenden Pointers gebraucht
      L     #iDekrement
      L     1
      -I    
      T     #iDekrement
      L     0
      >=I   
      SPB   anf
      SPA   ende

//dekremintiert den Zähler für die anwesenden Einträge in der Tabelle um EINS
ende: NOP   0
      L     #iAnzahl_Werte
      L     1
      -I    
      T     #iAnzahl_Werte

Könntet ihr mir, bitte erklären was ich so falsch mache? Oder was eurer Meinung nach bei mir falsch sein könnte?
Ich gehe selbstständig nicht mehr weiter :|:cry:
 
Hallo ChopinJunkie,

prüf' doch mal Dein #iAnzahl_Werte. Ich vermute es ist kleiner Null.
Wenn Du eine Prüfung auf kleiner Null am Ende Deines 2. Codeschnipsels anfügst
und bei <0 das #iAnzahl_Werte auf 0 setzt, soll es funktionieren.

Grüße
Gebs
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo ChopinJunkie,

prüf' doch mal Dein #iAnzahl_Werte. Ich vermute es ist kleiner Null.
Wenn Du eine Prüfung auf kleiner Null am Ende Deines 2. Codeschnipsels anfügst
und bei <0 das #iAnzahl_Werte auf 0 setzt, soll es funktionieren.

Grüße
Gebs

Hallo Gebs,

danke für deinen Hinweis auf
Code:
      L     #iAnzahl_Werte
      L     0
      <I    
      L     0
      T     #iAnzahl_Werte

CPU geht jetzt nicht mehr direkt ins STOP. ABER... iAnzahl_Werte wird offensichtlich ständig mit Null beschrieben, was im Endeffekt einen Fehlschlag beim Befüllen von Array mit Werten verursacht, da keiner Pointer gebildet wird. Die Ursache dafür, meiner Meinung nach liegt am absoluten Sprung auf "ende"
 
Zuletzt bearbeitet:
In Step7 gibt es nur wenige Anweisungen, die VKE-abhängig ausgeführt werden (S, R, BEB, CC, SPB, SPBN, ...). Die meisten Anweisungen werden unabhängig vom VKE immer ausgeführt.
Wenn Programmcode nichts bewirken soll dann darf man ihn nicht ausführen --> dann muß man ihn überspringen:
Code:
      U     #bit_1
      UN    #bErase
      [COLOR="#FF0000"]SPBN  end1[/COLOR]

      L     #iAnzahl_Werte              //lädt aktuellen index, typ INT
      T     #dIndex

      L     #dIndex
      L     4                           //bildet ein Integer, das vielfach einem Doppelwort ist
      *D    
      SLD   3                           //bildet einen Pointer
      LAR1                              //speichert ins Adressregister 1

      L     #dTemp_data_in              //lädt den Wert vom typ DINT
      [COLOR="#FF0000"]AUF   "Register_Puffer"[/COLOR]           //schlägt einen DB mit einem ARRAY[1..20] of DINT auf
      T     DBD [AR1,P#0.0]             //greift auf den DB ARRAY zu, schreibt den Wert unter Adresse des Pointers

[COLOR="#FF0000"]end1: SET[/COLOR]
Die AUF-Anweisung gehört so nahe wie möglich zu der Anweisung, wo auf den geöffneten DB zugegriffen wird, um sicherzustellen, daß nicht zwischendurch versehentlich ein anderer DB geöffnet wird.

Code:
      U     #bErase
      [COLOR="#FF0000"]SPBN  end2[/COLOR]
//iAnzahl_Werte beinhaltet die nummer des letzten eintrages,
// dies kann auf seine adresse verweisen
      L     #iAnzahl_Werte

//wir brauchen aber an der Stelle den zweitgeschriebenen Wert in der Tabelle
[COLOR="#FF0000"]//Vorsicht! wenn #iAnzahl_Werte = 0 dann gibt es wohl keinen "zweitgeschriebenen Wert", #iDekrement wird -1, ist das richtig so???[/COLOR]
      L     1
      -I    
      T     #iDekrement

      [COLOR="#FF0000"]AUF   "Register_Puffer"           //nahe am Zugriff, aber noch vor der Schleife[/COLOR]
anf:  NOP   0
      L     #iAnzahl_Werte
      L     #iDekrement
      -I    
      T     #dIndex                     //schreibt die nummer des allerersten Eintrages

      L     #dIndex
      L     4
      *D    
      SLD   3                           //bildet einen Pointer
      LAR1                              //speichert ins Adressregister 1

      L     DBD [AR1,P#4.0]             //greift auf den nächsten nach allerersten Element zu
      T     DBD [AR1,P#0.0]             //überschreibt den Allerersten mit nachfolgendem Element

//hier ist eine Verschiebung des verweisenden Pointers gebraucht
      L     #iDekrement
      L     1
      -I    
      T     #iDekrement
      SPPZ  anf                         [COLOR="#FF0000"]//hat den gleichen Effekt wie die nachfolgenden 4 Zeilen: springe zu anf wenn Ergebnis >= 0[/COLOR]
[COLOR="#FF0000"]//      L     0
//      >=I   
//      SPB   anf
//      SPA   ende                        // <-- SPA ist überflüssig[/COLOR]

//dekremintiert den Zähler für die anwesenden Einträge in der Tabelle um EINS
ende: NOP   0                           [COLOR="#FF0000"]// <-- Marke und NOP ist überflüssig[/COLOR]
      L     #iAnzahl_Werte
      L     1
      -I    
[COLOR="#FF0000"]      SPPZ  TIAW                        //springe wenn Ergebnis >= 0
      L     0                           //bei Ergebnis < 0 durch 0 ersetzen
TIAW:[/COLOR] T     #iAnzahl_Werte

[COLOR="#FF0000"]end2: SET[/COLOR]
Statt
Tip: Als Füll/Dummy-Anweisung an einer Sprungmarke ist eine SET-Anweisung ein kleines bischen besser geeignet als eine NOP-Anweisung (ist kürzer und garantiert eine VKE-Begrenzung).
An die Sprungmarke kann aber auch gleich eine sinnvolle Anweisung geschrieben werden, wie z.B. "anf: L #iAnzahl_Werte"

Harald
 
Zurück
Oben