ifachsoftware Inserito: 16 marzo 2017 Segnala Inserito: 16 marzo 2017 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
STEU Inserita: 16 marzo 2017 Segnala Inserita: 16 marzo 2017 Non ho provato ad utilizzarli , ho guardato il codice del primo, sei sicuro che funzioni?
STEU Inserita: 17 marzo 2017 Segnala Inserita: 17 marzo 2017 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.
ifachsoftware Inserita: 20 marzo 2017 Autore Segnala Inserita: 20 marzo 2017 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 Se qualcuno volesse realizzare moltiplicazione e divisione e condividerle , sarebbero bene accette , nel contempo ringrazio Steu
STEU Inserita: 20 marzo 2017 Segnala Inserita: 20 marzo 2017 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
stilnovo Inserita: 26 marzo 2017 Segnala Inserita: 26 marzo 2017 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 ?
ifachsoftware Inserita: 5 aprile 2017 Autore Segnala Inserita: 5 aprile 2017 Le operazioni con DW in SCL non sono ammesse. Appena trovo un poco di tempo testo le tua funzione. Per ora grazie
stilnovo Inserita: 8 aprile 2017 Segnala Inserita: 8 aprile 2017 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
Messaggi consigliati
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 accountAccedi
Hai già un account? Accedi qui.
Accedi ora