Vai al contenuto

Problema di casting TO_UINT su array di byte

Home Forum Programmazione IEC 61131 (LogicLab) Problema di casting TO_UINT su array di byte

Stai visualizzando 4 post - dal 1 a 4 (di 4 totali)
  • Autore
    Post
  • #35467
    Anonimo
    Ospite

    Ho la necessità di convertire il contenuto di un array di numeri USINT in numeri a 16 bit UINT. Per comodità ho usato la macro TO_UINT applicandola sul vettore stesso.

    ptrWrd := ADR( buf[13] );
    wrd := TO_UINT( @ptrWrd );

    Ho scoperto che per indici pari (o divisibili per 2) la macro funziona correttamente, ma per indici dispari sbaglia clamorosamente il cast della variabile. Credevo che funzionasse per qualsi varabile in entrata (come menzionato nel manuale) e che quindi si gestisse da sola lo spiazzamento in memoria della variabile d’entrata. E’ un bug ?  Oppure l’array di byte non essendo un numero da luogo a spiazzamenti imprevisti ? Ho risolto in questo modo:

    wrd := TO_UINT(buf[14]); (* MSB *)
    wrd := SHL(wrd, 8);
    wrd := wrd OR TO_UINT(buf[13]); (* LSB *)

    #37930
    Sergio Bertana
    Amministratore del forum

    I nostri sistemi SlimLine sono basati su architettura ARM, questo tipo di architettura vuole che le variabili a due bytes siano allocate ad indirizzi divisibili per 2 e le variabili a 4 bytes siano allocate ad indirizzi divisibili per 4. L’allocazione delle variabili ad indirizzi che non rispondono a queste regole ne rende impossibile l’accesso.

    LogicLab provvede automaticamente ad allocare le variabili seguendo le direttive imposte dalla architettura ARM, ma utilizzando un puntatore su di un array di bytes ecco che sarà il tuo programma a gestire l’indirizzamento e quindi quando ti trovi a puntare indirizzi pari verrà letta corettamente la variabile UINT (Come sequenza di due bytes) mentre se l’indirizzo è dispari la variabile non viene letta correttamente.

    Ma devi anche prestare attenzione all’endiannes dei dati, l’architettura ARM è di tipo Little-Endian, quindi il byte meno significativo si trova ad indirizzo più basso rispetto al byte più significativo. Come vedi dallo screenshot del programma ByteToWord, ho allocato un array di bytes a MX100.0 (In questo modo sono sicuro che sono allocati ad indirizzo pari divisibile per 4).

    Quando il puntatore a WORD punta l’indice 2 dell’array il risultato Result[0] è corretto (Il valore di LSB è l’indirizzo puntato mentre l’MSB è indirizzo+1, Little-Endian). Quando il puntatore a WORD punta l’indice 3 dell’array il risultato Result[1] è errato.

    #38702
    Anonimo
    Inattivo

    Ho il seguente problema. Dopo avere acquisito un valore di tensione attaverso un modulo analogico, mi trovo con la necessità di trasferire questo valore in una word al fine di consentire al PC collegato in Modbus TCP di tenere aggiornata la visualizzazione di questa variabile ed altre varie condizioni

    Mi rendo ovviamente conto che perdo precisione ma in realtà io acquisico un valore in V dal modulo analogico, ad esempio 8,8888888 V. Lo moltiplico in seguito x il mio fattore di conversione pari a 16 ed ottengo 142,222208. se adesso moltiplico questo valore per 100, ottenendo 14222,2208 i primi 5 caratteri 14222 contengono più di quello che mi serve, ma se utilizzo ad esempio la TO_UINT il compilatore mi alza un warning e la word non viene aggiornata. Come posso risolvere il problema ?

    #38703
    Sergio Bertana
    Amministratore del forum

    Quello che fai è corretto, è un normale cast di una variabile, unica accortezza è controllare che il valore massimo che assume la variabile REAL dopo i calcoli non superi il valore che può essere espresso in una variabile UINT (65535).

    Nel tuo caso il massimo può essere 10.0*16.0*100.0=16000.

    Ma se fai tutte le operazioni così come mi scrivi il compilatore non deve dare nessuna warning e la conversione deve funzionare come vedi dal mio screenshot. Non è che la variabile WORD è allocata in memoria ad un indirizzo che non è divisibile per 2.

Stai visualizzando 4 post - dal 1 a 4 (di 4 totali)
  • Devi essere connesso per rispondere a questo topic.