Tutorial → PIC18 →
Assembly → Il primo programma

In questa pagina vedremo come creare il primo progetto e come usare il
simulatore per esplorare la struttura ed il contenuto delle memorie del
microcontrollore che stiamo utilizzando. Non faremo uso di circuiti fisici perché è cosa complessa capire se un
comportamento imprevisto nasce da un errore hardware oppure software.
La creazione di un nuovo progetto
Ciascun programma deve essere incluso in un progetto. La procedura per
creare un progetto è guidata:
- Inizia ovviamente con Create New Project. Le scelte di
default (Microchip embedded e Standalone Project) sono
quelle in genere corrette
- Occorre quindi scegliere la variante di PIC18 (è facile sbagliare: molte sigle
si assomigliano). L'esempio mostrato in questa pagina utilizza un PIC18F26K20,
ma nulla cambia scegliendo un altro PIC18
- Se intendiamo utilizzare circuiti fisici (ma non è il caso qui
mostrato) viene richiesto il modello di In-Circuit Debugger.
In questo primo esempio sceglieremo invece il simulatore (Simulator)
- L'assemblatore da utilizzare (in seguito MPASM). Se
sono presenti più versioni, potrebbe essere conveniente scegliere quella
più aggiornata
- Il nome del progetto
Quando si crea un nuovo programma è necessario creare un nuovo progetto
oppure fare una copia del vecchio progetto (tasto destro del mouse sul nome
del progetto)
L'immagine seguente mostra le finestre principali di MPLAB X (nota
2):
- In alto a sinistra, l'elenco dei progetti. Se sono presenti più
progetti, quello in uso (main project, in grassetto) deve essere selezionato con il
tasto destro.
- Nella stessa finestra: l'elenco dei file del progetto (nell'esempio
uno solo: main.asm). Progetti semplici
sono costituiti da un solo file, progetti più complessi comprendono
molti file.
- In alto a destra, il contenuto di un file sorgente (nell'esempio
main.asm)
- In basso a sinistra, la dashboard, che permette di
monitorare l'uso delle risorse nonché di modificare le scelte fatte (per
esempio: il tipo di processore)
- In basso a destra, i messaggi nelle varie fasi di
compilazione, programmazione ed esecuzione. Eventuali errori (qui non
presenti) sono
evidenziati in rosso
- In alto le varie icone e menu di compilazione e debug
Durante l'uso vengono aperte anche numerose altre finestre...

La memoria
Attraverso il simulatore è possibile esaminare lo stato del
microcontrollore. Per esempio, attraverso la voce Window → PIC Memory view, è possibile esaminare il contenuto:
- dei File Registers, la memoria a lettura/scrittura
(RAM) utilizzata per contenere le variabili. Nell'esempio qui sotto
mostrato è piena di zeri,
tranne le due celle con indirizzo 0x043 e 0x126, evidenziate in rosso
- della Program Memory, la memoria a sola lettura (Flash) che
contiene il codice eseguibile. In questo casa è piena di uni, tranne le
prime celle (nota 1)

Si noti che queste due memorie hanno una struttura diversa:
- La prima è una memoria RAM volatile, suddivisa a seconda della
versione del PIC, in circa 4000 celle da 8 bit ciascuna
- La seconda è una memoria flash non volatile, suddivisa a seconda
della versione del PIC, in circa qualche decina di migliaia di celle da 16 bit ciascuna
Il primo programma
Scriviamo il primo programma, creando un file con estensione
.asm. e salvandolo nella cartella virtuale
Source Files. Quanto mostrato non fa
assolutamente nulla di utile, ma ci servirà per prendere confidenza con il
microcontrollore, l'ambiente di sviluppo ed i
fogli tecnici.

Cosa fa questo programma?
- Istruzione movlw 0x55: MOVe
Letteral to W register - muove letteralmente nel registro
W il numero
esadecimale 0x55.
- Istruzione addlw 0x10: ADD
Letteral to W register - somma letteralmente
0x10 al contenuto del registro
W, memorizzando il risultato nel registro W
- Istruzione addlw 0x10: ADD
Letteral to W register - somma letteralmente
0x10 al contenuto del registro
W, memorizzando il risultato nel registro in W
- Istruzione addlw 0x10: ADD
Letteral to W register - somma letteralmente
0x10 al contenuto del registro
W, memorizzando il risultato nel registro in
W
- Istruzione sleep: SLEEP -
addormenta il processore, cioè ne sospende l'attività
Se vogliamo riscrivere tale programma con uno pseudo-linguaggio:
0x55 → WREG
(WREG) + 0x10 → WREG
(WREG) + 0x10 → WREG
(WREG) + 0x10 → WREG
Fine
Se vogliamo riscrivere tale programma in C (o in un altro linguaggio ad
alto livello):
WREG = 0x55;
WREG = WREG + 0x55;
WREG = WREG + 0x55;
WREG = WREG + 0x55;
exit
In totale tre diverse istruzioni, che esamineremo nel dettaglio una per
una più avanti.
Alcune osservazioni:
- è necessario che ciascuna riga di codice abbia almeno uno spazio
davanti (il perché verrà spiegato più avanti)
- le istruzioni possono essere scritte maiuscole o minuscole, ma in
seguito saranno sempre in minuscolo per chiarezza
- la prima e l'ultima riga, in un colore diverso, NON contengono
istruzioni, ma direttive (il concetto verrà
spiegato più
avanti). Nello specifico indicano che il codice dovrà essere memorizzato
a partire dall'indirizzo di memoria 0 (CODE 0) e che dopo l'END non
c'è più nulla
di significativo
- i numeri esadecimali sono indicati con la sintassi tipica del C, ma,
in questo caso, non è strettamente necessario, dato che la base 16 è
quella predefinita. Quindi, a meno di impostazioni particolari, scrivere
0x10 è la stessa cosa che scrivere
10. Consiglio vivamente la prima codifica (0x10) in
quanto la seconda (10) può facilmente portare ad errori di interpretazione
da parte di chi legge il codice
Assembliamo il programma
Per assemblare il programma appena scritto occorre utilizzare l'icona
evidenziata, osservando nella finestra di output l'assenza
di errori.

Il programma compilato viene automaticamente caricato nella Program
Memory del simulatore. Nella figura seguente possiamo osservare
- le cinque istruzioni che abbiamo scritto, ma non le due direttive (colonna
DisAssy,
traducibile con Disassemblato)
- l'indirizzo (Address) delle celle di memoria in cui sono state memorizzate
(solo indirizzi pari, essendo tutte lunghe 16 bit, cioè quatto cifre
esadecimali)
- Il codice binario corrispondente (Opcode, codice operativo,
le sole istruzioni che un processore può elaborare)

Eseguiamo il programma
L'avvio del programma è gestito da una serie di icone la cui descrizione
è mostrata scorrendoci sopra il mouse:

Nell'ordine:
- Inizia l'esecuzione del programma
- Ferma definitivamente l'esecuzione del programma
- (in grigio) sospende temporaneamente l'esecuzione del programma
- Resetta il programma (ricomincia dall'indirizzo zero)
- Prosegue l'esecuzione del programma dal punto in cui è stato
precedentemente sospeso
- Esegue una singola istruzione (esecuzione passo-passo). In realtà
sono una serie di icone simili, dal comportamento un po' diverso (ma
intuitivo...)
Se si desidera fermare il programma ad una certa istruzione, è possibile
inserire un breakpoint (linea rossa nell'immagine seguente),
cliccando sul corrispondente numero di riga. (nota 3)
Durante l'esecuzione passo-passo possiamo osservare:
- In alto a destra il contenuto del Program Counter (PC) e del
registro W. Inoltre, anche se al momento non serve
comprenderne il significato, è segnalato il valore dei
flags (o Status Bits) e quale è il
banco di memoria in
uso
- Nella finestra del codice, evidenziato in rosso, un breakpont ed
evidenziata in verde e da una freccia l'istruzione che sta per essere eseguita
- Nella Program
Memory, la freccia verde indica l'istruzione che sta per essere
eseguita

Inoltre (non mostrato in figura) è possibile osservare e modificare il contenuto della
memoria RAM (File Registers).
Quesiti
- Durante l'esecuzione del programma di esempio, cosa contiene la cella di RAM con indirizzo 0?
- Cosa contiene la cella di memoria Flash con indirizzo 0?
- Cosa contiene la cella di RAM con indirizzo 0xFE8? Osservazioni?
- Cosa contiene la cella di RAM con indirizzo 0xFF9? Osservazioni?
(domanda non banale. Potrebbe essere utile la consultazione dei
fogli tecnici)
- Nel caso del PIC18F26K20, quante istruzioni potrà avere al massimo un programma?
- Nel caso del PIC18F25K20, quante istruzioni potrà avere al massimo un programma?
- La memoria RAM da quanti byte è costituita? (la risposta a questa
domanda potrebbe essere poco accurata)
- Gli uni sono rappresentati in esadecimale (1111 → F), per rendere il
tutto leggibile anche agli umani
- Le finestre possono essere spostate, ridimensinate, chiuse... Per
tornate alla situazione iniziale è utile la voce di menu Window
→ Reset Windows
- Spesso si desidera fermare il programma immediatamente al momento
del reset (cioè all'esecuzione dell'istruzione posta all'indirizzo 0);
per fare ciò è possibile attivare l'opzione Tools → Options →
Embedded → Debug startup → Halt at reset vector. In alternativa
potete inserire un breakpoint in corrispondenza della prima istruzione.
Data di creazione di questa pagina: gennaio 2017
Ultima modifica di questa pagina: 7 ottobre 2017