Go Down

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

Occhio che 0x10 equivale a 16 decimale se vuoi scrivere il 10 decimale in formato esa devi scrivere 0xa.

Le #define e in genere tutto quello che comincia con il simbolo # (cancelletto) riceve l'attenzione di un programma chiamato preprocessore C, che opera delle sostituzioni prima della compilazione. Per esempio:

#define crf 0x10

int somma = crf + 0x4

Viene trasformato dal preprocessore così:

int somma = 0x10 + 0x4;

Al posto del numero esa 0x10 puoi scrivere ciò che vuoi, anche F_CPU/16, il prepocessore sostituisce il segnaposto crf con quello che segue.

int somma = 16000000/16 + 0x4;

Nota però che la rappresentazione del numero in formato è da considerare cosa differente dal numero stesso, anche un'intero può essere rappresentato in esadecimale ma ciò che appare sul display o a video non è il numero reale utilizzabile ma appunto una solo rappresentazione, tanto che il calcolo viene fatto in binario.

La possibilità che il C offre è, che non importa se assegni il valore ad una variabile in formato esa oct o decimale, tanto il C trasforma tutto in binario.
La funzione della libreria avr-libc offre una printf & company che permette la formattazione tramite le stringhe di formato, se hai intenzione di usare questa fa sapere che trovo la giusta stringa di formattazione e la posto. L'unico motivo per rinunciare a queste funzione è legata all'incremento
della dimensione del programma in modo diciamo corposo, diomensione che cresce ancora se vuoi anche stampare numeri in formato float o double, ma per questo è necessario inserire un flag nella fase di linking.

Ciao.
AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

leo72

Lasciate perdere il discorso che ho fatto tra byte e char, ci ho pensato dopo che infatti byte altro non è che un unsigned char  :P

Sulle define, la notazione di ratto è errata, non ci vuole l'uguale. Il define non è un'assegnazione come nelle variabili, ma una direttiva per il compilatore per fare ciò che dice Mauro: sostituisce all'alias indicato tutto ciò che segue.

Con #define crf = 0x10; il compilatore ogni volta che trova crf mette "= 0x10;" quindi anche l'uguale ed il punto e virgola.

Michele Menniti

Allora, se uno dei byte della signature ha un valore decimale inferiore a 16 lo 0 iniziale viene omesso nella notazione esadecimale, quindi 0F mi appare come F, quindi in sola fase di visualizzazione voglio aggiungere uno 0.
Avevo pensato a:
Serial.print("SIGNATURE: ");
    #if (read_signature1 < 0x10) //serve per mostrare lo 0 iniziale per valori <16 = 10
        Serial.print("0");
    #endif
  Serial.print(read_signature1, HEX);
ma non funziona, lo 0 esce sempre, il primo byte che è il produttore e per ATMEL è 1E mi esce come 01E.
read_signature1 contiene un dato che viene letto direttamente da un indirizzo del micro.
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

leo72

Ma così non funziona?
Code: [Select]

if (read_signature1 < 16) { Serial.print("0"); }

(16 è uguale a 0x10)
Poi non capisco: perché hai messo i  "#" davanti all'if?

astrobeed


Avevo pensato a:
Serial.print("SIGNATURE: ");
    #if (read_signature1 < 0x10) //serve per mostrare lo 0 iniziale per valori <16 = 10
        Serial.print("0");
    #endif
  Serial.print(read_signature1, HEX);
ma non funziona, lo 0 esce sempre, il primo byte che è il produttore e per ATMEL è 1E mi esce come 01E.
read_signature1 contiene un dato che viene letto direttamente da un indirizzo del micro.


Non ti funziona, ma non dovrebbe nemmeno compilarlo, perché gli "#" non ci devono essere e tantomeno ci deve essere la endif

Code: [Select]

Serial.print("SIGNATURE: ");
   if (read_signature1 < 0x10) Serial.print("0");

 Serial.print(read_signature1, HEX);


Michele Menniti

Ora sono al lavoro ma nelklo sketch originale questa cosa del # è spiegata, infatti la usano davanti a tutte le define, p.es., e la usando anche negli if/endif del setup (in setup svolgono la prima parte ma io la sto cambiando radicalmente per non dover resettare ogni fine operazione) e del loop ; io credo che attivi una sorta di compatibilità perché in effetti se tolgo # endif non lo accetta invece con # lo compila e lo esegue. Proverò il tuo codice al rientro
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

astrobeed


Ora sono al lavoro ma nelklo sketch originale questa cosa del # è spiegata, infatti la usano davanti a tutte le define, p.es., e la usando anche negli if/endif del setup (in setup


Stavolta ti rimando a Settembre in programmazione  :smiley-mr-green:
Il carattere # è un tag per il preprocessore che svolge vari aggiustamenti al sorgente in base alle operazioni richieste, #if e #endif servono per compilazione condizionale, ovvero se la condizione espressa nella if, solitamente legata ad una #define o un valore fornito dalla riga di comando del compilatore, è vera il codice che segue viene incluso e compilato, in caso contrario viene escluso dal programma.

Michele Menniti



Ora sono al lavoro ma nelklo sketch originale questa cosa del # è spiegata, infatti la usano davanti a tutte le define, p.es., e la usando anche negli if/endif del setup (in setup


Stavolta ti rimando a Settembre in programmazione  :smiley-mr-green:
Il carattere # è un tag per il preprocessore che svolge vari aggiustamenti al sorgente in base alle operazioni richieste, #if e #endif servono per compilazione condizionale, ovvero se la condizione espressa nella if, solitamente legata ad una #define o un valore fornito dalla riga di comando del compilatore, è vera il codice che segue viene incluso e compilato, in caso contrario viene escluso dal programma.

:smiley-red:, beh, del resto se leggi il titolo del Topic non puoi meravigliarti più di tanto; però, caro Prof XD, sulla base di questa tua lezioncina vedrò di capire a che servono tutti quegli # che ci sono. Tanto per cominciare: poiché ci sono una ventina di #include all'inizio e servono tutte (perché quelle inutili le ho levate io di crudo), ho un qualche vantaggio dal lasciarli?

@ Leo: non lo so, ho sempre pensato che trattandosi di hex andasse scritto 10 e non 16, può essere allora che stia funzionando ma che i valori in decimale siano sempre > 10 (0A se non sbaglio...); però ho provato 0x10 senza successo, vero è che la forma era quella #, quindi quando torno verifico.
Dopo verrà il "bello".. Siccome l'editor di questo Forum mi fa incazz a morte scrivo un altro post perintrodurre l'argomento.
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Michele Menniti

Appena avrò completato la parte di lettura della signature, con l'HVSP, sempre col prezioso aiuto di Astro, dovrò caricvare nello sketch una notevole tabella dei micro, che ho già (grazie UWE!), ma che devo implementare. Alla fine otterrò qualcosa del tipo (i valori sono inventati!)

1e950f  ATmega328P 62dff9 P
1e93ff   ATtiny85      62dfff S

Cioè per ogni micro devo memorizzare sia la signature che i fuse di default che la tecnica di programmazione necessaria (hvPp o hvSp).
Le domande che mi vengono sono queste:
Che tipo di array devo usare?
Mi creerà problemi di memoria ram (ad occhio sono un centinaio di righe, ma alla fine potrei accontentarmi delle 25 relative ai processori che ho provato)?
Se ho problemi potrei creare una tabella in forma di file (sarebbe anche meglio, più facilmente aggiornabile nel tempo)? Ma sarebbe accessibile dal firmware
Una volta che ottengo i tre valori di signature dal micro come faccio a farli diventare una stringa unica?
Che tecnica mi conviene usare per confrontare questa stringa con l'array per estrapolare le altre info?
Così una volta letta la signature posso chiedere all'utente se vuole leggere i fuse, se li vuole scrivere o se vuole ripristinare quelli di fabbrica (caso bricked), ed in automatico scelgo la procedura da seguire.
Che ne dite? sarebbe un bel lavoro no? Consigli?
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

leo72


Ora sono al lavoro ma nelklo sketch originale questa cosa del # è spiegata, infatti la usano davanti a tutte le define, p.es., e la usando anche negli if/endif del setup

Sono casi differenti, però. Le direttive per il compilatore sono istruzioni particolari che servono a creare il sorgente originale. Ad esempio, tu puoi mettere una porzione di codice dipendente dal micro.
Faccio un esempio più concreto. Mettiamo che devi scegliere un registro in base al micro, Atmega328 o Attiny85. Se tu metti un semplice if il tuo sketch conterrà sia la porzione di codice per il primo che per il secondo. Se metti un #if allora il compilatore includerà nello sketch solo la parte che occorre, salvando spazio. Questo è un caso stupido, ma rende l'idea.

Quote

ci sono una ventina di #include all'inizio e servono tutte (perché quelle inutili le ho levate io di crudo), ho un qualche vantaggio dal lasciarli?

Dipende.

Quote

@ Leo: non lo so, ho sempre pensato che trattandosi di hex andasse scritto 10 e non 16, può essere allora che stia funzionando ma che i valori in decimale siano sempre > 10 (0A se non sbaglio...); però ho provato 0x10 senza successo, vero è che la forma era quella #, quindi quando torno verifico.

Sono 2 forme differenti per rappresentare lo stesso numero. Scrivere 0x10 o 16 sono indifferenti. E' sempre un valore di 0b00010000  :P

Michele Menniti

Quando hai un po' di tempo pensa all'altra problematica  :)
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

leo72


Quando hai un po' di tempo pensa all'altra problematica  :)

Ehm... non ricordo...  :smiley-sweat:

Michele Menniti

:smiley-eek-blue: sta storia del pollo al sale ti ha ferito profondamente :P
ma è il post prima della tua ultima risposta :smiley-fat:
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

leo72


Appena avrò completato la parte di lettura della signature, con l'HVSP, sempre col prezioso aiuto di Astro, dovrò caricvare nello sketch una notevole tabella dei micro, che ho già (grazie UWE!), ma che devo implementare. Alla fine otterrò qualcosa del tipo (i valori sono inventati!)

1e950f  ATmega328P 62dff9 P
1e93ff   ATtiny85      62dfff S

Cioè per ogni micro devo memorizzare sia la signature che i fuse di default che la tecnica di programmazione necessaria (hvPp o hvSp).
Le domande che mi vengono sono queste:
Che tipo di array devo usare?
Mi creerà problemi di memoria ram (ad occhio sono un centinaio di righe, ma alla fine potrei accontentarmi delle 25 relative ai processori che ho provato)?
Se ho problemi potrei creare una tabella in forma di file (sarebbe anche meglio, più facilmente aggiornabile nel tempo)? Ma sarebbe accessibile dal firmware
Una volta che ottengo i tre valori di signature dal micro come faccio a farli diventare una stringa unica?
Che tecnica mi conviene usare per confrontare questa stringa con l'array per estrapolare le altre info?
Così una volta letta la signature posso chiedere all'utente se vuole leggere i fuse, se li vuole scrivere o se vuole ripristinare quelli di fabbrica (caso bricked), ed in automatico scelgo la procedura da seguire.
Che ne dite? sarebbe un bel lavoro no? Consigli?

Uhm... E' un bel blocco di dati.
Facciamo un calcolo. Se ogni voce deve contenere questi dati:
1e950f  ATmega328P 62dff9 P
abbiamo (senza gli spazi) più di 20 caratteri, ma devi stare largo perché potresti avere qualcosa tipo ATmega1284P nel nome. Quindi diciamo una media di 25 caratteri. Se li salvi come stringa di caratteri, sei nella cacc...  ;)
25*100=2500! Impossibile in RAM. Magari nella flash con PROGMEM.

Oppure... la signature la devi salvare in 3 byte, così come la leggi. Il nome devi salvarlo in formato intero. L'altro codice alfanumerico (i fuse, immagino) devi salvarli come byte anch'essi. L'ultimo come char.

Puoi usare anche un file su SD ma lo sketch cresce enormemente: aggiungi 10/12 kB solo per includere la libreria SD.

Michele Menniti

Ora che ci penso alla fine lavorerò in stand-alone e quindi niente file "esterni", né posso implementare un lettore SD, progettazione hw chiusa. E con l'eeprom potrei fare qualcosa? altrimenti mi rassegno e metto solo la trentina di micro noti sui quali ho fatto le prove, però mi piacerebbe avere la possibilità di identificare un bel numero di micro.
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Go Up