Introduzione
La funzionalità descritte qui sotto sono state aggiunte da RTE >= 34.24 e RC3E >= 33.6.2.
Per utilizzare variabili globali persistenti, è necessario riservare un'area di memoria ritentiva:
•Con la versione RDE> = 33.5.1 in Configurazione / Generale / Memoria / Impostazioni, il parametro "Dimensione massima delle variabili globali" deve essere impostato a 65536.
•Con la versione RDE <33.5.1, è necessario aggiungere le seguenti righe nel file RTE.CFG:
_ifvs 0x22180000 DIM_PV_AREA 65536 _endvs 0x22180000 |
Segnalibri
Accesso ai tipi di dato delle variabili globali
Le variabili globali sono variabili (strutture reali, int o persino) a cui è possibile accedere da ogni task del controllo (task R3, rules, funzioni OB o anche task RPL).
Queste variabili, oltre ad essere "Globali", possono anche essere dichiarate "Persistenti", in questo caso manterranno i loro valori dopo aver spento il controllo.
RTE fornisce alcune funzioni per creare, leggere e scrivere in modo sicuro queste variabili.
Per semplificare l'uso di queste variabili nelle funzioni OB, il compilatore definisce alcuni tipi di dati speciali che inglobano e nascondono le chiamate alle funzioni RTE.
Questi tipi di dati sono: rGlobalInt per variabili intere (int), rGlobalReal per reali (doppie) variabili, rGlobalBool per variabili booleane (bool) e rGlobalString per variabili stringa (char []).
La dichiarazione di queste variabili deve fornire il "Nome globale" della variabile (una stringa che deve essere univoca in tutta l'applicazione e utilizzata come identificatore della variabile globale) e (facoltativamente) alcuni flag che vengono utilizzati quando la variabile globale viene creata (come l'attributo Persistente).
I flag definiti sono:
•gv :: Persistent (0x00000001) La variabile è persistente
•gv :: ForceOverwrite (0x00000002) Forza la scrittura della variabile già esistente
•gv :: NoDataFile (0x00000004) Se non persistente, il file di dati non viene creato
•gv :: WriteValue (0x00000008) Se la variabile è già esistente, sovrascrivi il valore con quello nella cache
Viene inoltre fornito un parametro const stringa opzionale per impostare una password per la scrittura la variabile, senza fornire la password corretta impostata al momento della creazione della variabile, la variabile può solo essere letta.
Esempio
rGlobalInt gvKEY_MODE ("KEY_MODE", gv::NoDataFile); rGlobalReal gvDesFr ("DES_FR", gv::Persistent); rGlobalReal myPrivateVar ("myvar", gv::Persistent, “1234abc”); |
Queste variabili possono essere usate come una qualsiasi variabile 'int' o 'double'
Esempio
if (gvKEY_MODE > 3) gvKEY_MODE = 1; gvDesFr = i_maximum(gvDesFr - frstep, 0.01); |
Non è possibile utilizzare queste variabili con funzioni che portano un puntatore a int o double come parametro, se è necessario passare le variabili per riferimento, utilizzare un riferimento a rGlobalInt o rGlobalReal. Per lo stesso motivo nelle funzioni con argomenti aperti, come printf, devi esplicitamente trasmettere la variabile al tipo base.
È importante in ogni caso ricordare che queste variabili sono solo un'interfaccia alle variabili "vere" globali, quindi viene creato un nuovo collegamento quando viene creata la variabile, e la variabile ha una memoria locale per "memorizzare" il valore della variabile globale.
Per queste ragioni è importante che:
•Per evitare una grande perdita di tempo e memoria, queste variabili devono essere dichiarate nello spazio "globale" (statico) e non dichiarate "localmente" in una funzione.
•(solo per strutture globali) Una variabile diversa deve essere dichiarata per ciascun diverso task che lo utilizza. Significa che, se nell'OB ci sono due funzioni che usano la stessa variabile globale, e una funzione viene chiamata da un'attività e l'altra funzione viene chiamata dalle rule (o da un servizio ob), devono esserci due diverse variabili dichiarate, una per ogni attività.
Uso delle variabili globali come proprietà degli OB
Per definire una variabile globale in un OB, accessibile dall'esterno, come task R3, tools RDE o widget RTM, l'interfaccia dell'OB può dichiarare alcune proprietà virtuali che forniranno l'accesso alle variabili globali interne.
Esistono due modi per farlo:
•Definire le proprietà global o persistent nel file .obs
Esempio
; Class properties properties global real gvr global ro int gvi persistent real nvgvr persistent int nvgvi end_properties |
•Utilizzare alcune macro definite nel compilatore.
Esempio
In .obs file: ; Class properties properties virtual real gvr virtual ro int gvi virtual real nvgvr virtual int nvgvi end_properties
In .h file: // virtual properties OB_DEFINE_GLOBAL_PROPERTY0(double, gvr) OB_DEFINE_GLOBAL_PROPERTY_RO0(int, gvi) OB_DEFINE_GLOBAL_PROPERTY0(double, nvgvr) OB_DEFINE_GLOBAL_PROPERTY0(int, nvgvi)
In .cpp file: // Constructor obclass::obclass (rObOptions *opts): obclass_base(opts), OB_INIT_GLOBAL_PROPERTY0(gvr, gv::NoDataFile), OB_INIT_GLOBAL_PROPERTY_RO0(gvi, gv::NoDataFile), OB_INIT_GLOBAL_PROPERTY0(nvgvr, gv::Persistent), OB_INIT_GLOBAL_PROPERTY0(nvgvi, gv::Persistent) { } OB_IMPLEMENT_GLOBAL_PROPERTY0(obclass, double, gvr) OB_IMPLEMENT_GLOBAL_PROPERTY_RO0(obclass, int, gvi) OB_IMPLEMENT_GLOBAL_PROPERTY0(obclass, double, nvgvr) OB_IMPLEMENT_GLOBAL_PROPERTY0(obclass, int, nvgvi) |
Utilizzando entrambi i metodi, queste proprietà saranno accessibili dall'esterno dell'OB (task R3, strumenti RDE o widget RTM) come:
•obname.gvr
Dentro l'OB saranno utilizzate come:
•gvr
Il 'nome globale', usato per accedere da altri OB o da tasks RPL, sarà:
•“obname_gvr”
Array Global e Persistent
Le variabili globali e persistenti di tipo intero e reale possono anche essere definite come array:
•global real my_vect[10]
In questo caso, la variabile definita in un altro OB deve essere definita come:
•rGlobalRealVect gvMyVect(“obname_my_vect”, 10);
e può essere usata come un vettore di 10 double:
•gvMyVect[i] = gvMyVect[i-1] + 1;
Ricorda che non è un vero array, quindi non puoi passarlo a funzioni che accettano un puntatore (double *), ma è necessario passarlo come riferimento (rGlobalRealVect &).
Utilizzo dei registri come variabili globali
Per facilitare anche l'uso dei registri RTE da un OB, sono stati definiti i seguenti tipi di dato:
•rIntRegVar varname(index); // come R(index)
•rBitRegVar varname(index, bit); // come R(index).(bit)
•rRealRegVar varname(index); // come RR(index)
•rNvIntRegVar varname(index); // come NVR(index)
•rNvRealRegVar varname(index); // come NVRR(index)
•rStringRegVar varname(index); // come SR(index)
•rNvStringRegVar varname(index); // come NVSR(index)
Leggere e scrivere queste variabili sarà lo stesso di leggere e scrivere il registro corrispondente.
Il metodo idx () fornirà l'"indexof" del registro.
Sui registri interi è possibile accedere a un singolo bit anche con i metodi bit () e setBit ().
Esempio
rIntRegVar RHMI_CMD1(1); // come R(1) rBitRegVar bAutoMan (RHMI_CMD1.idx(), 1); // come R(1).1 rRealRegVar rrAG_FR(37); // come RR(37) rStringRegVar srProgramPath(2); // come SR(2) … if (bAutoMan) { bAutoMan = 0; RHMI_CMD1.setBit(5, true); } rrAG_FR = rrAG_FR + 0.1; srProgramPath = “name of program |