Topic permanente di programmazione newbie

leo72: 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)".

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

menniti: 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

if (dato && 0b11000000) { ... }

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

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 :~

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

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

menniti: 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

No, Leo, mi sono espresso male, io uso, come suggerito da Astro un valore tipo 0x00 per memorizzare dei flag, vorrei usare l’ultima cifra per leggere solo quella, cioè 0x01, 0x02, 0x03 ecc., quindi faccio qualcosa del tipo
se = 1 EFUSE=0 e mode=HVPP
se = 2 EFUSE=0 e mode=HVSP
è più chiaro ora?
Sono appena rientrato, ora mi comincio a mettere al lavoro, se hai suggerimenti immediati spara! :stuck_out_tongue:

Ok. Ora è chiaro. Comunque ricorda che in un byte ci sono 8 bit per cui puoi avere fino a 8 flag differenti. Se ragioni in termini di "cifre" perdi dei bit per futuri usi. Pensando in termini di notazioni numeriche, in notazione esadecimale ogni cifra contiene un valore che prende 4 bit. Ragionando in termini di notazione binaria, invece, per memorizzare dei valori decimali da 0 a 6, usi solo 3 bit, salvando quelli dal 4°all'8°(quindi 5 flag) per futuri usi.

leo72: Ok. Ora è chiaro. Comunque ricorda che in un byte ci sono 8 bit per cui puoi avere fino a 8 flag differenti. Se ragioni in termini di "cifre" perdi dei bit per futuri usi. Pensando in termini di notazioni numeriche, in notazione esadecimale ogni cifra contiene un valore che prende 4 bit. Ragionando in termini di notazione binaria, invece, per memorizzare dei valori decimali da 0 a 6, usi solo 3 bit, salvando quelli dal 4°all'8°(quindi 5 flag) per futuri usi.

Scusa, ma usando un valore esadecimale io mi predispongo per 32 combinazioni, da 0x00 a 0xFF, giusto? usando da 0x01 a 0x06 non sto semplicemente usando i primi 6 bit preservandomi i successivi 26 oppure non c'ho capito una mazza?

menniti: Scusa, ma usando un valore esadecimale io mi predispongo per 32 combinazioni, da 0x00 a 0xFF, giusto?

Da 0x00 a 0xFF sono 256 possibili valori.

usando da 0x01 a 0x06 non sto semplicemente usando i primi 6 bit preservandomi i successivi 26 oppure non c'ho capito una mazza?

Se usi da 0x00 a 0x06 sono sette possibili valori e impegni 3 bit, la stessa cosa che ottieni impegnando ogni singolo bit per un flag a due stati, se applichi la matematica binaria sempre 256 valori totali ottieni, cambia solo il modo di rappresentare le cose.

Sì, sì, che figura di m, scusate ma sto dormendo da seduto, infatti chiudo, sono proprio scoppiato :fearful:
Praticamente 0xFF è la rappresentazione esadecimale di 0b11111111, quindi 4+4=8 bit=2^8=256 combinazioni, di cui ne uso solo 6, hai voglia di “usi futuri”…per la tecnica da adottare vedremo, prima di tutto devo riorganizzare il firmware perché la problematica dei tiny 2313 e 861 mi ha imbordellito la vita, il problema l’ho risolto con 3 sole righe ma vanno messe all’inizio e l’unico modi di leggere le signature di tutte le famiglie è quello HVSP che non funziona se attivo quelle tre righe, quindi ora dvo organizzare tutto in “void” e in loop devo creare una specie di main che ogni volta esegua la giusta routine, lavoro da fare a mente fresca, ora non c’è. :sleeping:
Speravo di avere energie ma ho proprio l’abbiocco, cerco di ricominciare domattina dopo una sana dormitissima, troppo lavoro in questi giorni. Grazie ragazzi e scusatemi.

astrobeed: Se usi da 0x00 a 0x06 sono sette possibili valori e impegni 3 bit, la stessa cosa che ottieni impegnando ogni singolo bit per un flag a due stati, se applichi la matematica binaria sempre 256 valori totali ottieni, cambia solo il modo di rappresentare le cose.

Si parlava di "cifra", una cifra esadecimale occupa 4 bit. Se parliamo di "valore" allora si torna al discorso che avevo fatto e che hai ripreso, che cioè dentro a 3 bit ci stanno 8 valori, 2^3=8.

menniti: Praticamente 0xFF è la rappresentazione esadecimale di 0b11111111, quindi 4+4=8 bit=2^8=256 combinazioni, di cui ne uso solo 6, hai voglia di "usi futuri"......

Scusa Mike se insisto ma non è proprio così :sweat_smile: Se ragioniamo in termini di flag, abbiamo 8 flag, ognuno che può assumere il valore 0 o 1, quindi le combinazioni sono 256 ma in realtà riguardano sempre 8 impostazioni. Immagina 8 interruttori della luce: ogni interruttore può essere "su" (acceso o 1) o "giù" (spento o 0). Nel quadro elettrico potrai sì vedere 256 combinazioni dello stato dei singoli interruttori ma in realtà tu starai considerando lo stato binario di 8 interruttori. Mettiamo che gli interruttori siano: 0=cucina 1=bagno 2=corridoio 3=camera 4=salotto 5=ripostiglio 6=ingresso 7=terrazza e vuoi dire a tua moglie di accendere la cucina e la camera, non andrai a dirgli "accendimi la combinazione" (1*2^0)+(1*2^3)=9 ma gli dirai di accendere l'interruttore 0 e l'interruttore 3.

Tornando ai tuoi flag, l'informazione "globale" è contenuta in un byte, quindi tu hai quel dato memorizzato, ma non tratti il numero nella sua completezza ma per singoli bit.

leo tu hai ragione ed anche io preferisco ragionare in termini binari specialmente se si tratta di sfruttare un byte in termini di singoli flag. Pero lastrada del menny funziona ugualmente quindi se per lui e' piu facile ragionare in termini di byte singolo va bene cosi. Meglio avere uno sketch che capisci che uno migliore ma di cui non hai padronanza. Mio parere :)

Dopo una sana dormita di 10 ore stamattina mi sento in condizioni di poter riaffrontare la cosa, sia dal punto di vista teorico che da quello pratico, che poi, come dice giustamente Test, è quello che mi interessa di più: se non in grado di tirare fuori 1,2,....6 da quel valore memorizzato non mi serve altro, se devo farlo considerando che 6=1100 mi rompe un po' di più ma alla fine è la stessa cosa, l'importante è capire ed implementare il meccanismo, ma prima ho da affrontare due problemi più importanti: 1 - la frammentazione del mio firmware in void, mentre prima potevo fare una procedura unica perché l'informazione sul micro la davo io da menu e tutto il resto veniva da sé, ora devo prima riconoscere il micro in automatico, quindi devo eseguire gran parte del firmware per poi rieseguirlo quasi tutto in funzione del micro inserito, chiaro che non posso "ricopiare" un intero firmware togliendo poche cose, quindi ogni spezzone funzionante lo metto in una void e nel loop mi lascio un main semplice semplice che esegua le varie void all'occorrenza. 2 - Letta la signature devo confrontare i suoi tre byte con quelli prememorizzati, io direi di semplificare confrontanto solo secondo e terzo, il primo mi serve come controllo della validità della signature, deve essere infatti sempre 1E (=Atmel), sopno il secondo e terzo che cambiano in funzione della memoria e del modello del micro. A tale proposito ho imparato che: 1° byte = produttore = 1E = Atmel 2° byte = memoria del micro -> 91=2K, 92=4K, 93=8k, ecc.ecc. ;) 3° byte =modello del micro ma in coppia col secondo byte -> 950F = 328P (da approfondire quando avrò la tabella completa da studiare) scrivete gente, scrivete.... Allora la mia idea di confronto della signature è: un ciclo for di due passi all'interno di un while (flag); logica: fino a che il flag = 0 leggo il secondo byte del secondo array, se è uguale leggo il terzo, se è uguale fine. se non è uguale (o primo o secondo byte) passo alla riga successiva dell'array se arrivo a fine array gli dico : guagliò che tieni inta a capa? mietti o micro giusto XD idee migliori? (di sicuro ne avete!) a più tardi e grazie.

menniti: leggo il secondo byte del secondo array, se è uguale leggo il terzo, se è uguale fine. se non è uguale (o primo o secondo byte) passo alla riga successiva dell'array se arrivo a fine array gli dico : guagliò che tieni inta a capa? mietti o micro giusto XD idee migliori? (di sicuro ne avete!) a più tardi e grazie.

Io procederei così, prima di tutto verifichi se il primo byte della signature è 0x1E, se è così continui in caso contrario il processo termina e visualizzi sul display un idoneo messaggio di errore. Se il confronto sul primo byte da esito positivo inizializzi una for con tante iterazioni quanti sono i modelli di micro supportati, in due variabili locali unsigned int sommi i due byte rimanenti della signature e i due byte della riga matrice in uso, confronti tra loro i due valori, se sono identici hai finito e hai l'indice per accedere agli altri arry, se non trovi nessuna corrispondenza alla fine della for termini con un messaggio di modello non supportato. Ti allego la relativa funzione così ci capiamo meglio, tiene presente che la sto scrivendo al volo direttamente sul forum senza provare nulla quindi è possibile che contenga qualche errore, quello che conta è il concetto.

/* funzione controllo signature invocata dopo il controllo del primo byte, 
    la invochi fornendo gli altri due byte della signature, ti ritorna il valore 
   dell'indice se viene trovata corrispondenza oppure 0xff in caso di errore.

*/

unsigned char Controllo_signature(unsigned char byte2, unsigned char byte3)
{
char i;
unsigned int temp1, temp2;

temp1 = (unsigned inte) byte2 << 8 + byte1;

for (i=0;i<20;i++)
 {
  temp2 = (unsigned char) Signature[i] [1] <<8 + Signature[i] [2];
  if (temp1 == temp2) return i; // esce dalla funzione con il valore dell'indice
 }

return 0xff; // corrispondenza non trovata.
}

Piccola nota aggiuntiva, il codice è composta da funzioni e non da void, questo è solo un attributo che indica "nulla", ovvero la funzione non ritorna nessun valore, infatti nel nostro caso la funzione è identificata come "unsigned char Controllo_signature(unsigned char, unsigned char)", vuol dire che accetta in ingresso due valori compresi tra 0 e 255 e ritorna un valore compreso tra 0 e 255.

Testato: leo tu hai ragione ed anche io preferisco ragionare in termini binari specialmente se si tratta di sfruttare un byte in termini di singoli flag. Pero lastrada del menny funziona ugualmente quindi se per lui e' piu facile ragionare in termini di byte singolo va bene cosi. Meglio avere uno sketch che capisci che uno migliore ma di cui non hai padronanza. Mio parere :)

O sono io che non mi so spiegare oppure ho disimparato a leggere... ma la questione iniziale era usare un byte come contenitore di impostazioni aggiuntive, quindi flag. :P Così infatti è stato detto e suggerito di usare il 4° byte. Usarlo in formato numerico porta ad un gran casino perché se il byte ha il valore, ad esempio, di 195 a me dice poco ma sapere che i suoi bit sono 11000011 mi fa capire che ho 4 flag ad 1 che mi indicheranno determinate opzioni o configurazioni. Proprio l'uso dei singoli bit permette di immagazzinare informazioni più "specifiche". Se poi in quel 4° byte non ci deve stare altro che un valore da 0 a 6 allora è un altro discorso però è stato detto che era possibile usarlo anche per scopi futuri: strutturare il codice bene fin da subito in questo modo permette in seguito di non dover cambiare tutti i dati memorizzati e la logica del programma perché si è deciso di aggiungere dei dati a quel byte.

menniti: Dopo una sana dormita di 10 ore stamattina mi sento in condizioni di poter riaffrontare la cosa, sia dal punto di vista teorico che da quello pratico, che poi, come dice giustamente Test, è quello che mi interessa di più: se non in grado di tirare fuori 1,2,....6 da quel valore memorizzato non mi serve altro, se devo farlo considerando che 6=1100 mi rompe un po' di più ma alla fine è la stessa cosa, l'importante è capire ed implementare il meccanismo, ma prima ho da affrontare due problemi più importanti:

Leggi sopra. Se vuoi metterci solo 0..6 usalo come vuoi, se in futuro pensi di usarlo per altri scopi, usalo nei singoli bit.

1 - la frammentazione del mio firmware in void, mentre prima potevo fare una procedura unica perché l'informazione sul micro la davo io da menu e tutto il resto veniva da sé, ora devo prima riconoscere il micro in automatico, quindi devo eseguire gran parte del firmware per poi rieseguirlo quasi tutto in funzione del micro inserito, chiaro che non posso "ricopiare" un intero firmware togliendo poche cose, quindi ogni spezzone funzionante lo metto in una void e nel loop mi lascio un main semplice semplice che esegua le varie void all'occorrenza.

Una piccola correzione. void indica al compilatore che una funzione restituisce un valore nullo, non è una parola chiave che indica al compilatore una funzione. Cioè, void non indica che si sta scrivendo una sub-routine ma il suo valore. Esempi:

void mario() {
  ... codice ...
}

Questo codice indica al compilatore che esiste una funzione o sub-routine, chiamala come vuoi, che non restituisce nessun valore. La dichiarazione di funzione è implicita, è come se esistesse una parola chiave "function" omessa.

Questo:

byte beppe() {
  byte dato;
  ... codice ...
  return dato;
}

Crea invece una funzione di nome beppe che restituisce un tipo di dati byte. Quindi, non è corretto indicare una funzione con il termine "void". Ti faccio questa precisazione perché se nell'articolo scrivi che hai creato una void per fare una certa operazione, poi ricevi 100 lettere da programmatori C incacchiati che ti vogliono ardere in piazza tipo Savonarola ;)

2 - Letta la signature devo confrontare i suoi tre byte con quelli prememorizzati, io direi di semplificare confrontanto solo secondo e terzo, il primo mi serve come controllo della validità della signature, deve essere infatti sempre 1E (=Atmel), sopno il secondo e terzo che cambiano in funzione della memoria e del modello del micro. A tale proposito ho imparato che: 1° byte = produttore = 1E = Atmel 2° byte = memoria del micro -> 91=2K, 92=4K, 93=8k, ecc.ecc. ;) 3° byte =modello del micro ma in coppia col secondo byte -> 950F = 328P (da approfondire quando avrò la tabella completa da studiare) scrivete gente, scrivete.... Allora la mia idea di confronto della signature è: un ciclo for di due passi all'interno di un while (flag); logica: fino a che il flag = 0 leggo il secondo byte del secondo array, se è uguale leggo il terzo, se è uguale fine. se non è uguale (o primo o secondo byte) passo alla riga successiva dell'array se arrivo a fine array gli dico : guagliò che tieni inta a capa? mietti o micro giusto XD idee migliori? (di sicuro ne avete!) a più tardi e grazie.

Basta un if con un triplo controllo all'interno di un for. Mettiamo che firma[..] contenga la firma digitale letta dal micro e archivioFirme[..][..] le firme memorizzate:

boolean trovato=false;
for (byte i=0; i

"trovato" è false all'uscita del ciclo for se non è stato trovato nessun corrispondente modello nell'archivio

Leo, ma sei chiarissimo, solo che io nella mia beata ignoranza tento di rispiegare a parole mie e dico czz; grazie per il chiarimento void/funzione, ci sto proprio litigando ora. HELP! Se metto in loop

byte read_signature1;
read_signature1=SIGN_S_read(0x00, SIGN_READ_INSTR4);

con questa funzione messa nella “zona” delle routine:
byte SIGN_S_read(byte data, byte instr) { // leggo un byte col protocollo HVSP
byte response = 0x00;
.
.
return response;
}

funziona correttamente.

Se sposto il comando di lettura in una sua funzione, così:

byte read_signature1;
sign_HVSP_read();

e quindi ora ho due funzioni:

void sign_HVSP_read(void) {
read_signature1=SIGN_S_read(0x00, SIGN_READ_INSTR4);
}

byte SIGN_S_read(byte data, byte instr) { // leggo un byte col protocollo HVSP
byte response = 0x00;
.
.
return response;
}

Mi dà questo errore: HV_Programmer_MAIN.cpp: In function 'byte signt_SP_read()': HV_Programmer_MAIN:489: error: 'read_signature1' was not declared in this scope

Perché? Devo risolvere con qualcosa del genere altrimenti non ho la possibilità di leggere la signature in modo sequenziale nelle tre diverse modalità. Cioè io da sign_HVSP_read(); mi aspetto di rientrare in main avendo a disposizione il valore di signature1

Si chiama spazio dei nomi, ed indica la visibilità di una variabile. Se una variabile la dichiari in una funzione, non la puoi usare al di fuori di essa. Per poterla usare in tutte le funzioni del tuo programma, devi dichiararla come variabile globale: per far ciò basta mettere la sua dichiarazione in cima allo sketch:

byte read_signature1;
....
void setup() {
....
}

void loop() {
...
}

void sign_HVSP_read(void) {
read_signature1=SIGN_S_read(0x00, SIGN_READ_INSTR4);
}

menniti: HV_Programmer_MAIN.cpp: In function 'byte signt_SP_read()': HV_Programmer_MAIN:489: error: 'read_signature1' was not declared in this scope

Vuol dire che "read_signature1" non viene trovata come variabile locale o globale, se l'hai dichiarata nella loop è normale che non la trova, devi dichiararla esternamente come variabile globale se vuoi che sia disponibile per tutte le funzioni senza doverla passare esplicitamente.

astrobeed:

menniti: HV_Programmer_MAIN.cpp: In function 'byte signt_SP_read()': HV_Programmer_MAIN:489: error: 'read_signature1' was not declared in this scope

Vuol dire che "read_signature1" non viene trovata come variabile locale o globale, se l'hai dichiarata nella loop è normale che non la trova, devi dichiararla esternamente come variabile globale se vuoi che sia disponibile per tutte le funzioni senza doverla passare esplicitamente.

Infatti stavo provando e mettendola direttamente nella funzione come byte read_signature1; l'errore è sparito In effetti era dichiarata in loop, allora mi basta spostarla nelle variabili globali per risolvere in modo anche più elegante. Grazie e a dopo, oggi sarà dura con questa storia della main :grin:

Ora che funziona la prima parte ho fatto una scoperta interessante: la tecnica HVPP mi permette di leggere TUTTI i tipi di signature, anche quelle dei micro che normalmente programmo in HVSP, quindi come prima manovra leggo la signature a colpo sicuro, poi differenzio invece la lettura e la scrittura dei fuse :)

EDIT: ma mi viene un dubbio e devo fare una controverifica...