Tutorials - PIC18

 

Il Set di istruzioni dei PIC18

 


Introduzione

I microcontroller PIC appartengono alla categoria dei RISC, ovvero dispongono di un set limitato di istruzioni . Queste istruzioni sono , però, basilari sia come funzionalità che come rapidità di esecuzione; il programmatore potrà creare, se ritiene necessario, altre istruzioni più complesse associando più istruzioni fondamentali attraverso la tecnica della macro istruzione.

Per i PIC più semplici si ha un set ridotto con 31 istruzioni a 12bit. Per i mid-range, la famiglia 16Fxxx, il set di istruzioni è composto da circa 35 elementi a 14 bit. 

Per i PIC18Fxxx il set è espanso a 77 istruzioni, più altre speciali, per un totale di 83 possibili opcodes, in un formato a 16 bit.


 

Struttura degli opcodes

Prima di iniziare a vedere in dettaglio il set di istruzioni, occorre fare una precisazione importante.
Nei PIC la sequenza di bit che codifica le istruzioni contiene sia il codice specifico dell' istruzione, sia l' indirizzo di destinazione (se previsto) e le eventuali opzioni o specifiche dell' istruzione stessa. Questo riduce il numero dei bit disponibili per l' indirizzamento sia nell' area di memoria utente che nella memoria programma e nei registri interni, richiedendo una suddivisone in banchi (registri, memoria dati) o pagine (memoria programma).

Occorre per prima cosa tenere ben presente che, quando si dice che i PIC16F e 18F sono a "8 bit" , si identifica con questo la lunghezza del byte dati (ovvero sono trattabili elementi numerici da 0 a FFh, 255 decimale). 
Invece, le istruzioni sono lunghe "2 bytes", ovvero 1 word composta da 12, 14 o 16 bit a seconda della famiglia. 
Nel set a 14 bit (PIC16F),  1 word del codice dell' istruzione è composto da due bytes di cui il basso è dei canonici 8 bit, ma quello alto è di soli 6 bit (per un totale di 14 bit, appunto). 
Nei PIC18F, i due "bytes" sono entrambi a 8 bit, dando così un codice istruzione a 16 bit; oltre a questo, sono disponibili alcune istruzioni che occupano 2 word, ovvero 4 bytes.
Quindi, per riassumere, i PIC18F dispongono di dati su un bus a 8 bit e di istruzioni su un bus a 16 bit.

Con 16 bit, se fossero tutti usati per l' indirizzamento, si potrebbe coprire un' area di memoria da 0 a 65 k (FFFFh), mentre con 14 bit si arriverebbe solo a 3FFFh (16 k). 
Se questo è classico con microprocessori che utilizzano un bus per indirizzi e un bus per dati separati tra di loro, ricordiamo che nei PIC la struttura è differente : alcuni bit dell' opcode sono impegnati per definire l' istruzione altri i dati relativi, altri l' indirizzo. 
Questo approccio è solo parzialmente limitativo, perchè non tutte le istruzioni hanno come scopo di toccare locazioni di memoria o registri, mentre l' impacchettamento di tutti gli elementi in una unica word assicura una esecuzione più efficiente e rapida, tanto che gran parte degli opcodes è completata in un solo ciclo macchina.

Ad esempio, l' istruzione per sommare al registro di lavoro W un numero fisso k (ADDLW - ADD Literal to W) viene codificata con la seguente stringa binaria :

   11 111x kkkk kkkk    per il set a 14 bit
0000 1111 kkkk kkkk    per il set a 16 bit

dove l' istruzione in sè è indicata dai primi bit (11111 o 0000 1111), mentre il numero k è indicato dagli 8 bit più bassi (x è un bit non utilizzato nel codice 16F). Questo compattamento di bit permette un notevole risparmio di risorse ed un certo vantaggio nell' esecuzione dei codici, ma si scontra con la necessità di disporre di istruzioni che vadano a lavorare in memoria e sui registri interni diversi dall' accumulatore in modo altrettanto efficace. 

Certamente esistono istruzioni "intrinseche" che non hanno bisogno nè di indirizzo, nè di oggetto, in quanto svolgono una funzione ben determinata ed unica. Ad esempio la sequenza :

   00 0001 0xxx xxxx    per il set a 14 bit
0000 0000 0000  0011    per il set a 16 bit

indica al processore di passare in modalità attesa a basso consumo (SLEEP) : nel set a 14 bit solo i primi 7 bit del codice sono significativi, mentre gli altri restano inutilizzati. Questo è possibile perchè esiste un solo modo per mandare il processore in Sleep e non è necessario un vero e proprio oggetto e relativo indirizzo. 
Se, però, vogliamo, ad esempio, azzerare un qualsiasi registro, sarà necessario specificarne l' indirizzo preciso, visto che ce ne sono molti. La serie di bit :

        00 0001 1fff ffff   per il set a 14 bit
   0110 101a ffff ffff  per il set a 16 bit

comunica al processore di azzerare (clear) il file f (CLRF). Ora, si nota come 7 bit della word sono usati per codificare l' istruzione (0000011 a 14 bit e 0110101 per il 16 bit), mentre ne restano solo 7 per definire l'indirizzo del registro f nell' opcode a 14 bit e 8 nell' opcode a 16 bit. Con 7 bit il massimo numero binario esprimibile è 111 1111  ovvero 3Fh, cioè 127 decimale. Questo vuol dire che questa istruzione può azzerare locazioni di memoria da 0 a 127, ma non oltre; per raggiungere la locazione 128 o 240 sarà necessario utilizzare un qualche altro sistema, come vedremo. Per contro, con 8 bit si arriva a 1111 1111, ovvero FFh, cioè 255 decimale, raddoppiando l'area indirizzabile, ma comunque, per raggiungere destinazioni più lontane, occorre implementare un qualche sistema ausiliario esterno. (Nel codice a 16 bit il bit a è legato a questi meccanismi e serve a specificare una particolare modalità di indirizzamento).

Con tutte le istruzioni che vanno a toccare i registri si presenta questa situazione. Ad esempio :

  01 10bb bfff ffff   per il set a 14 bit
1011 bbba ffff ffff per il set a 16 bit

permette di saltare l' istruzione successiva se il bit indicato da b nel file f è = 0 (BTSSC - Bit TeSt on file, Skip next instruction if Clear), quindi con la possibilità di specificare 1 bit su 8. In entrambi i set, il codice dell' istruzione occupa 4 bit (0110 per il 14 e 1011 per il 16), mentre, come nell' esempio precedente, 7 bit indirizzano il file f a 14 bit e 8 a 16, dando rispettivamente un' area indirizzabile di 127 e 255 . I tre bit b determinano quale degli 8 bit di f va testato, mentre il bit a presente nel set a 16 bit serve come sopra per definire una modalità particolare di indirizzamento.
Un primo punto da considerare, quindi, è quello che l' area di azione nella memori dati di buona parte delle istruzioni è limitata ad una area di 128 bit per il set a 14 e di 256 per quello a 16. Inoltre, questa ampiezza è definita da un numero di bit inferiore a quello di due word : nel PIC abbiamo visto che c'è una "differenza" tra larghezza del "byte" per gli indirizzi e del "byte" per i dati e che, nei "byte" di istruzione, i bit dedicati all' indirizzamento sono solo una parte.

Però questa caratteristica non è costante in tutte le istruzioni del set a 14 bit. Nell' accesso alla memoria programma, l' area indirizzabile è maggiore. Ad esempio,  il codice :

10 0kkk kkkk kkkk   per il set a 14 bit

contiene i primi tre bit (100) che indicano al processore di saltare ad una subroutine (CALL subroutine), la posizione della quale è definita dagli altri 11 bit k. Con 11 bit si può arrivare da 0 a 3FFh, ovvero 1024 (1k) locazioni di memoria, coprendo uno spazio diverso dai casi precedenti; d' altronde le istruzioni BTFSSC e CRLF operano sui registri della memoria dati, mentre la CALL opera sulla memoria programma, che ha dimensioni maggiori. In ogni caso, se la memoria programma da indirizzare supera la possibilità degli 11 bit, occorre anche qui utilizzare un qualche marchingeno addizionale.
Da osservare che la stessa istruzione CALL, nel caso della famiglia 18F, si sviluppa su due word, per un totale di 32 bit, di cui ben 20 (k) sono utilizzati per l' indirizzamento   :

1110  110s  kkkk  kkkk
  1111  kkkk kkkk kkkk

Si nota quindi una primaria differenza tra il set a 14 bit e quello a 16 : la maggiore ampiezza dell' area indirizzabile da quest' ultimo. Per inciso, il bit s specifica una modalità detta Fast.

In effetti il tutto è legato alla struttura della memoria dei PIC :

Memoria 16F 18F Note
pagine bytes pagine bytes
Programma da 1 
a 3
fino a 2 k 1 fino a
128 k
Nella famiglia 16F la memoria programma è segmentata in più pagine raggiungibili modificando degli switches in un apposito registro (PCLATH). Questo è uno dei punti dolenti dei PIC, perchè richiede particolare attenzione da parte dell' utente se la lunghezza del programma eccede una pagina .
Nella famiglia 18F, la memoria programma è organizzata in una sola pagina, raggiungibile grazie alla maggior estensione dell' indirizzamento : non esiste più il problema della paginazione del programma (sospiro di sollievo)
Dati banchi bytes banchi bytes Nella famiglia 16F la memoria dati è frammentata in banchi (da 1 a 4) raggiungibile modificando gli switches RP1:0 dello STATUS.
I registri general purpose e quelli speciali sono suddivisi sui vari banchi e questo è un altro dei punti dolenti dei PIC : per pasare da un registro all' altro occorre agire sugli switches dei banchi.
Nella famiglia 18F la memoria dati è (purtroppo) ancora frammentata in banchi, fino a 16, anche qui raggiungibili modificando degli switches. I banchi, però, hanno ampiezza doppia, dato che le istruzioni a 16 bit permettono di indirizzare 256 bytes e i registri stanno tutti in uno stesso banco, il che rende le cose meno antipatiche. Inoltre esistono modalità diverse di indirizzamento ed istruzioni dedicate alla commutazione dei banchi.
da 1 
a 3 
127
cad
fino a 16  256 
cad

Vedremo più avanti di chiarire come funziona l' indirizzamento della memoria.

 


 

 

 

Copyright © afg. Tutti i diritti riservati.
Aggiornato il 08/11/10.