Newsgroup: it.hobby.elettronica.digitale
Titolo: Modificare Flags di un registro

Salve a tutti.
Ho un problema banale, ma non riesco a venirne a capo :
Sto usando l'MCC18 come compilatore C.
Vorrei fare una cosa di questo tipo :
data la variabile globale "GlbStatusDisplay" e un Flag tipo
"FLAG_BLINK_ON", vorrei fare questo :
GlbStatusDisplay.FLAG_BLINK_ON = 1;
Ho sbirciato negli headers del compilatore per vedere come funziona
per es. "PORTAbits" e ho visto che va usata una "struct", ma non mi e'
per niente chiaro il funzionamento.
Ho visto anche su un manuale di C ansi come si comportano le struct,
ma sembra che in ambiente MCC18 non abbia niente a che fare oppure non
riesco a cogliere il succo della questione a causa dell'inesperienza.
.
Qualche link o qualche suggerimento?
Grazie anticipatamente.
Massimo

IW0HKG Massimo ha scritto:

struct
{
   unsigned char bFlInt          : 1;
//  unsigned char bFlDebug        : 1;
//  unsigned char ecc.
} flag;
Poi, nelle funzioni, puoi usare, ad esempio :
flag.bFlInt = 1;
Se non ti funziona, non e' colpa dell'implementazione della 
struttura ma di qualcos'altro.
ciao
Angelo


Si chiamano bitfield, fanno parte delle struct,
e sono indicati con i due punti ":".
E' una sintassi del C standard e molto utile nella
programmazione con forte interazione con l'hardware,
pero' i vari compilatori fanno un po' come vogliono.
Cerca nel manuale del tuo.

 Cerca nel manuale del tuo.
Su questo concordo!
Ciao!
Marco / iw2nzm

 if (g_uiFlags & (1 << FLAG1)) ... // per test
A parte per il "clear" e' esattamente quello che ho fatto fino a ieri,
ma
mi sembrava una pratica da "smanettone" e, quindi, per nulla
professionale.
Pero', da quello che ho letto dai tuoi precedenti post, mi sembri
abbastanza
ossessionato dalla ricerca della forma piu' elegante e compatta di
scrivere codice.
Mi sento quindi rincuorato di aver pensato ad una soluzione uguale
alla tua.
In particolare, quello che mi preoccupava e che "(pippo & 128)"
sarebbe stato sempre piu' veloce di
"(pippo & (1 << 7) )" a livello di esecuzione del programma.
Se c'e' questo rischio di spreco di risorse utilizzando i "bit fields"
con certi compilatori, tornero'
alla vecchia maniera (almeno con i PIC).
Comunque la "struct" dovevo impararla lo stesso (gia' la conoscevo, ma
mi ricordavo che si implementasse in modo diverso sui PC).
Ringrazio te e gli altri per le preziose informazioni e gli esempi (ho
risolto il problema).
Vado a vedermi le "union"......
Ciao
Massimo IW0HKG

 "(pippo & (1 << 7) )" a livello di esecuzione del programma.
Ho scritto una fesseria. Una volta compilati i due esempi sono
equivalenti in run-time.


Esatto.
Il secondo esempio poi è molto più leggibile, si vede subito che si 
parla del bit 7.
Tempo fa avevo postato delle macro per rendere più facile il lavoro in 
questione, te le riallego se vuoi darci un'occhiata:
/* Ritorna lo stato di bit in data */
#define GET_BIT(data, bit) ((data) & (1 << (bit)))
/* Setta il bit in data */
#define SET_BIT(data, bit) ((data) |= (1 << (bit)))
/* Resetta il bit in data */
#define RESET_BIT(data, bit) ((data) &= ~(1 << (bit)))
-- 
  _|/ Francesco Sacchi - Develer S.r.l., R&D dept.
   |\ 
http://www.develer.com/
 - 
http://www.bertos.org

 alla vecchia maniera (almeno con i PIC).
Come dico sempre io i bitfields sono "evil", sembrano carini ed 
eleganti ma hanno dei problemi, soprattutto di portabilità del codice.
Invece &, |, ~ e ^ funzionano sempre dappertutto, sono più generali 
anche se più difficili da capire all'inizio.


IW0HKG Massimo ha scritto:

Infatti, ho provato e viene tradotto in assembler con il set 
bit e clear bit.
Con il C18 puoi usare tranquillamente le structures e 
flag.pippo = 1.
ciao
Angelo

 anche se più difficili da capire all'inizio.
Sei molto ottimista sulle capacità degli implementatori. Non sostengo
minimamente che tu sia troppo ottimista. Basta assicurarsi di guardar bene
l'assembler generato.


Se ti riferisci agli implementatori dei compilatori, posso confermare
che sono abbastanza bravi. Su AVR, per esempio, il gcc è in grado di
usare l'istruzione assembly cbi/sbi quando il registro lo permette e
fornisci una costante:
#define BUZZER_BIT BV(PE3)
PORTE |= BUZZER_BIT;
in assembly diventa:
0022 1B9A	sbi 35-0x20,3    ;  26  *sbi    [length = 1]
(ATMega64)


 fornisci una costante:
Esattamente. Basta solo essersene accertati, come hai fatto tu.