Topic permanente di programmazione newbie

menniti: Se ho ben capito, una volta bloccati i lock bit generali non è possibile neppure variare i valori dei fuse, oltre che quelli dei lock bit specifici; infatti c’è una

Si, una volta attivati i lock bits non puoi più tornare indietro e non puoi nemmeno modificare i fuse perché il livello minimo è proprio la protezione in scrittura. Per rimuovere i lock bit puoi usare solo il comando erase, non c'è programmazione HV che tenga.

astrobeed:

menniti: Se ho ben capito, una volta bloccati i lock bit generali non è possibile neppure variare i valori dei fuse, oltre che quelli dei lock bit specifici; infatti c’è una

Si, una volta attivati i lock bits non puoi più tornare indietro e non puoi nemmeno modificare i fuse perché il livello minimo è proprio la protezione in scrittura. Per rimuovere i lock bit puoi usare solo il comando erase, non c'è programmazione HV che tenga.

Io le procedure di chip_erase le ho già implementate con successo, spariscono i blink che è una bellezza sia in HVPP che in HVSP, quindi posso stare tranquillo che una volta bloccati i lock_bit se do' un chip erase tornano su 11?

Il Topic sul compilatore è aperto serve il Suo regal imprimatur, Sua Realtà :D

menniti: quindi posso stare tranquillo che una volta bloccati i lock_bit se do' un chip erase tornano su 11?

Yes.

Bene, la notte porta consiglio, poco saggio secondo me, ma ormai è fatta (si fa per dire…).
Allora appena identifico il micro mediante signature leggo anche i fuse ed i lock bit e mostro tutto a video; nel menu principale (ce ne faremo di risate con l’LCD reale :fearful:), oltre al tipico fine lavoro (potrebbero essere sufficienti le info mostrate) ho previsto il ripristino dei fuse di default, la programmazione personalizzata dei fuse, il chip erase ed ora aggiungerò anche la mcu protection (nome temporaneo), che farà apparire una domanda per scegliere tra read_lock e read-write_lock; inutile aggiungere lo sblocco perché tanto non funziona; come chiarito da Astro l’unico modo possibile per sbloccarli è il chip erase.
Però non so quanto tempo mi leva tutta questa cosa, quindi oggi mi metto a scrivere l’articolo della prima parte hw, visto che per settimana prossima devo consegnarlo e poi mi dedicherò nuovamente al firmware.
Intanto se avete idee e suggerimenti scirvete tranquillamente, ovvio che faccio filtro, ma magari c’è qualcosa su quanto già fatto…

Quando devo programmare i fuse scrivo i valori sul serial monitor; ho notato che la procedura è case sensitive e a me non va bene, vorrei poter scrivere i valori dia in minuscolo che in maiuscolo ottenendo che alla fine diventino maiuscoli; ai miei tempi :blush: mi pare che sommavo in basic 32 al minuscolo per ottenere il maiuscolo, poi uscirono comandi specifici come ucase e lcase, ma qui?

EDIT: ho risolto, disponevo di una funzione di conversione da HEX a numero, mi è bastato aggiungere le minuscole :slight_smile:

Se non hanno cambiato il codice ASCII l'altro giorno dovrebbe funzionare allo stesso modo XD

ratto93: Se non hanno cambiato il codice ASCII l'altro giorno dovrebbe funzionare allo stesso modo XD

No, l'ho dovute aggiungere le minuscole e trattarle come le maiuscole, comunque è ok. Invece:

while (Serial.available() == 0);   // aspetta il primo carattere
  
  serbuffer[0] = Serial.read();

tra queste due righe voglio mettere un controllo per rifiutare i caratteri che non rientrano nei range 0÷9 e A/a÷F/f, altrimenti la conversione esadecimale mi dà risultati sconvolgenti. Come posso fare?

In pratica devo poter accettare solo i caratteri con valore decimale tra 48 e 57 (0-9), tra 65 e 70 (A-F) e tra 97 e 102 (a-f); se il carattere rientra in questi range allora esegue la riga successiva, caricando il valore nel buffer, altrimenti dovrebbe restare in attesa del carattere come se non fosse stato premuto alcun tasto.

(spazio permettendo) si poteva anche convertire tutto in striga e usare gli appositi operatori

BrainBooster:
(spazio permettendo) si poteva anche convertire tutto in striga e usare gli appositi operatori
http://arduino.cc/en/Tutorial/StringCaseChanges

Non ho problemi di spazio :grin:; Comunque la funzione che mi risolve il problema di maiuscole/minuscole nella conversione a HEX è:

/************************ conversione di un carattere HEX in un numero *************************/
int hex2dec(byte c) {
  if (c >= '0' && c <= '9') {
    return c - '0';
  }
  // accetta indifferentemente maiuscole o minuscole
  else if (c >= 'A' && c <= 'F') {
    return c - 'A' + 10;
  }
  else if (c >= 'a' && c <= 'f') {
    return c - 'a' + 10;
  }
}

come vedi ho aggiunto il controllo delle minuscole. Invece ora ho il problema di dover ignorare tutti i valori che non rientrano nell’esadecimale.

spiega meglio cosa passa e cosa vuoi filtrare

In pratica devo restare in attesa di un carattere sulla seriale ma devo poter accettare solo i caratteri con valore decimale tra 48 e 57 (0-9), tra 65 e 70 (A-F) e tra 97 e 102 (a-f); se il carattere rientra in questi range allora esegue la riga successiva, caricando il valore nel buffer, altrimenti dovrebbe restare in attesa del carattere come se non fosse stato premuto alcun tasto.

con if potresti fare esattamente quello che hai detto :) mettiamo che il carattere in entrata si chiami c

if (c>=48 ||c<=70 ||c>=65 ||c<=70 || c>=97 || c<=102){
c è un carattere valido
}
else
{
ignoralo
}

ho usato i valori decimali perchè li avevi già scritti :)

Perfetto, ma credo di dover mettere tutto in un while; la logica è: aspetto un carattere leggo il carattere e lo confronto con i codici se è ok carico il carattere nel buffer se non è ok aspetto un nuovo carattere

quindi ora il mio problema è come fargli rifare la lettura se il carattere è sbagliato, provo a "studiare" :D

perchè deve rileggere un carattere sbagliato?

Mi spiego meglio, io devo fornire al firmware due caratteri validi per programmare il fuse; allo stato attuale accetta qualsiasi schifezza e la riconverte a modo suo in un valore HEX; voglio fare in modo di poter scrivere solo valori HEX; se scrivo "X" lui deve ignorarlo ed aspettare un nuovo carattere che rientri tra quelli richiesti. Ho fatto così:

do {
    while (Serial.available() == 0);   // aspetta il primo carattere
    r = Serial.read();
  } while (r>=48 || r<=70 || r>=65 || r<=70 || r>=97 || r<=102);
  serbuffer[0] = Serial.read();      // lo imposta come HIGH byte del fuse

ma come faccio a trasformare il carattere letto nel suo valore ascii? la riga r = Serial.read(); dovrebbe essere qualcosa tipo r = ASC(Serial.read()); c'è un comando di conversione?

EDIT: penso che così vada bene:

do {
    while (Serial.available() == 0);   // aspetta il primo carattere
    r = Serial.read();
  } while (r>=0 || r<=9 || r>='a' || r<='f' || r>='A' || r<='F');

ora a cena e poi provo

usare char? http://arduino.cc/it/Reference/Char

l'avevo visto ma sul mio manualetto non dice niente, ora ho visto che è proprio ciò che mi serve. Ma così mi funziona esattamente al rovescio, come faccio ad invertire la logica del while:

 do {
    while (Serial.available() == 0);   // aspetta il primo carattere
    r = char(Serial.read());
  } while ((r>=48 && r<=57) || (r>=65 && r<=70) || (r>=97 && r<=102));
  serbuffer[0] = Serial.read();      // lo imposta come HIGH byte del fuse
  
  do {
    while (Serial.available() == 0);   // aspetta il primo carattere
    r = char(Serial.read());
  } while ((r>=48 && r<=57) || (r>=65 && r<=70) || (r>=97 && r<=102));
  serbuffer[1] = Serial.read();      // lo imposta come HIGH byte del fuse

[quote author=Michele Menniti link=topic=95050.msg750159#msg750159 date=1333643733] ai miei tempi :blush: mi pare che sommavo in basic 32 al minuscolo per ottenere il maiuscolo, [/quote] No si sommava 32 per passare da maiuscolo a minuscolo, oppure l'inverso cioè si sottraeva 32 per passare da minuscolo a maiuscolo. Questo perché A=65, a=97 ;)

Tornando al tuo problema, tu devi fare la conversione di un dato esadecimale in decimale. Se ad esempio ti arriva E2 devi convertirlo in 226, ma non puoi farlo come pensi tu. Cioè la conversione da esadecimale a decimale si fa con (valore del 1° carattere*16)+valore del 2° carattere. Quindi E*16+2 -> 14*16+2 -> 224+2 = 226

Io allora farei così

char carattere;
byte contatore=2;
byte risultato=0;
while (contatore) { //loop finché non sono arrivati 2 cifre
  if (Serial.available()) {
    carattere=Serial.read();
    if ((carattere>='0') && (carattere<='9')) { //cifra numerica
      contatore--;
      risultato+=(carattere*(contatore>0?16:1)); //sommo il valore esadecimale
      
    } else if ((carattere>='A') && (carattere<='F')) { //
      contatore--;
      risultato+=(carattere-55)*(contatore>0?16:1); //A=65 -> 65-55=10 ecc..
    } else if ((carattere>='a') && (carattere<='f')) {
      contatore--;
      risultato+=(carattere-87)*(contatore>0?16:1); //a=97 -> 97-87=10 ec...
    }
  }
}

In questo modo dovrebbe funzionare. Dovrebbe leggere 2 cifre, e continuare a leggere finché il carattere ricevuto non ricade nell'intervallo 0-9, oppure A-F oppure a-f. "contatore" serve per eseguire il ciclo solo 2 volte (2 cifre), viene anche usato per la conversione in questo modo: all'avvio vale 2, se si riceve un carattere valido, passa a 1, poi viene moltiplicato per 16 ed il risultato moltiplicato per il valore ricevuto. Vien da sé che l'operatore condizionale su contatore quando vale 1 dia 16 mentre quando vale 0 (caso della seconda cifra), dia come risultato 1. Non so nemmeno se compila, l'ho scritta di getto

No, Leo, la mia situazione è molto più semplice, io non devo controllare la validità del valore esadecimale, semplicemente devo impedire di comporlo usando caratteri diversi da quelli previsti. Ciò che faccio è: leggo il primo carattere se non è 0-9, A-F, a-f rileggo il carattere quando il carattere è corretto lo memorizzo faccio lo stesso col secondo carattere alla fine ottengo due caratteri, p.es. F9 che passo alla procedura di scrittura del fuse. Quindi il code che ho postato prima funziona benissimo, ma al rovescio, cioè mi accetta SOLO i caratteri diversi da quelli che mi servono. Come faccio ad invertire la logica del do-while?

Anche il mio codice fa questo, forse non l'ho spiegato bene. Tornando al tuo, mi pare che non vada bene:

do {
    while (Serial.available() == 0);   // aspetta il primo carattere
    r = char(Serial.read());
} while ((r>=48 && r<=57) || (r>=65 && r<=70) || (r>=97 && r<=102));
serbuffer[0] = Serial.read();      // lo imposta come HIGH byte del fuse

Nel momento in cui esci dal ciclo do..while perdi il carattere che leggevi e memorizzi il secondo in arrivo. Questo perché la Serial.read preleva materialmente dal buffer seriale il carattere che leggi, perdendolo del tutto se non lo memorizzi. Ma tu l'hai memorizzato in "r", quindi metti quello direttamente in serbuffer[0] oppure usi Serial.peek() che ti dice qual è il prossimo carattere che viene prelevato dal buffer: in pratica lo leggi ma non lo togli dal buffer.