T&T - PIC

 

 

Tabelle RETLW


Questa pagina richiede il font 7Segments, scaricabile qui.

Le Tabelle RETLW 

Nei PIC, il Program Counter avanza a seconda dell' istruzione incontrata, scandendo la lista del programma in modo automatico.

Però è possibile manipolarne il valore per far si che l' istruzione successiva non sia quella prevista dall' automatismo, ma un' altra.

PC e PCLATH  sono accessibili come normali SFR e quindi il loro contenuto può essere letto e scritto, con istruzioni del genere movwf PCLaddwf PCL, ecc.

Un uso pratico di questa possibilità è la creazione di tabelle che possono essere scandite a seconda di un offset stabilito. La loro funzione è quella di tradurre il valore indicato dall' offset in un numero binario differente.

Più che le parole, un esempio chiarifica bene la questione.

Supponiamo di avere in display a 7 segmenti, a catodo comune, ognuno dei quali è collegato ad un pin di un port del processore.

Ogni volta che noi portiamo a livello 1 un pin, il corrispondente segmento del display si accenderà.

Certamente possiamo dire che ad ognuna delle 256 combinazioni possibili dei valori 1 e 0 dei pin del port corrisponde una specifica situazione di segmenti accesi e spenti.

Ad esempio:

pin PORT

 

Segmenti accesi

  Cifra
7 6 5 4 3 2 1 0 dp G F E D C B A  
0 0 0 0 0 0 0 0                  
0 0 0 0 0 0 0 1               X  
0 0 0 0 0 0 1 0             X    
0 0 0 0 0 0 1 1             X X  
0 0 0 0 0 1 0 0           X      
0 0 0 0 0 1 0 1           X   X  
0 0 0 0 0 1 1 0           X X  
0 0 0 0 0 1 1 1           X X X
                                   

che mette in rapporto i segmenti accesi e il livello logico dei pin del port.

Ora, è chiaro che, tra tutte le possibili combinazioni, solo alcune rappresentano una cifra numerica o una lettera. Nella tabella qui sopra, soltanto la situazione presentata nella quarta riga è identificabile come un 1 e quella nell' ultima riga è identificabile come un 7. Le altre combinazioni non hanno una corrispondenza con caratteri alfanumerici
Volendo usare il nostro display per rappresentare le cifre da 0 a 9 dobbiamo restringere le possibili 256 combinazioni alle sole 10 utilizzabili.

Ne otteniamo la seguente tabella:

pin PORT

  HEX  

Segmenti accesi

  Cifra
7 6 5 4 3 2 1 0     dp G F E D C B A  
0 0 1 1 1 1 1 1   3F     X X X X X X
0 0 0 0 0 1 1 0   06           X X  
0 1 0 1 1 0 1 1   5B   X   X X   X X
0 1 0 0 1 1 1 1   4F   X     X X X X
0 1 1 0 0 1 1 0   66   X X     X X  
0 1 1 0 1 1 0 1   6D   X X   X X   X
0 1 1 1 1 1 0 1   7D   X X X X X X  
0 0 0 0 0 1 1 1   07           X X X
0 1 1 1 1 1 1 1   7F     X X X X X X X
0 1 1 0 1 1 1 1   6F     X X   X X X X

In questa tabella abbiamo associato tre elementi:

  1. la cifra che vogliamo rappresentare con i segmenti accesi
  2. i segmenti accesi necessari a rappresentare la cifra
  3. la parola di 8 bit necessaria da piazzare sul PORT per ottenere quei determinati segmenti accesi

Dunque, nel momento in cui voglio accendere la cifra 8, dovrò porre sul PORT il valore b'01111111' (che in esadecimale è 7Fh).
Così per visualizzare uno 0 dovrò caricare b'001111111' (che è 3Fh). E così via.

Va notato che la corrispondenza tra il numero esadecimale-binario del PORT e i segmenti accesi dipende da come sono collegati fisicamente i pin e i segmenti.
Cambiando le connessioni, ovvero il rapporto tra pin e segmenti, il contenuto della tabella cambierà di conseguenza.

Due considerazioni:

  • sicuramente è più semplice pensare alle cifre-numeri come tali e non come corrispondenti esadecimali dipendenti dalle connessioni fisiche tra in e segmenti. Ed in effetti anche il codice BCD o ASCII  che normalmente si usano per rappresentare cifre all' interno del programma sono in relazione con i numeri reali che rappresentano (ad esempio, 0 in ASCII è 30h, in BCD sarà 03h.
  • possiamo pensare di usare la tabella "manualmente": ogni volta che nel programma ci serve rappresentare un dato numero, caricheremo il PORT con il valore opportuno.
    Ma sarebbe più semplice se il programma facesse questa conversione per noi.

Si tratta allora di inserire nel programma la nostra tabella in modo tale che sia il programma stesso ad utilizzarla per noi, scegliendo la giusta combinazione di bit da applicare a port per ottenere il display voluto.

Uno dei sistemi più semplici per ottenere questo è la creazione di una Tabella RETLW, così chiamata dal fatto che è costituita da una serie di istruzioni retlw numero, dove numero è il valore binario (esadecimale) cercato.

La forma tipica di una tabella RETLW è questa:

;--------------------------------------------------------------
; 7 segments display code Table
;--------------------------------------------------------------
;**************************************************************
;* Table for 7 segment display
;* Displayport: 0 Segment A   AAAAA
;*              1 Segment B   F   B
;*              2 Segment C   F   B
;*              3 Segment D   GGGGG
;*              4 Segment E   E   C
;*              5 Segment F   E   C
;*              6 Segment G   DDDDD
;*              7 Segment dp        dp
GetDigitCode

     addwf   PCL, f

; segments table for high level(common K) drive
; pin       76543210
; segment   pGFEDCBA    pos  hex

    retlw b'00111111'  ; 0 - 0x3F
    retlw b'00000110'  ; 1 - 0x06
    retlw b'01011011'  ; 2 - 0x5B
    retlw b'01001111'  ; 3 - 0x4F
    retlw b'01100110'  ; 4 - 0x66
    retlw b'01101101'  ; 5 - 0x6D
    retlw b'01111101'  ; 6 - 0x7D
    retlw b'00000111'  ; 7 - 0x07
    retlw b'01111111'  ; 8 - 0x7F
    retlw b'01101111'  ; 9 - 0x6F 

La tabella viene "chiamata" semplicemente con un call, avendo cura di caricare WREG con la cifra che si vuole rappresentare. Quindi, ad esempio:

     ... 
    
movlw   .3            ; cifra 3
; display numero

     call    GetDigitCode  ; prendo dalla tabella
disp movwf   DisplayPort   ; e copio sul port di uscita
     ...

La tabella ritorna con il codice corrispondente alla cifra in WREG. 

Molto semplice ed efficace. Ma può ancora essere oscuro come il meccanismo funzioni.

Ricordando quello che conosciamo del funzionamento del Program Counter non è poi così complicato. Vediamolo nei dettagli:

  ... 
 
movlw   .3            ;
in WREG la cifra 3
  call    GetDigitCode  ;
l' istruzione call salva nello stack il valore corrente
                        ; del prossimo passo (
disp) del PC e lo sostituisce con l'
                        ; indirizzo di
GetDigitCode prendo dalla tabella
; il programma lascia la sequenza corrente e passa ad eseguire la
GetDigitCode
  ...
  ...

; Viene eseguita la prima istruzione addwf PCL, f, che modifica il contenuto del PC
;
sommando il valore numerico contenuto in WREG, ovvero 3

GetDigitCode
     addwf   PCL, f

; Ora il PC contiene l' indirizzo dell' istruzione prossima da eseguire, ma 
; aumentato di tre. Di conseguenza sarà eseguita non la linea 

;  retlw b'00111111'  ; PC+0 - 0x3F

; ma la linea evidenziata, che ha indirizzo PC+3

   retlw  b'00111111'  ; PC+0 - 0x3F
   retlw  b'00000110'  ; PC+1 - 0x06
   retlw  b'01011011'  ; PC+2 - 0x5B
   retlw b'01001111' ; PC+3 - 0x4F

; retlw scarica dallo stack l' indirizzo di ritorno salvato dalla call e rientra
; alla label
disp, avendo in WREG il valore b'01001111'(4Fh).
   ...
   ...

; WREG contiene ora valore 4Fh, che, applicato al PORT da cui dipendo i segmenti
; provocherà  l' accensione della cifra 3.

disp  movwf   DisplayPort  

E così per ogni altro entri retlw  della tabella. Ovvero, in modo "meccanico", colleghiamo un indice (offset) inviato attraverso WREG con uno dei valori contenuti nella tabella.
Il meccanismo sfrutta la modifica forzata del PC con la somma dell' offsset.


I limiti delle tabelle RETLW

Questo sistema può essere implementato su qualsiasi PIC 10/12/16/18  e le note seguenti valgono per tutti i PIC indicati (anche se nei PIC18F la Tabella RETLW viene sostituita con grande vantaggio dalle istruzioni di accesso alle tabelle, tipiche del set Enhanced).

Ma esistono alcuni limiti che vanno rispettati:

  1. WREG è un registro a 8 bit, quindi la tabella non può avere più di 255 entries.(1 spazio è occupato dalla addwf PCL,f )
  2. Anche PCL è un registro a 8 bit, quindi il suo contenuto va da 00h a FFh.
  3. Dato che l' istruzione  addwf PCL,f somma al PC corrente il contenuto di WREG, occorre che il risultato di questa somma non sia superiore a FFh, altrimenti occorre modificare anche il PCH.
  4. Se la tabella si trova in una pagina diversa da quella della chiamata, occorre modificare il PCLATH di conseguenza

Dunque è necessario che:

  1. la tabella non sia più ampia di 256 linee
  2. che il suo indirizzo di inizio sia tale per cui la somma con il contenuto di WREG non superi FFh

Ovvero, una tabella che inizia a 0x0FD potrà avere solo 3 linee. Altrimenti la parte che sborda oltre 0x100F farà si che il PC venga a contenere valori che nulla hanno a che fare con la tabella.
Questo perchè, ricordiamo, la scrittura di PCL provoca la copia di PCLATH in PCH, ma l' incremento di PCL effettuato dalla addwf  NON aggiorna di conseguenza il PCLATH. Che dovrà essere aggiornato a aprte, se necessario.
Cos' pure se la call  genera un salto di pagina, occorre che il PCLATH sia modificato opportunamente, altrimenti il salto avverrà nella stessa pagina chiamante, con le relative conseguenze..

Quindi le tabelle RETLW sono impiegabili senza alcuna manipolazione del PCLATH se:

  • sono situate nella pagina chiamante
  • non sono a cavallo tra due pagine

Negli altri casi occorrerà manipolate il PCLATH.

Ed occorrerà una struttura diversa per tabelle più ampie di FFh.

 


Le tabelle RETLW nei PIC18F

Abbiamo detto che nulla osta all' utilizzo delle tabelle RETLW per i PIC18F, anche se per questa famiglia il set di istruzioni offre una serie di opcodes pensati proprio per la gestione delle tabelle e molto più pratici del sistema fin qui dettagliato.

In ogni caso, ci si può trovare a dover inserire una brevissima tabella oppure a dover convertire un sorgente scritto per PIC16 e trovare più comodo mantenere la struttura RETLW.
In questo caso è necessaria una ulteriore considerazione:

Le istruzioni dei PIC Enhanced sono codificate su 2 o 4 bytes, ovvero sempre su un numero pari di bytes.
Quindi l' accesso alla memoria programma attraverso il RETLW avviene sugli indirizzi pari, dato che il bit 0 del Program Counter è sempre a 0 (e punta quindi solo a indirizzi pari).

Ne risulta che la tabella RETLW vista in precedenza, in un PIC16 viene assemblata come: (ved. Nota più avanti)

Indirizzo Contenuto Istruzione
00000A 0782 addwf PCL, f
00000B 34C0 retlw b'00111111'
00000C 34F9  retlw b'00000110'
0000D 34A4 retlw b'01011011'
0000E  34B0 retlw b'01001111'
0000F 3499  retlw b'01100110' 
000010 3492 retlw b'01101101'
000011 3482 retlw b'01111101'
000012 34F8 retlw b'00000111'
000013 3480  retlw b'01111111'
000014 3490 retlw b'01101111'

Va notato che la memoria programma è organizzata in "bytes" da 12 o 14 bit per cui la cifra esadecimale dell'opcode (contenuto) è lunga al massimo 12 o 14 bit e occupa una sola locazione.

Ma in un PIC18F la memoria programma è organizzata in bytes da 8 bit per cui la cifra esadecimale dell'opcode (contenuto), che è lunga (al minimo) 16 bit, occupa DUE locazioni.
Quindi la tabella diventa: (ved. Nota più avanti)

Indirizzo Contenuto Istruzione
00000A 26F9 addwf PCL, f
00000C 0C3F retlw b'00111111'
00000E 0C06 retlw b'00000110'
000010 0C5B retlw b'01011011'
000012  0C4F retlw b'01001111'
000014 0C66 retlw b'01100110' 
000016 0C6D  retlw b'01101101'
000018 0C7D retlw b'01111101'
00001A  0C07 retlw b'00000111'
00001C  0C7F  retlw b'01111111'
00001E 0C6F retlw b'01101111'

Ovvero ogni linea della tabella occupa 2 bytes e il passaggio da una linea all' altra necessita di un incremento del PC non di una unità, ma di 2.

Ne deriva che l' entry per la tabella, per un PIC18F dovrà essere modificata così::

GetDigitCode
   
rlncf   WREG, f   ;<-- raddoppia il puntatore
     addwf   PCL, f

; segments table for high level(common K) drive
; pin       76543210
; segment   pGFEDCBA    PC+  hex

    retlw b'00111111'  ; 0 - 0x3F
    retlw b'00000110'  ; 1 - 0x06
    retlw b'01011011'  ; 2 - 0x5B
    retlw b'01001111'  ; 3 - 0x4F
    retlw b'01100110'  ; 4 - 0x66
    retlw b'01101101'  ; 5 - 0x6D
    retlw b'01111101'  ; 6 - 0x7D
    retlw b'00000111'  ; 7 - 0x07
    retlw b'01111111'  ; 8 - 0x7F
    retlw b'01101111'  ; 9 - 0x6F 

Va da se che, essendo sempre il WREG a 8 bit, l' ampiezza possibile della tabella sarà dimezzata (dato che le linee occupano il doppio di spazio).

E restano validi tutti i limiti descritti prima: anche se i PIC18F non hanno paginazione della memoria programma, ugualmente il meccanismo del PC non prevede un aggiornamento della parte alta dopo una somma sulla parte basse.


 



Va notato che l' ampiezza della memoria  programma, così come quella del codice di una istruzione dei PIC è differente a seconda della famiglia.

I PIC16F hanno memoria programma e codice istruzioni a 14 bit
I PIC18F hanno memoria programma e codice istruzione a 16 bit

Questo vuol dire che il "byte" della memoria programma dei PIC16 è ampio non 8, ma 14 (o12) bit. E questa è l' ampiezza del bus istruzioni, in modo tale che l' intero opcode viene trattato in un solo passaggio.
Potremmo dire che il "byte" istruzioni è di 14 (o12) bit.

Mentre il byte della memoria programma dei PIC18F è 8 bit, configurati però come word da 16 bytes. E questa è l' ampiezza del bus istruzioni, in modo tale che anche qui l' intero opcode viene trattato in un solo passaggio, con una word da 16 bit.

Ne deriva che il codice di una istruzione (ampio 12 o 14 bit) nei PIC16F occupa una cella di memoria programma (ampia 12 o 14 bit).
E, partendo il Vettore del Reset da 0000h,  può collocarsi ad indirizzi sia pari che dispari, a seconda della lunghezza dell' opcode, dato che esistono anche istruzioni a due "bytes"

Mentre il codice di una istruzione nei PIC18F occupa due celle di memoria da 1 byte ciascuna, per un totale di 16 bit. E, partendo il Vettore del Reset da 0000h,  può collocarsi solo ad indirizzi pari.
E questo vale anche per le istruzioni lunghe 2 words, che, occupando 32 bit = 4 bytes, iniziano sempre ad indirizzi pari.

 


Argomenti collegati:


 

     

Copyright © afg . Tutti i diritti riservati.
Aggiornato il 19/05/11 .