Go Down

Topic: Topic permanente di programmazione newbie (Read 128334 times) previous topic - next topic

astrobeed


mi servono 6 valori per le possibili combinazioni di EFuse e Tipo di Programmazione;


Per gestire in modo semplice il quarto byte che fa da bit flag ti consiglio l'uso di una unione contenente una variabile unsigned char e una struttura bit fields di otto elementi.
In pratica carichi sulla variabile unsigned char il quarto byte dopo di che puoi accedere direttamente ai singoli flag tramite nomi mnemonici, ti allego un semplice sketch di esempio dove viene creata la struttura che ti dico, i vari nomi li puoi cambiare come ti pare, e dopo aver caricato sulla variabile principale un valore binario vengono stampati sul serial monitor i singoli bit che lo costituiscono:

Code: [Select]

struct Bit_Fields {
        unsigned char dato1:1;
        unsigned char dato2:1;
        unsigned char dato3:1;
        unsigned char dato4:1;
        unsigned char dato5:1;
        unsigned char dato6:1;
        unsigned char dato7:1;
        unsigned char dato8:1;
                  };

union bit_fields {
       unsigned char AllBits;
       struct Bit_Fields BtF;
                 } AuxData;


void setup()
{

  Serial.begin(9600);

  AuxData.AllBits = 0b11001100;

  Serial.print("Bit 1 = "); 
  Serial.println(AuxData.BtF.dato1, DEC);

  Serial.print("Bit 2 = "); 
  Serial.println(AuxData.BtF.dato2, DEC);

  Serial.print("Bit 3 = "); 
  Serial.println(AuxData.BtF.dato3, DEC);

  Serial.print("Bit 4 = "); 
  Serial.println(AuxData.BtF.dato4, DEC);

  Serial.print("Bit 5 = "); 
  Serial.println(AuxData.BtF.dato5, DEC);

  Serial.print("Bit 6 = "); 
  Serial.println(AuxData.BtF.dato6, DEC);

  Serial.print("Bit 7 = "); 
  Serial.println(AuxData.BtF.dato7, DEC);

  Serial.print("Bit 8 = "); 
  Serial.println(AuxData.BtF.dato8, DEC);

  Serial.print("AllBits "); 
  Serial.println(AuxData.AllBits, HEX);

}


void loop()
{

}
Scientia potentia est

menniti

:smiley-eek: Forse se lo provo in uno sketch da solo ci capisco qualcosa, ciò che non riesco proprio ad immaginare è come collegare tutto ciò al 4° byte del terzo array :smiley-red: comunque facciamo un passo per volta, stasera provo, una volta che mi sono fatta l'idea certa del funzionamento vedremo di capire come collegare un valore del 4° bytre al corrispondente valore di questa struttura. Grazie!

astrobeed


:smiley-eek: Forse se lo provo in uno sketch da solo ci capisco qualcosa, ciò che non riesco proprio ad immaginare è come collegare tutto ciò al 4° byte del terzo array :smiley-red:


Semplicemente caricando il suo valore in "AuxData.AllBits", p.e. "AuxData.AllBits = Fuses [11] [4]", cioè carichi il 4 byte dell'undicesimo modello di micro nella varabile AllBits, da questo momento in poi puoi accedere a i singoli flag con i loro nomi mnemonici, p.e. per verificare il terzo flag:

"if (AuxData.BtF.dato3 == 1) quellochedevifare();"

Scientia potentia est

menniti



:smiley-eek: Forse se lo provo in uno sketch da solo ci capisco qualcosa, ciò che non riesco proprio ad immaginare è come collegare tutto ciò al 4° byte del terzo array :smiley-red:


Semplicemente caricando il suo valore in "AuxData.AllBits", p.e. "AuxData.AllBits = Fuses [11] [4]", cioè carichi il 4 byte dell'undicesimo modello di micro nella varabile AllBits, da questo momento in poi puoi accedere a i singoli flag con i loro nomi mnemonici, p.e. per verificare il terzo flag:

"if (AuxData.BtF.dato3 == 1) quellochedevifare();"

Fantastico! questa tecnica mi evita di dover mettere un bordello di "if" per convertire gli 8 valori del 4° byte (anche se per ora ne uso solo 6) in una coppia di valori che rappresentano il tipo di programmazione e lo status dell'EFuse. Un approfondimento: ma io posso estrapolare dal byte due valori invece di uno? Spiego:
0x01 per me significa EFuse = "No" e mode = "HVSP"
0x02 EFuse="No" e mode = "HVPP"
ecc.
come faccio ad assegnare due variabili distinte con questa tecnica?

leo72

Io avrei fatto diversamente. Bastava usare la funzione predefinita di Arduino bitRead:
Per accedere ad un singolo bit basta fare
Code: [Select]
bitRead(dato, num_bit).

Quindi
Code: [Select]
for (byte i=0; i<8; i++) {
  Serial.print("Bit ");
  Serial.print(i, DEC);
  Serial.print(": ");
  Serial.println(bitRead(dato,i), DEC);
}




astrobeed


Io avrei fatto diversamente. Bastava usare la funzione predefinita di Arduino bitRead:


Corretto, però la BitRead in realtà è questo:

Code: [Select]

#define bitRead(value, bit) (((value) >> (bit)) & 0x01)


Ogni volta che la vai ad usare in realtà viene eseguito uno shift della variabile e una mascheratura, inoltre anche se ti crei delle #define con nomi mnemonici dei vari campi assegnandoli al relativo bit, p.e. #define HVPP 3, quando vai scrivere il software il tutto diventa meno leggibile dell'uso diretto di un nome mnemonico.
Non ultimo il modo con cui vengono trattati i dati dalle strutture e unioni è decisamente più efficace del fare uno shift e una maschera, in pratica il codice compilato risulta più compatto e impiega meno cicli macchina, che poi queste sono finezze da programmazione avanzata è vero, nel nostro caso non cambia nulla se per accedere al dato ci vogliono solo tre cicli macchina invece di cinque, però non è male se si impara ad usare tutti gli strumenti del C e unioni/strutture sono tra quelli più potenti che ci vengono messi a disposizione.

Scientia potentia est

menniti

forse è meglio se chiarisco il mio intento; nel 4° byte memorizzo un valore da 0x01 a 0x06 in base alle 6 possibili combinazioni tra EFuse presente/non presente e modo di programmazione: HVPP, HVSP, HVP13.
Quando identifico la signature estrapolo e mostro il nome del micro, ed io nella mia ignoranza avrei fatto una void con una Select Case tipo (non badare alla sintassi):

void datimicro()
read.... 4 byte dell'array
select case 4byte
   case 0x01:
      EFUSE = 0 // non presente
      mode = "HVSP"
   case 0x02:
ecc...
Così il seguito del programma procede in base a queste due variabili già previste....
Ciò che mi state consigliando fa la stessa cosa e migliora la tecnica di esecuzione o no?

astrobeed


forse è meglio se chiarisco il mio intento; nel 4° byte memorizzo un valore da 0x01 a 0x06 in base alle 6 possibili combinazioni tra EFuse presente/non


Quello che ti sto suggerendo io è di usare i singoli bit del byte come singoli flag, p.e. bit 0 eFuse, bit 1 HVPP, bit 2 HVSP, bit 3 HVP13, dopo di che li hai sotto forma di nomi mnemonici come variabili a booleane (1 bit) grazie all'unione, p.e. AuxData.BtF.eFUSE, i nomi della unione e struttura puoi metterli a tuo piacere, anche di una sola lettera, p.e. U.S.eFuse .
Scientia potentia est

menniti



forse è meglio se chiarisco il mio intento; nel 4° byte memorizzo un valore da 0x01 a 0x06 in base alle 6 possibili combinazioni tra EFuse presente/non


Quello che ti sto suggerendo io è di usare i singoli bit del byte come singoli flag, p.e. bit 0 eFuse, bit 1 HVPP, bit 2 HVSP, bit 3 HVP13, dopo di che li hai sotto forma di nomi mnemonici come variabili a booleane (1 bit) grazie all'unione, p.e. AuxData.BtF.eFUSE, i nomi della unione e struttura puoi metterli a tuo piacere, anche di una sola lettera, p.e. U.S.eFuse .


OK, quindi dovrei impostare il bit meno significativo (p.es.) per il mode e quello più significativo per l'EFuse?
0x01 EFuse=0 mode = HVPP
0x02 EFuse=0 mode = HVSP
0x13 EFuse=1 mode = HVP13
intendi questo?

leo72



Io avrei fatto diversamente. Bastava usare la funzione predefinita di Arduino bitRead:


Corretto, però la BitRead in realtà è questo:

Sì, è vero. Però suggerisco un metodo più semplice da comprendere ed usare da uno la cui prima attività non è la programmazione. Usando la funzione predefinita hai al costo di un leggero aumento del peso computazionale una semplicità di gestione dei dati.

astrobeed


Sì, è vero. Però suggerisco un metodo più semplice da comprendere ed usare da uno la cui prima attività non è la programmazione. Usando la funzione predefinita hai al costo di un leggero aumento del peso computazionale una semplicità di gestione dei dati.


Per la come la vedo io è più semplice scrivere, e anche più leggibile, "if(U.S.eFuse == 1)" invece di " if(bitRead(dato,eFuse) == 1)".
Scientia potentia est

menniti

Io ho intenzione di provare ogni suggerimento, questa per me deve essere anche occasione di studio, altrimenti torniamo alle pappe pronte, con l'HW e i datasheet, l'avete visto, me la cavo un po' di più, ma il sw... :~
La BitRead dovrei usarla due volte per leggere prima uno e poi l'altro bit oppure in questo caso uso solo il bit meno significativo, dando valori da 01 a 06?

Poi ciò che userò sarà quella con cui riuscirò a prendere più dimestichezza, devo comunque avere la padronanza totale del firmware

leo72


La BitRead dovrei usarla due volte per leggere prima uno e poi l'altro bit oppure in questo caso uso solo il bit meno significativo, dando valori da 01 a 06?

Con la bitRead leggi un solo bit alla volta. Se vuoi leggere più bit insieme potresti usare una bitmask. Ad esempio
Code: [Select]
if (dato && 0b11000000) { ... }

faresti una certa azione solo nel caso in cui i 2 bit più significativi di un byte fossero ad 1.

menniti

NO, mi conviene leggere solo il bit meno significativo con valore da 1 a 6.
Quando finisco di lavorare provo le due tecniche, vediamo che ne esce  :~

leo72


NO, mi conviene leggere solo il bit meno significativo con valore da 1 a 6.

Non ho capito.... il bit meno significativo è lo 0.


La BitRead dovrei usarla due volte per leggere prima uno e poi l'altro bit oppure in questo caso uso solo il bit meno significativo, dando valori da 01 a 06?

Uhm.. Ma te volevi memorizzare un numero da 1 a 6. Per fare ciò bastano 3 bit.
000=0 001=1 010=2 011=3 100=4 101=5 110=6
Quindi basta uno switch..case su questi 3 bit:
switch (dato && 0b00000111) {
  case 0:
  ecc...
}

In pratica usi una bitmask con valore 7 o, se preferisci, 0b00000111, così isoli solo i primi 3 bit e poi controlli agisci

Go Up