Vai al contenuto
PLC Forum


DWORD


ifachsoftware

Messaggi consigliati

ifachsoftware

Buongiorno a tutti , ho notato che i plc Siemens supportano le DWORD solo come DINT per tutte le operazioni matematiche e di comparazione. 

La differenza tra i due tipi di dati è la gestione del segno.

Le DWORD essendo unsigned dovrebbero lavorare tra 0 e 4294967295 , mentre i DINT lavorano tra -2147483648 e 2147483647.

Nel mio caso volevo realizzare un contatore e con i comandi standard sono stato costretto a limitare la gestione al range della parte positiva dei DINT.

Per superare questo clamoroso limite ho scritto delle funzioni in AWL che allego , invitandomi a dare suggerimenti e a completarle.

 

MINORE

 

FUNCTION "DW_A<B" : Bool
TITLE = DWORD A < DWORD B
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : CR
VERSION : 0.1
   VAR_INPUT 
      A : DWord;
      B : DWord;
   END_VAR

   VAR_TEMP 
      TmpA : DInt;
      TmpB : DInt;
   END_VAR


BEGIN
NETWORK
TITLE = 
      L #A;
      AD DW#16#0FFF_FFFF;
      T #TmpA;

      L #B;
      AD DW#16#0FFF_FFFF;
      T #TmpB;

      L #TmpA;
      L #TmpB;
      <D;
      JC AAA;

// CHECK LAST BYTE

      L #A;
      AD DW#16#F000_0000;
      SLD 28;
      T #TmpA;


      L #B;
      AD DW#16#F000_0000;
      SLD 28;
      T #TmpB;


      L #TmpA;
      L #TmpB;
      <D;
      JC AAA;

      SET;
      R #"DW_A<B";
      BE;

AAA:      SET;
      S #"DW_A<B";

      BE;
END_FUNCTION

 

MAGGIORE

 

FUNCTION "DW_A>B" : Bool
TITLE = DWORD A > DWORD B
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : CR
VERSION : 0.1
   VAR_INPUT 
      A : DWord;
      B : DWord;
   END_VAR

   VAR_TEMP 
      TmpA : DInt;
      TmpB : DInt;
   END_VAR


BEGIN
NETWORK
TITLE = 
      L #A;
      AD DW#16#0FFF_FFFF;
      T #TmpA;

      L #B;
      AD DW#16#0FFF_FFFF;
      T #TmpB;

      L #TmpA;
      L #TmpB;
      >D;
      JC AAA;

// CHECK LAST BYTE

      L #A;
      AD DW#16#F000_0000;
      SLD 28;
      T #TmpA;


      L #B;
      AD DW#16#F000_0000;
      SLD 28;
      T #TmpB;


      L #TmpA;
      L #TmpB;
      >D;
      JC AAA;

      SET;
      R #"DW_A>B";
      BE;

AAA:      SET;
      S #"DW_A>B";

      BE;
END_FUNCTION

 

SOMMA

 

FUNCTION "DW_SUM" : DWord
TITLE = DWORD A < DWORD B
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : CR
VERSION : 0.1
   VAR_INPUT 
      A : DWord;
      B : DWord;
   END_VAR

   VAR_TEMP 
      TmpA : DInt;
      TmpB : DInt;
      SumR : DInt;
      SumL : DInt;
   END_VAR


BEGIN
NETWORK
TITLE = 
// SUM LOW PART

      L #A;
      AD DW#16#0000_FFFF;
      T #TmpA;

      L #B;
      AD DW#16#0000_FFFF;
      T #TmpB;

      L #TmpA;
      L #TmpB;
      +D;
      T #SumR;

// Sum High Part

      L #A;
      AD DW#16#FFFF_0000;
      SRD 16;
      T #TmpA;

      L #B;
      AD DW#16#FFFF_0000;
      SRD 16;
      T #TmpB;

      L #TmpA;
      L #TmpB;
      +D;
      T #SumL;

// GET REMINDER

      L #SumR;
      AD DW#16#FFFF_0000;
      SRD 16;
      T #TmpA;

      L #TmpA;
      L 0;
      >D;
      JC REM;

      JU aa;

REM:      L #TmpA;
      L #SumL;
      +D;
      T #SumL;

aa:      L #SumL;
      SLD 16;
      T #SumL;

      L #SumR;
      AD DW#16#0000_FFFF;
      T #SumR;

      L #SumR;
      L #SumL;
      OD;
      T #DW_SUM;

      BE;
END_FUNCTION

 

Cattura.PNG

Link al commento
Condividi su altri siti


Vedo dagli screenshoot che funziona. Tieni presente che non ho mai aperto TIA PORTAL , ti faccio una domanda :

hai provao con A= EFFFFFFF   B= FFFFFFFF

 

Io ho provato con step 7 e con i valori sopra indicati non funziona , ripeto non conosco assolutamente TIA Portal e ho visto la riga del tuo sorgente

{ S7_Optimized_Access := 'FALSE' }

che probabilmente è la spiegazione del non corretto funzionamento sul mio PC.

 

 

Link al commento
Condividi su altri siti

ifachsoftware

Ciao , hai ragione , ho caricato la versione precedente e chiedo venia.

Carico ora le versioni corrette con relativi esempi :

 

<

FUNCTION "DW<" : Bool
TITLE = DWORD A < B
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : CR
VERSION : 0.1
   VAR_INPUT 
      A : DWord;
      B : DWord;
   END_VAR

   VAR_TEMP 
      TmpA : DInt;
      TmpB : DInt;
   END_VAR


BEGIN
NETWORK
TITLE = 
      L #A;
      AD DW#16#0FFF_FFFF;
      T #TmpA;

      L #B;
      AD DW#16#0FFF_FFFF;
      T #TmpB;

      L #TmpA;
      L #TmpB;
      <D;
      JC AAA;

// CHECK LAST BYTE

      L #A;
      AD DW#16#F000_0000;
      SRD 28;
      T #TmpA;


      L #B;
      AD DW#16#F000_0000;
      SRD 28;
      T #TmpB;


      L #TmpA;
      L #TmpB;
      <D;
      JC AAA;

      SET;
      R #"DW<";
      BE;

AAA:      SET;
      S #"DW<";
      BE;
END_FUNCTION

>

FUNCTION "DW>" : Bool
TITLE = DWORD A > B
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : CR
VERSION : 0.1
   VAR_INPUT 
      A : DWord;
      B : DWord;
   END_VAR

   VAR_TEMP 
      TmpA : DInt;
      TmpB : DInt;
   END_VAR


BEGIN
NETWORK
TITLE = 
      L #A;
      AD DW#16#0FFF_FFFF;
      T #TmpA;

      L #B;
      AD DW#16#0FFF_FFFF;
      T #TmpB;

      L #TmpA;
      L #TmpB;
      >D;
      JC AAA;

// CHECK LAST BYTE

      L #A;
      AD DW#16#F000_0000;
      SRD 28;
      T #TmpA;


      L #B;
      AD DW#16#F000_0000;
      SRD 28;
      T #TmpB;


      L #TmpA;
      L #TmpB;
      >D;
      JC AAA;

      SET;
      R #"DW>";
      BE;

AAA:      SET;
      S #"DW>";

      BE;
END_FUNCTION

>=

FUNCTION "DW>=" : Bool
TITLE = DWORD A >= B
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : CR
VERSION : 0.1
   VAR_INPUT 
      A : DWord;
      B : DWord;
   END_VAR

   VAR_TEMP 
      TmpA : DInt;
      TmpB : DInt;
   END_VAR


BEGIN
NETWORK
TITLE = 
      L #A;
      AD DW#16#0FFF_FFFF;
      T #TmpA;

      L #B;
      AD DW#16#0FFF_FFFF;
      T #TmpB;

      L #TmpA;
      L #TmpB;
      <D;
      JC AAA;

// CHECK LAST BYTE

      L #A;
      AD DW#16#F000_0000;
      SRD 28;
      T #TmpA;


      L #B;
      AD DW#16#F000_0000;
      SRD 28;
      T #TmpB;


      L #TmpA;
      L #TmpB;
      <D;
      JC AAA;

      SET;
      S #"DW>=";
      BE;

AAA:      SET;
      R #"DW>=";

      BE;
END_FUNCTION

<=

FUNCTION "DW<=" : Bool
TITLE = DWORD A <= B
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : CR
VERSION : 0.1
   VAR_INPUT 
      A : DWord;
      B : DWord;
   END_VAR

   VAR_TEMP 
      TmpA : DInt;
      TmpB : DInt;
   END_VAR


BEGIN
NETWORK
TITLE = 
      L #A;
      AD DW#16#0FFF_FFFF;
      T #TmpA;

      L #B;
      AD DW#16#0FFF_FFFF;
      T #TmpB;

      L #TmpA;
      L #TmpB;
      >D;
      JC AAA;

// CHECK LAST BYTE

      L #A;
      AD DW#16#F000_0000;
      SRD 28;
      T #TmpA;


      L #B;
      AD DW#16#F000_0000;
      SRD 28;
      T #TmpB;


      L #TmpA;
      L #TmpB;
      >D;
      JC AAA;

      SET;
      S #"DW<=";
      BE;

AAA:      SET;
      R #"DW<=";

      BE;
END_FUNCTION

Somma

FUNCTION "DW+" : DWord
TITLE = DWORD C = A + B
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : CR
VERSION : 0.1
   VAR_INPUT 
      A : DWord;
      B : DWord;
   END_VAR

   VAR_TEMP 
      TmpA : DInt;
      TmpB : DInt;
      SumR : DInt;
      SumL : DInt;
   END_VAR


BEGIN
NETWORK
TITLE = 
// SUM LOW PART

      L #A;
      AD DW#16#0000_FFFF;
      T #TmpA;

      L #B;
      AD DW#16#0000_FFFF;
      T #TmpB;

      L #TmpA;
      L #TmpB;
      +D;
      T #SumR;

// Sum High Part

      L #A;
      AD DW#16#FFFF_0000;
      SRD 16;
      T #TmpA;

      L #B;
      AD DW#16#FFFF_0000;
      SRD 16;
      T #TmpB;

      L #TmpA;
      L #TmpB;
      +D;
      T #SumL;

// GET REMINDER

      L #SumR;
      AD DW#16#FFFF_0000;
      SRD 16;
      T #TmpA;

      L #TmpA;
      L 0;
      >D;
      JC REM;

      JU aa;

REM:      L #TmpA;
      L #SumL;
      +D;
      T #SumL;

aa:      L #SumL;
      SLD 16;
      T #SumL;

      L #SumR;
      AD DW#16#0000_FFFF;
      T #SumR;

      L #SumR;
      L #SumL;
      OD;
      T #"DW+";

      BE;
END_FUNCTION

Sottrazione

FUNCTION "DW-" : DWord
TITLE = DWORD C = A - B
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : CR
VERSION : 0.1
   VAR_INPUT 
      A : DWord;
      B : DWord;
   END_VAR

   VAR_TEMP 
      TmpA : DInt;
      TmpB : DInt;
      SubR : DInt;
      SubL : DInt;
   END_VAR


BEGIN
NETWORK
TITLE = 
// SUBTRACT LOW PART

      L #A;
      AD DW#16#0000_FFFF;
      T #TmpA;

      L #B;
      AD DW#16#0000_FFFF;
      T #TmpB;

      L #TmpA;
      L #TmpB;
      -D;
      T #SubR;

// SUBTRACT HIGH PART

      L #A;
      AD DW#16#FFFF_0000;
      SRD 16;
      T #TmpA;

      L #B;
      AD DW#16#FFFF_0000;
      SRD 16;
      T #TmpB;

      L #TmpA;
      L #TmpB;
      -D;
      T #SubL;

// GET REMINDER

      L #SubR;
      AD DW#16#FFFF_0000;
      SRD 16;
      T #TmpA;

      L #TmpA;
      L 0;
      >D;
      JC REM;

      JU aa;

REM:      L #TmpA;
      L #SubL;
      +D;
      T #SubL;

aa:      L #SubL;
      SLD 16;
      T #SubL;

      L #SubR;
      AD DW#16#0000_FFFF;
      T #SubR;

      L #SubR;
      L #SubL;
      OD;
      T #"DW-";

      BE;
END_FUNCTION

 

Esempio1.PNG

Esempio2.PNG

Esempio3.PNG

Esempio4.PNG

Se qualcuno volesse realizzare moltiplicazione e divisione e condividerle , sarebbero bene accette , nel contempo ringrazio Steu

Link al commento
Condividi su altri siti

Ciao premetto che ancora non ho testato il programma, e ho guardato solamente il primo e forse non è la versione che gira nei screen shoot seguenti.

Credo che sia giusto testare prima i bit più significativi e poi gli altri

scusa la scocciatura

 

Link al commento
Condividi su altri siti

Hai scritto una tonnellata di SW per risolvere un problema che forse nemmeno c'è.

Infatti nulla vieta di utilizzare le operazioni di aritmetiche con le DWORD, e il risultato fa esattamente quello che chiedi, ovvero

DW#80000000

+

DW#10000000

=

DW#90000000

 

Per i confronti invece è sufficiente utlizzare gli operatori disponibili per gli i DINT, con l'accortezza di invertire il risultato quando necessario.

Vedi codice seguente:

FUNCTION FC 1 : VOID
TITLE =
VERSION : 0.1


VAR_INPUT
  Value1 : DWORD ;	
  Value2 : DWORD ;	
END_VAR
VAR_OUTPUT
  Minore : BOOL ;	
  Uguale : BOOL ;	
  Maggiore : BOOL ;	
END_VAR
VAR_TEMP
  Value1Negativo : BOOL ;	
  Value2Negativo : BOOL ;	
  CfrIntermedio : BOOL ;	
END_VAR
BEGIN
NETWORK
TITLE =#Value1Negativo

      L     #Value1; 
      L     0; 
      <D    ; 
      =     #Value1Negativo; 
NETWORK
TITLE =#Value2Negativo

      L     #Value2; 
      L     0; 
      <D    ; 
      =     #Value2Negativo; 
NETWORK
TITLE =#CfrIntermedio

      L     #Value1; 
      L     #Value2; 
      <D    ; 
      =     #CfrIntermedio; 
NETWORK
TITLE =Res #Uguale

      L     #Value1; 
      L     #Value2; 
      ==D   ; 
      =     #Uguale; 
NETWORK
TITLE =Res #Minore

      U(    ; 
      U(    ; 
      UN    #Value1Negativo; 
      UN    #Value2Negativo; 
      O     ; 
      U     #Value1Negativo; 
      U     #Value2Negativo; 
      )     ; 
      U     #CfrIntermedio; 
      O     ; 
      U(    ; 
      UN    #Value1Negativo; 
      U     #Value2Negativo; 
      O     ; 
      U     #Value1Negativo; 
      UN    #Value2Negativo; 
      )     ; 
      UN    #CfrIntermedio; 
      )     ; 
      UN    #Uguale; 
      =     #Minore; 
NETWORK
TITLE =Res #Maggiore

      UN    #Uguale; 
      UN    #Minore; 
      =     #Maggiore; 
END_FUNCTION

Ti ho convinto ? ;)

Link al commento
Condividi su altri siti

  • 2 weeks later...
ifachsoftware

Le operazioni con DW in SCL non sono ammesse.

Appena trovo un poco di tempo testo le tua funzione.

Per ora grazie

Link al commento
Condividi su altri siti

Con Simatic "Classic" lo sono, con TIA Portal non ho provato.

Le seguenti variabili Pippox sono tutte DWORD. Basta solo dichiarare esplicitamente la conversione a DINT.

Il risultato dell'operazione è sempre un numero da 0 a 2^32-1. Per le operazioni di confronto, ovviamente non puoi affidarti direttamente a quelle di sistema, ma attuare uno stratagemma tipo quello che ti ho suggerito sopra.

Pippo3 := DINT_TO_DWORD(DWORD_TO_DINT(Pippo1) + DWORD_TO_DINT(Pippo2));

 

Ciao

Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...