Trasmettere a distanza più
segnali.
|
Passiamo il sorgente ad altri PIC (+ un addendum al ricevitore 7
segmenti).
Terza ed ultima puntata sull' argomento.
Lo scopo di queste pagine è
essenzialmente uno: far comprendere che, in moltissimi casi, è possibile
spaziare su molti più chip di quelli con cui si ha a che fare comunemente.
In particolare per i principianti che, all' inizio, copiano as-is una
realizzazione vista sul WEB. Cosa corretta: si impara dal lavoro di chi è
più avanti, ma, dato che questo ha la possibilità di essere molto datato, si
finisce per usare sempre gli stessi chip altrettanto datati se non decisamente
obsoleti (16F84, 12F508, 16F876/77, 16F628, ecc), andando a spendere più di
quello che è il costo di un componente recente e perdendo la possibilità
di sperimentare, o anche solo conoscere, le molteplici prestazioni e funzioni
che questo offre rispetto ai vecchi prodotti.
Il fatto di trasportare programmi da un chip ad un altro dello stesso
costruttore non è niente di magico, per le ragioni che saranno indicate; ma
se queste ragioni non sono conosciute finisce per mancare lo stimolo all'aggiornamento, che è essenziale in una materia come quella dei
microprocessori e microcontroller, in continua evoluzione.
Non abbiamo i PIC indicati nei sorgenti...
... ma ne abbiamo altri. Possiamo adattare il firmware senza troppi
problemi?
La risposta è: "probabilmente sì".
Le chiavi della traslazione del sorgente da un chip ad un altro stanno
essenzialmente in questo:
- famiglia di appartenenza del chip
- risorse integrate (essenzialmente funzioni analogiche)
- mappa della RAM
Da punto 1 dipende il set di istruzioni usate.
Possiamo dire che, per i PIC a 8 bit, si tratta di set di istruzioni
crescenti, ma omogenei, in 4 gradini:
- Baseline
- Midrange
- Enhanced Midrange
- PIC18F
ovvero, in linea di massima, ogni famiglia contiene tutte le istruzioni della precedente e le
amplia aggiungendo altri opcode.
Certamente EnhancedMidrange e PIC18F possono
disporre di istruzioni che non esistono nelle altre famiglie e questo potrebbe
complicare le cose se dobbiamo portare un programma scritto per questi sui PIC
minori (Baseline e Midrange). Ma non è un ostacolo la direzione inversa: nei
set di istruzioni dei PIC maggiori sono comprese tutte le istruzioni di quelli
minori; quindi, portare un programma da un Baselie a un PIC18F non è
impossibile, anzi.
Ci sono, ovviamente, degli ostacolo, come ad esempio le istruzioni OPTION
e TRIS che esistono solo nei Baseline,
ma nelle altre famiglie la sostituzione con i corretti opcodes è immediata:
dato che i due registri sono mappati in RAM, basterà un
normale movwf. Se opcodes
inadeguati vengono inseriti nel
sorgente, l' Assembler MPASM ne segnala la non congruità e in alcuni casi li
può sostituire direttamente (ad esempio return
con retlw 0 per i Baselien).
Quindi la prima regola è:
- E' possibile spostare con semplicità un sorgente scritto per un chip
con un certo set di istruzioni verso un altro chip con un set di
istruzioni superiore.
L'inverso può essere possibile, ma richiede di sostituire le istruzioni
mancanti o con una variazione della logica degli algoritmi di cui fanno aprte
o con diverse altre istruzioni.
Dal punto 2 dipendono le azioni che dobbiamo mettere in atto per arrivare a
disporre pienamente degli I/O digitali. Ricordiamo che nella filosofia
di base di Microchip c'è l' idea di minimo consumo al default del POR, per
cui:
- tutti gli I/O configurabili come analogici, sono definiti in questo modo
- tutti gli altri sono definiti come ingressi digitali
- tutti i moduli non indispensabili sono spenti
Ne deriva la necessità di individuare quali siano le funzioni che
impediscono l' accesso ai pin come semplici I/O digitali e le le manovre
necessarie per ottenere questo. Solitamente basta uno sguardo alle primissime
pagine del foglio dati per identificare immediatamente la presenza di
analogiche, ovvero dei comparatori e dell' ADC.
Possono poi esserci altre differenze hardware caratteristiche di singoli
chip, tra cui si possono ricordare:
- la necessità di un oscillatore esterno (vecchi chip come 16F84,
16F876/77, ecc.).
- l' impossibilità di usare il pin MCLR come input, sempre per vecchi.
PIC
- la gestione di interrupt
- la possibilità di usare Timer 0 a 16 bit
La necessità dell'oscillatore esterno riduce di 2 unità il numero dei pin
disponibili come I/O, dato che in gran parte dele applicazioni l'oscillatore
interno dei chip meno "antichi" è più che adeguato.
Altrettanto la funzione di I/O sul pin MCLR.
Per quanto riguarda gli interrupt, è ben difficile che si possa spostare un
programma scritto con una gestione interrupt su un processore che ne sia
privo: la cosa, al minimo, richiede la riscrittura completa della logica di
funzionamento.
Per quanto riguarda l'ultimo punto, va precisato che si tratta
essenzialmente di funzioni dei PIC18F o degli Enhanced Midrange, nei quali,
però, i default fanno si che la posizione iniziale al Power On ne permetta l'
uso in legacy, ovvero in un modo del tutto compatibile con le versioni meno
dotate; ad esempio, il Timer0, pur potendo operare a 16bit, per default
funziona a 8 bit e quanto scritto per altri Timer0 che non hanno questa
opzione è adatto senza modifiche (però sparisce il registro OPTION_REG,
sostituito da uno specifico, dedicato al controllo del timer).
Esistono poi delle trappole di vario genere; tanto per citarne alcune:
- la funzione open drain per RA4, presente su vecchi modelli obsoleti
- l'oscillatore interno che per default, in vari chip recenti, è a
frequenze diverse da 4MHz
- la diversa destinazione di alcuni pin per usi speciali, come i port per
USB, che rende i chip non compatibili con il pinout degli altri con lo
stesso package.
- diversità nella label riservate per la definizione del config iniziale
che generano errori nella compilazione
- la presenza di weak pull-up abilitati o disabilitati a seconda dei chip
Per quanto riguarda periferiche non analogiche, la filosofia di Microchip
è quella di una "legacy" con i modelli meno dotati e dell'
onnipresente principio del minimo consumo, il che comporta la disabilitazione
per default di queste funzioni; se ne abbiamo bisogno, occorre
"accendere" il modulo richiesto e configurarlo. Altrimenti è come
se non ci fosse.
Questo vale in generale per CCP, MSSP, VREF, ecc, come pure per la presenza di
EEPROM, per gli interrupt o altre particolarità specifiche della struttura di
una data famiglia di chip.
Quindi, davanti ad un chip con un numero elevato di moduli e un foglio dati da
400 pagine non è il caso di scoraggiarsi: le funzioni, al di là delle
analogiche (comparatori e ADC) è generalmente disabilitata per default e se
non la usiamo è come se non fosse presente.
In generale vale il seguente principio:
- Il programma scritto per un chip di una famiglia può essere trasferito ad
chip appartenente ad una superiore senza troppi problemi. Il contrario però
può non essere possibile.
Ad esempio, se ho un programma che impiega interrupt a due livelli di
priorità, potrò farlo girare solo su PIC18F, dato che le altre famiglie non
hanno questa funzione. Se ho un programma che usa interrupt ad un livello,
potrò adattarlo a tutte le famiglie, esclusi i Baseline che non gestiscono
interrupt. Se ho un programma che non usa interrupt potrà con grandi
probabilità essere fatto girare su tutti i chip.
Così, ovviamente, non potrò fare cose impossibili, come spostare programmi
che usano ADC o moduli di comunicazione seriale su chip che non ne dispongono
e così via per tutti i vari USB o LIN o Ethernet o LCD, che sono moduli
specifici solo di alcuni chip specializzati.
Il punto 3 riguarda la mappatura della RAM, che può iniziare in posizioni
diverse a seconda del componente, ma vedremo che si tratta di un problema
facilmente risolvibile.
A riguardo della memoria, va considerato che se nei Baseline esistono forti
limitazioni per le chiamate goto e call, dovute alla struttura del Program
Counter e delle istruzioni codificate su soli 12 bit, nei Midrange queste
limitazioni sono decisamente minori e molto lievi nei 18F, dove non ci sono
pagine in memoria.
Anche la situazione degli SFR può creare situazioni di difficoltà all'
utilizzatore, dato che, per le famiglie superiori ai Baseline, è comune
avere la zona RAM frammentata in più banchi (anche 32 negli Enhanced Midrange)
il che mette in difficoltà il programmatore Assembly con la continua
richiesta di cambio dei banchi.
Per quanto riguarda Baseline e Midrange, possiamo riportare un esempio dei
mappa delle risorse.
Ecco quelle di un Baseline (12F505) minimale e di un Midrange (16F628):
Se consideriamo gli Enhanced Midrange o i 18F abbiamo una
disponibilità di risorse quanto mai maggiore. Ecco, ad esempio, quelle di
16f1503:
Dove non vengano usate funzioni particolari, va però detto che la
filosofia generale dei PIC a 8 bit pone in banco 0 i registri dei PORTx, che
devono essere usati in continuazione nel programma, mentre in banco 1 si
trovano i registri TRISx di direzione, il cui uso è meno intenso, limitandosi
generalmente alla sola fase di inizializzazione della situazione degli I/O.
Per gli altri SFR, anche se è normale che i registri primari, come STATUS e
FSR siano accessibili allo stesso modo da tutti i banchi, è opportuno dare
una occhiata alle tabelle della mappa della memoria onde evitare di
prendere abbagli e di incorrere in bug difficili da diagnosticare.
Ci sarebbe ancora moltissimo da dire, anche perchè il numero dei modelli
di PIC prodotti è elevato e vengono aggiunte risorse e strutture sempre
nuove; la casistica è molto ampia e diventa necessaria una buona conoscenza
dei vari chip nel momento in cui si intendono usare risorse non comuni. Però,
in sostanza, possiamo dire che:
- meno risorse usa il programma da
spostare, meno sarà problematica la sua migrazione da un chip ad un
altro.
In particolare, l'uso delle pseudo macro dell' Assembler MPASM (banksel,
pagesel, bankisel) consente di scrivere sorgenti portabili
facilmente. Il contrario, no.
Ad esempio, la commutazione dei banchi, in Baseline e Midrange avviene con
uno o due bit dello STATUS, ma negli Enhanced Midrange e nei PIC18 questi
bit non esistono più. Se si è usata una manipolazione diretta di questi
bit, magari con le solite macro aggiunte (Bank0 e simili), occorrerà
modificare manualmente tutti i punti dove queste sono presenti. Se, invece,
è stato usato il banksel, MPASM provvede
a compilarlo con i giusti opcodes per ogni singolo processore; così, in un
Baseline banksel 1 porterà a 1 il bit
RP0, per un Enhanced scriverà 1 in BSR: il codice è immediatamente
portabile senza modifiche.
I nostri RX e TX.
Abbiamo visto che il sorgente per i Baseline impiegati nella trasmissione
sul cavo è stato scritto specificamente per impiegare il minimo di risorse,
sia come registri che come struttura logica e funzionale.
Per svolgere il suo lavoro non usa interrupt (dato che i Baseline non ne
hanno...), non usa periferiche speciali (i Baseline sono chip piuttosto
"poveri"), non usa istruzioni particolari (i Baseline hanno il set
minimo), usa una quantità minima di RAM e di memoria, tale da non mandare in
crisi anche il chip più misero; non usa EEPROM, nè altro di particolare.
L' unica periferica chiamata nel ricevitore è Timer0 (ma se ne potrebbe anche
fare a meno), che esiste praticamente identico in tutti i chip.
Uniche particolarità sono l' uso del pin MCLR come ingresso e l'
oscillatore interno.
Possiamo allora affermare subito che passare il sorgente ad altri Baseline è
del tutto automatico. Abbiamo già visto come i sorgenti siano compilabili
direttamente per vari chip.
Baseline.
Passare i sorgenti ad altri Baseline è del tutto immediato, tanto che è
stato semplice scrivere qualcosa di adatto a più di un processore nello
stesso sorgente.
Se si usano chip con più di 8 pin, basterà adattare i collegamenti di I/O in
modo da replicare la situazione del GPIO per non avere necessità di
modificare la logica di funzionamento del programma. Ovviamente sarà
necessario adattare la definizione del processore e verificare se non ci sono
situazioni "strane" su I/O e memoria, ma dovrebbe sempre trattarsi
di modifiche minimali, dato che i componenti della famiglia Baseline sono
piuttosto uniformi.
Midrange - l'esempio del noto (e vetusto)
16F84A...
Anche passare i sorgenti da Baseline a Midrange non è un problema, in
quanti questi sono i "fratelli maggiori" dei primi e ne comprendono
tutte le funzioni. Quindi non capita di non disporre di una risorsa prevista
dal programma.
Iniziamo allora (purtroppo) con il più noto dei Midrange, il
16F84A (consideriamo questo e non 16F84 dato che esso dovrebbe essere
disponibile solo nei musei della storia dell' elettronica. Comunque le
differenze sono trascurabili).
Vediamo le caratteristiche del chip: si tratta di un prodotto extra vecchio
e quindi assai primitivo rispetto ai Midrange più recenti.
Gli elementi salienti, visibili nelle primissime pagine del foglio dati, sono:
- è un 18 pin, con gli I/O organizzati in due PORT
(PA e PB)
rispettivamente a 4 e 8 bit. Quindi le risorse come numero di I/O ci sono
in abbondanza.
- Non ha oscillatore interno e richiede componenti esterni.
- Il pin MCLR è dedicato e non
corrisponde a nessun port
- Ha il Timer0
- Non ha nessuna analogica, per cui l' accesso ai pin come I/O digitali è
diretto
- Ha interrupt e EEPROM, ma queste non ci interessano
- Ha la verifica del on-change pin e un ingresso di interrupt, ma sono
funzioni che non usiamo
- La memoria è di 1K in un unica pagina; non occorrono switch di pagina,
nè ci sono le limitazioni dei Baseline
- La memoria RAM e gli SFR sono su due banchi, ma il banco 1 riguarda solo
i registri della EEPROM (che non usiamo) mentre la RAM e gli altri
registri sono speculari sulle due pagine; non occorre alcun cambio di
pagina.
L' OPTION_REG ha struttura del tutto
simile a quella dei Baseline e gli switch per T0CKI,
l' assegnazione del prescaler e del suo valore sono nelle stesse posizioni,
per cui valgono le stesse inizializzazioni.
16F84A è un Midrange povero, in pratica un Baseline con l' aggiunta dell'
interrupt e un set di istruzioni più esteso.
Dunque il passaggio del sorgente è praticamente immediato.
Hardware TX - 16F84A
Data la diversa disposizione dei pin (chissà per quale ragione i 18 pin
non sono sovrapponibili ai 20/14/8) e la diversa distribuzione dei port
richiedono un diverso schema elettrico:
Usiamo i primi 6 bit di PORTB con le
stesse funzioni del GPIO dei Baseline a 8 pin.
PORTA è inutilizzato.
Nulla vieta di utilizzare altri pin in qualsiasi combinazione, ma questa è la
più semplice.
Per quanto riguarda l' oscillatore, anche se è possibile utilizzare un RC
esterno, meglio usare un cristallo, dato che non è per nulla semplice
realizzare un RC che origini 4MHz all' 1% e mantenga questa taratura
col variare della temperatura. L' uso di condensatori di precisione NP0 e
resistenze a strato metallico è ideale, ma il costo finisce per superare
quello di un comune risonatore ceramico.
|
Questo non è preciso nè stabile come un quarzo, ma
nella versione a tre pin è un elemento assai comodo ed economico,
contenendo anche i condensatori necessari all' oscillatore e generando
una frequenza di precisione e stabilità più che adeguate per
questa applicazione. |
La frequenza sarà 4MHz, dato che per questo valore sono calcolate le
routines di tempo; nel caso in cui si utilizzino quarzi o risonatori con una
frequenza diversa basta modificarle.
Ecco un possibile circuito stampato unico, adatto per TUTTI i chip a 18 pin.
|
Al posto del solito ingombrante cristallo HC49 si potrà usare il
risonatore, eliminando i condensatori E$5/E$6. |
Il software.
Ecco il sorgente, con evidenziate le linee che presentano una differenza,
concentrate nella parte iniziale del sorgente, iniziando dalla definizione del
processore
; scelta
del processore
LIST p=16F84A
#include <p16F84A.inc> |
Potrebbe essere utile impiegare i weak pull-up che il chip mette a
disposizione. La scelta è effettuata con il bit 7 di OPTION_REG
:
;
Option_Reg - disabilita T0CKI e prescaler a Timer0
movlw b'01010111' ; si
pullup, presc.256
movwf OPTION_REG |
Questo può essere utile per avere pull-up sui pin di ingresso senza
aggiungere resistenze esterne. Se l' opzione non serve, basta portare a 1 il bit
7.
|
In particolare occorre ricordare che i weak pull-up
integrati non sono resistenze, ma MOSFET con una elevata resistenza
drain-source (20-100K); solitamente non hanno nessuna contro
indicazione; sono ideali per ingressi da pulsanti e open collector o
anche logiche CMOS.
Però è possibile (anche se molto improbabile) che , essendo
elementi attivi, si possano creare problemi quando gli ingressi sono
pilotati da qualche logica "strana" e quindi ecco la
possibilità di disabilitarli.
|
Da notare che tutti i pin di PORTB hanno un weak pull-up e sono tutti
abilitati o disabilitati contemporaneamente, ma diventano attivi solo quelli
sui pin configurati in TRISB come
ingressi.
La differente struttura dei port ci fa passare da GPIO a PORTB:
;---------------------------------------------
;inizializzazione I/O
clrf PORTA ; clear port
clrf PORTB
clrf sGPIO
; clear shadow
; Direzione I/O
; I pin non usati sono
configurati come uscite per
; evitare la captazione di disturbi.
movlw b'00000000' ; PORTA out
movwf TRISA
movlw b'00001111' ; RB0-3 in,
altri out
movwf TRISB |
quindi:
movf
sGPIO,W ; set output
movwf
PORTB ; questo spegne
anche il LED |
Nessuna modifica è necessaria alle altre righe !
Osserviamo che nel complesso le variazioni riguardano solamente ovvietà,
ovvero:
- la definizione del processore
- il suo config specifico
- le assegnazioni degli I/O
Va aggiunta anche la necessità di sostituire le istruzioni OPTION
e TRIS il cui uso è limitato ai
Baseline.
Non occorre neppure modificare l' inizio RAM, dato che quella di 16F84A parte
a 0Ch e quindi 10h è nell' intervallo utile.
Hardware RX - 16F84A
Data la diversa disposizione dei pin e la diversa distribuzione dei port
anche qui si richiede un diverso schema elettrico:
L' assegnazione dei pin non è certo ottimale, ma permette una diretta
compatibilità con quanto scritto per i Baseline a 8 pin, sempre considerando i
primi 6 bit di PORTB come sostituti del GPIO.
Il software RX - 16F84A.
Ecco le differenze rispetto alla versione per Baseline.
Ovviamente ancora per prima la definizione del processore e config come già
visto, mentre la seconda riguarda le assegnazioni degli I/O. Utilizziamo delle
assegnazioni apparentemente strane, ma che ricalcano perfettamente la situazione
dei Baseline a 8 pin:
;**************************************************************
;==============================================================
; DEFINIZIONE DI IMPIEGO DEI PORT
;==============================================================
;
;PORTB
;
#define D0 PORTB,RB0
; out dati paralleli
#define D1 PORTB,RB1
#define D2 PORTB,RB2
#define D3 PORTB,RB4
#define serin PORTB,RB3 ; in seriale
#define LED PORTB,RB5 ;
out LED
; PORTA non è usato |
Inizializziamo i port:
;---------------------------------------------
;inizializzazione I/O
clrf PORTA ; clear port
clrf PORTB
clrf sGPIO
; clear shadow
; Option_Reg - disabilita T0CKI e prescaler a Timer0
movlw b'11010111' ; no pullup,
presc.256
movwf
OPTION_REG
; Direzione I/O
; I pin non usati sono
configurati come uscite per
; evitare la captazione di disturbi.
movlw b'11111111' ; PORTA out
movwf TRISA
movlw b'00001000' ; RB3 in,
altri out
movwf TRISB |
e
movf
sGPIO,W ; set output
movwf
PORTB ; questo spegne anche il
LED |
Nessuna modifica nelle altre righe !
Osserviamo che anche qui le variazioni riguardano gli stessi elementi visti
prima.
Non ci sono variazioni nella logica delle istruzioni del programma vero e
proprio.
Midrange - 16F628.
Un altro dei must nell' ambito dei "processori d'annata" è il
16F628.
Successore del 16F84A, è quasi altrettanto obsoleto, ma presenta almeno
qualche caratteristica più avanzata. Si sempre di un Midrange, ma meno
spartano del primo:
- sempre a 18 pin, con gli I/O organizzati in due PORT
(PA e PB)
entrambi a 8 bit.
- Ha oscillatore interno
- Il pin MCLR è configurabile come input
- Ha il Timer0
- Ha interrupt e EEPROM, UART, CCP e Vref, oltre ad altri due timer, ma
queste funzioni non ci interessano
- Dispone di comparatore, che andrà disabilitato
- Ha la verifica del on-change pin e un ingresso di interrupt, ma sono
funzioni che non usiamo
- La memoria è di 2K in due pagine, ma per questa applicazione non
occorrono switch di pagina, nè ci sono le limitazioni dei Baseline
- La memoria RAM e gli SFR sono su 4 banchi; in questo va prestata
attenzione, in quanto i registri TRISx stanno in in banco 1 e non in banco
0 come i PORTx..
Anche qui l' OPTION_REG ha la stessa
struttura di quello del 16F84A e gli switch per T0CKI,
l' assegnazione del prescaler e del suo valore sono nelle stesse posizioni,
per cui valgono le stesse inizializzazioni.
Non usando nè interrupt, ne EEPROM, la gestione di queste parti, per default
disabilitate, non ci interessa.
Anche se 16F628 è un sostituto più evoluto di 16F84A, il passaggio del
sorgente è praticamente immediato, anche se occorre prestare attenzione a due
punti.
Hardware TX - 16F628.
La stessa disposizione di 16F84A. Si può usare lo stesso circuito stampato
che si è eventualmente realizzato per 16F84A e che è adatto a qualsiasi chip
a 18 pin.
Avendo disponibile un oscillatore interno possiamo risparmiare i componenti
esterni: nello schema sopra non sono indicati; basterà impostare la scelta
nella configurazione. Altrimenti si può mantenere l' oscillatore
ceramico o il quarzo usati in precedenza, sempre adeguando il config. Ne
parliamo qualche riga più sotto.
Ugualmente si può anche eliminare la R2 se si disabilita MCLR, sempre dal
config.
Però è possibile realizzare uno stesso circuito stampato attorno allo
schema indicato per il 16F84A e questo sarà adeguato per TUTTI i chip a 18
pin.
Il software TX -
16F628.
Ecco le differenze rispetto alla versione per Baseline. Ovviamente per prima
la definizione del processore:
; scelta
del processore
LIST p=16F628
#include <p16F628.inc> |
La seconda, come per 16F84A riguarda le assegnazioni degli I/O. Se non
utilizziamo il pin MCLR, possiamo mantenere le stesse assegnazioni
precedentemente usate ericalcare quanto scritto per 16F84A.
Per 16F628 l' assegnazione della RAM deve essere variata:
;*************************************************************
;=============================================================
; Variabili RAM
;=============================================================
;
CBLOCK
0x20 ; RAM start
sGPIO
; buffer temporaneo PORTB
d1
; counter per delay
d2
ENDC |
Altra modifica essenziale è quella del config, che va adeguato alle risorse
specifiche del chip
;==============================================================
; CONFIGURAZIONE =
;==============================================================
; Oscillatore interno, no WDT,
PWRT on, BOBE on, no CP, n
__config _HS_OSC & _WDT_OFF & _PWRTE_ON
& _BODEN_ON & _LVP_OFF & _MCLRE_ON & _CP_OFF |
Qui ci si presentano alcune scelte:
- usare l' oscillatore interno come per i Baseline visti in precedenza o
quello esterno come per il 16F84A. Dal punto di vista del programma, la
scelta è indifferente. Si tratta solo di assegnare la giusta scelta nella
riga di configurazione
- a differenza di 16F84A, il pin MCLR è utilizzabile come ingresso; però
può essere utile mantenere la stessa struttura usata per il 16F84A, dato
che qui MCLR è alternativo a RA5
Se abbiamo realizzato un circuito stampato per il 16F84A possiamo
utilizzare lo stesso, senza alcuna modifica, per tutti i 18 pin. Quindi
possiamo continuare ad impiegare l' oscillatore esterno e il pin MCLR, anche
se non necessari. In particolare, va osservato che l' oscillatore interno di
16F628 non ha un registro di calibrazione, con il rischio di risultare poco
preciso; però, nella nostra applicazione, i tempi di sustain dei bit
trasmessi sono 1000 volte (1ms) maggiori del ciclo di istruzione (1us) e non
dovrebbero esserci problemi di sincronizzazione anche con oscillatore meno
preciso dell' 1%.
la scelta del modo di oscillatore dipende dalla riga di config.
Analogo discorso per i weak pull-up che questo chip permette di abilitare
su PORTB.
La selezione è sempre il bit 7 dell' OPTION_REG
.
Un punto "dolente", causa di disperazione per i super
principianti, riguarda le analogiche: 16F628 ha un comparatore e quindi questo
ha la precedenza nei default rispetto alla semplice funzione digitale dei pin.
No problem, basta disabilitare:
;
Disabilita comparatori
movlw
0x07
;disabilita comparatori
movwf CMCON |
Ma occorre ancora attenzione: come tipico dei PIC non Baseline, i registri
TRISx, a differenza di 16F84A, non sono in banco 0, ma in banco 1, per cui:
banksel TRISA
movlw b'11111111'
; PORTA out
movwf TRISA
movlw b'11110000'
; PORTB7-4 out, altri in
movwf TRISB
banksel 0 |
lasciando fare il lavoro"sporco" della commutazione dei banchi a
banksel e ricordandosi di riportare l'azione in bank0.
Ultima azione, come per il 16F84A, è l' uso diverso dei PORT, dove
PORTB sostituisce GPIO:
;---------------------------------------------
Main bcf
LED
; LED 0ff
bcf serout
; serial out = 0
call Delay100ms
; delay 100ms
movf PORTB,W ; salva stato I/O
movwf sGPIO
bsf
LED ; LED on
durante la trasmissione |
Nessuna modifica nelle righe successive!
Osserviamo che le variazioni riguardano sempre e solo gli elementi prima
visti, a cui si aggiunge:
- la necessità di escludere il comparatore
- l' adattamento della RAM
- la necessità di commutare i banchi per accedere a certi SFR.
Hardware RX - 16F628.
Utilizziamo lo stesso schema usato per 16F84A. Il circuito stampato può
essere lo stesso utilizzabile per qualsiasi 18 pin:
Disponiamo sempre i collegamenti in modo tale che PORTB sostituisca GPIO.
Questo consente di impiegare la stessa logica senza modifiche.
Come sopra, se si usa l' oscillatore interno non servono componenti
esterni: basterà impostare la scelta nella configurazione, ma si può usare
lo stesso stampato con l' oscillatore esterno installato, sempre adeguando il
config iniziale.
Ugualmente si può anche eliminare la R2 se si disabilita MCLR dal config.
PORTA non viene usato.
Il software RX - 16F628.
Ecco le differenze rispetto alla versione per Baseline.
Valgono le stesse modifiche iniziali già viste per il trasmettitore:
- la definizione del processore
- il config
- l'inizio della RAM
- le assegnazioni degli I/O.
Utilizziamo delle assegnazioni apparentemente strane, ma che ricalcano
perfettamente la situazione dei Baseline a 8 pin:
;**************************************************************
;==============================================================
; DEFINIZIONE DI IMPIEGO DEI PORT
;==============================================================
;
;PORTB
#define D0 PORTB,RB0 ; out dati paralleli
#define D1 PORTB,RB1
#define D2 PORTB,RB2
#define D3 PORTB,RB4
#define serin PORTB,RB3 ; in seriale
#define LED PORTB,RB5 ; out LED |
Inizializziamo i port come già visto, eliminando il comparatore e dando la
direzione voluta ai pin:
;
Disabilita comparatori
movlw
0x07
;disabilita comparatori
movwf CMCON
; Direzione I/O
banksel TRISA
movlw b'00000000'
; PORTA out
movwf TRISA
movlw b'00001000'
; PORTB3 in, altri out
movwf TRISB
banksel 0 |
Nessuna modifica nelle altre righe!
Il rapporto tra segnali e pin ricalca quello dei Baseline a 8 pin e quindi
resta identica la logica.
Osserviamo che le modifiche riguardano sempre e solo gli elementi già
visti e non ci sono variazioni nella logica delle istruzioni del programma
vero e proprio.
Note.
In effetti sono stati forniti sorgenti adatti contemporaneamente per
entrambi i chip, ma non solo. Sono accomunati:
- 16F84A
- 16F627
- 16F628
- 16F627A
- 16F628A
- 16F648A
con lo stesso sistema di selezione già visto, basato sulla definizione del
processore nel progetto. Questo perchè le differenze che i chip presentano
per questa applicazione sono limitate solamente alla solita necessità
iniziale di definire il modello, la configurazione e dove necessario,
disabilitare le analogiche.
Siccome la RAM di 16F84A va da 0Ch a 4Fh e quella degli altri si estende da
20h a 7Fh (banco0), è stato scelto di usare 3 bytes a partire da 20h, area
comune a tutti, il che permette di non modificare neppure questa assegnazione.
Una precisazione: con il sistema visto si possono scrivere sorgenti comuni
a molti PIC, ma non è il caso di esagerare: se le risorse sono limitate come
in questi esempi, sono necessarie anche poche selezioni #ifdef, ma se si
accomunano troppi chip differenti o l' applicazione utilizza risorse
complesse, il risultato è quello di ottenere un sorgente ben poco leggibile.
Qui si sarebbero potuti aggiungere facilmente 16F87, 16F88 (che dispone di ICD),
16F716, ecc., con, però, un aggravio di linee di selezione, anche solo per il
tipo di processore o in config.
Quindi, volendo scrivere sorgenti comuni a vari modelli è il caso di
accomunare in un gruppo componenti che abbiano risorse e struttura quanto più
simili possibile, in modo da minimizzare le selezioni #ifdef.
Nei casi esemplificati, vediamo come abbiano data sheet comune:
- 12F629/675
- 16F627/628
- 16F627A/628A/648A
il che indica una stretta somiglianza dei chip, con differenze speso
ridotte alla sola quantità di memoria integrata.
Inoltre le versioni A sono solitamente degli enhancement di versioni più
datate ed offrono solitamente prestazioni in più, ma sono utilizzabili in
legacy senza problemi. Comunque Microchip provvede documenti di migrazione, ad
esempio
Midrange - 12F629/675.
Ci sono dei Midrange a 8 pin, che possono sostituire
"direttamente" i 12F5xx originali. Consideriamo due chip abbastanza
noti: 12F629 e 12F675.
Si tratta di chip "gemelli" (condividono uno steso foglio dati), con
piccole differenze tra loro.
Se il pinout è identico come per tutti i DIP8, troviamo però all' interno
una struttura Midrange e non Baseline:
- 8 pin, con il caratteristico GPIO.
- Ha oscillatore interno
- Il pin MCLR è configurabile come input
- Ha il Timer0
- Ha interrupt e EEPROM, oltre al Timer1
- Dispone di comparatore, che andrà disabilitato
- 12F675 dispone anche di ADC, che andrà pure disabilitato
- La memoria è di 1K in una pagina e quindi non servono pagesel, nè ci
sono le limitazioni dei Baseline
- La RAM, come comune nei Midrange, inizia a 20h
- La memoria RAM e gli SFR sono su due banchi; in questo va prestata
attenzione, in quanto i registri TRISx stanno in banco1 e non in banco0
come i PORTx, come comune nei Midrange.
L' OPTION_REG ha sempre la stessa
struttura di quelli finora visti e gli switch per T0CKI,
l' assegnazione del prescaler e del suo valore sono nelle stesse posizioni,
per cui valgono le stesse inizializzazioni. Però, come in tutti i Midrange,
il registro è accessibile sia in lettura che scrittura e non richiede
istruzioni speciali, come pure i registri di direzione TRISx.
Non usando nè interrupt, ne EEPROM, la gestione di queste parti, per default
disabilitate, non ci interessa.
Dunque il passaggio del sorgente è praticamente immediato, anche se
occorre prestare attenzione a due punti.
Hardware TX - 12F629/675.
Usiamo gli stessi identici circuiti visti per i Baseline a 8 pin della
puntata I.
Il software TX - 12F629/675.
Ecco il sorgente, con evidenziate le linee che presentano una differenza
dall' originale.
Ovviamente la prima riguarda l' assegnazione del processore; col sistema
già visto possiamo avere un unico sorgente per i due chip:
; scelta
del processore
#ifdef __12F629
LIST p=12F629
#include <p12F629.inc>
#endif
#ifdef __12F675
LIST p=12F675
#include <p12F675.inc>
#endif |
Altra modifica essenziale è quella del config, che va adeguato alle
risorse specifiche del chip:
;===============================================================
; CONFIGURAZIONE =
;===============================================================
; Oscillatore interno, no WDT, PWRT on, BOD on, no CP, no LVP
__config
__CONFIG _CP_OFF & _CPD_OFF & _BODEN_ON & _MCLRE_OFF &
_PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT |
Nessuna variazione rispetto agli originali per Baseline per quanto riguarda
l' assegnazione degli I/O, mentre per l'inizio della RAM va modificato:
;***************************************************************
;===============================================================
; Variabili RAM
;===============================================================
;
CBLOCK
0x20 ; RAM start
sGPIO
; buffer temporaneo PORTB
d1
; counter per delay
d2
ENDC |
Osserviamo che il comando per l' oscillatore interno contiene una variabile
in più, ovvero quella relativa alla possibilità di avere Fosc/4 in uscita
sul pin OSC2; dato che questa non è desiderata, perchè abbiamo bisogno di
tutti gli I/O, specifichiamo la scelta
Solito punto "dolente" che riguarda le analogiche: i due chip hanno
un comparatore e 12F675 anche un ADC, che hanno la precedenza nei default
rispetto alla semplice funzione digitale dei pin.
No problem, basta disabilitarli:
;
Direzione I/O
movlw
0x07
;disabilita comparatori
movwf CMCON
#ifdef
__12F675
; disabilita ADC
banksel ANSEL
clrf
ANSEL
banksel 0
#endif |
va ricordato poi che come per ANSEL, anche i TRISx stanno in Bank
1...
Nessuna modifica nelle altre righe !
Hardware RX - 12F629/675.
Usiamo gli stessi identici circuiti visti per i Baseline a 8 pin della
puntata I.
Il software RX - 12F629/675.
Le linee che presentano una differenza dall' originale sono quelle finora
viste.
Ovviamente la prima riguarda l' assegnazione del processore; col sistema
già visto possiamo avere un unico sorgente per i due chip. Inoltre, come già
visto l'inizio della RAM va modificato.
Nessuna variazione rispetto agli originali per Baseline per quanto riguarda
l' assegnazione degli I/O
Altra modifica essenziale è quella del config, che va adeguato alle
risorse specifiche del chip e che non stiamo a ripetere. Così pure per le
analogiche, che basta basta disabilitare.
Come comune nei Midrange, ricordare che i TRISx e ANSEL stanno in Bank 1,
usando sempre il comodo banksel e ricordandosi di riportare l'azione in
Bank 0.
Nessuna modifica nelle altre righe!
18F - 18F13K22.
Per completare il panorama, vediamo anche un PIC18F, ad esempio il 18F13K22,
che è un 20 pin. Condivide il foglio dati con 18F14K22 che si differenzia per
la maggior quantità di memoria.
Come già detto altrove, il pinout dei chip in package a 8/14/20 pin è
sovrapponibile, però, all' interno, qui troviamo una struttura 18F, con
un elevato set di funzioni integrate:
- Ha oscillatore interno
- Il pin MCLR è configurabile come input
- Ha il Timer0
- Ha interrupt e EEPROM, oltre ai Timer1/2/3
- Dispone di comparatore e di ADC, che andranno disabilitati
- La memoria è enormemente più ampia di quella dei Baseline usati nel
progetto iniziale e quindi non ci sono problemi di commutazione di pagina.
- La RAM inizia a 00h
- I meccanismi dei 18F fanno si che la memoria programma non sia paginata
e quella RAM, nonostante la presenza di banchi, usufruisca con gli SFR di
un sistema di accesso (Access RAM) particolare. Non occorre commutazione
di banchi.
- Delle molteplici funzioni che il chip offre non ne usiamo alcuna e la
loro presenza non ci interessa; la gestione di queste parti, per default
disabilitate, non è richiesta.
Non esiste un OPTION_REG e la
gestione di Timer0 avviene attraverso un registro dedicato.
Nonostante si tratti di un componente appartenente ad una famiglia di chip
abbastanza diversi da quelli visti in precedenza, il passaggio del sorgente è
soggetto praticamente alle stesse azioni viste finora.
Hardware TX-18F.
Possiamo usare uno schema analogo a quello impiegato per i chip a 18 pin,
con PORTB al posto di GPIO. Da notare che il pinout dei chip a 20 pin non è
sovrapponibile a quello dei chip a 18 pin:
Il circuito va bene per tutti i PIC a 20 pin.
Viene usato PORTC dato che PORTB è composto da soli 4 bit mentre PORTA
contiene i pin per ICSP/ICD.
La presa ICSP consente non solo la programmazione onboard, ma nella maggior
parte dei chip a 20 pin svolge anche la funzione di accesso all'in-circuit-debug
(ICD), cosa estremamente utile in didattica, sviluppo, test, ecc.
Se ne fate un circuito stampato, questo andrà bene per TUTTI i chip a 20
pin.
Il software - TX.
Nel passaggio da Baseline/Midrange a PIC18F ci troviamo ad effettuare un
salto sensibile, dato che il core della famiglia è diverso dalle precedenti.
Si tratta non solo delle solite modifiche alla scelta del processore e al
config, ma anche della necessità di considerare un set di istruzioni, sempre
"compatibile", ma in alcuni punti diverso, oltre ad una diversa
struttura dei registri e delle memorie.
Qui diventa più vera l'affermazione che quante meno risorse il sorgente
utilizza, quanto più semplice sarà il passaggio, dato che anche periferiche
semplici come Timer0 non dipendono più da un SFR multiuso come OPTION_REG,
ma da un registro ad hoc e così via.
In particolare, potremo trovare difficoltà notevoli nella direzione opposta,
ovvero nel passaggio del sorgente scritto per 18F a PIC "minori",
con la necessità di riscriverne intere sezioni.
Vediamo cosa è necessario nel nostro semplice caso.
La prima azione riguarda l' assegnazione del processore; col sistema già
visto possiamo avere un unico sorgente per i due chip che ci interessano:
; scelta del processore
#ifdef __18F13K22
LIST p=
#endif
#ifdef __
#endif |
Nessuna variazione rispetto a quanto visto per i Midrange, anche se qui
usaimo PORTC invece di PORTB, mentre per l'inizio della RAM va modificato
;**************************************************************
;==============================================================
; Variabili RAM
;==============================================================
;
CBLOCK 0x0 ; RAM start
sGPIO
; buffer temporaneo PORTB
d1
; counter per delay
d2
ENDC |
Altra modifica essenziale è quella del config, che va adeguato non solo
alle risorse specifiche del chip, ma anche alla sintassi prevista per questa
famiglia:
;==============================================================
; CONFIGURAZIONE =
;==============================================================
; oscillatore interno (1MHz), no PLL, no WDT, no LVP, no CP, no MCLR
; no debug, PWRT on, BOR on
CONFIG FOSC = IRC
CONFIG MCLRE = OFF
CONFIG WDTEN = OFF
CONFIG LVP = OFF
CONFIG BOREN = ON
CONFIG BORV = 22
CONFIG WRTD = OFF
CONFIG CPD = OFF
CONFIG DEBUG = OFF
CONFIG PWRTEN = ON
CONFIG CP0 = OFF
CONFIG CP1 = OFF
CONFIG CPB = OFF |
L'esclusione delle funzioni che si sovrappongono ai port digitali non
diventa più gravosa in seguito alla maggiore quantità di opzioni
disponibili; problematiche potranno essere piuttosto le azioni necessarie al
corretto utilizzo di queste periferiche.
In questo senso è da osservare che il chip contiene, oltre a 17 pin
configurabili come I/O digitali con slew rate programmabile, un mare di
funzioni:
- Analog-to-Digital Converter (ADC) a 10bit con 12 canali
- Analog Comparator module doppio
- Voltage Reference module
- Programmable weak pull-ups
- Programmable interrupt-on- change
- 3 pin per interrupt esterno
- 4 Timer, di cui 3 a 16 bit e uno a 8
- oscillatore per Timer1
- Enhanced Capture/Compare/PWM (ECCP) con 1/2/4 uscite PWM
- Master Synchronous Serial Port (MSSP) module
- Enhanced Universal Synchronous Asynchronous Receiver Transmitter module
(EUSART)
- SR Latch (555 Timer) module con supporto per mTouch™ capacitive
sensing
- Oscillatore interno programmabile d1 31kHz a 16MHz con PLL
- Oscillatore esterno, 4 modalità
- interrupt a 2 livelli di priorità
- set istruzioni esteso
- moltiplicazione hardware
- accesso alle tabelle con istruzioni ad hoc
- EEPROM
- auto scrittura della Flash
e varie altre cose. Questo porta le pagine del foglio dati a oltre 400, il
che farebbe supporre drammatica la consultazione.
Ma la cosa non è così terribile in quanto viene applicato il principio
che tutte le funzioni "extra" sono disattivate per default al POR
e quindi è come se non ci fossero: l' accesso ai pin come I/O digitali si
limita ad una quantità ridotta di operazioni, analoga e perfino minore di
quella richiesta per alcuni Baseline e Midrange.
In particolare, nel nostro caso dobbiamo agire solamente sugli ingressi del
modulo ADC (abilitati al default) e sullo slew rate, impostato dal default a
1/10; non interessandoci una riduzione dell' EMC, lo riportiamo alla pendenza
normale (cosa che comunque non influirebbe sul funzionamento di questa
applicazione, dati i tempi molto lunghi delle temporizzazioni degli impulsi).
; no AD
movlw b'00000000'
movwf ANSEL
clrf ANSELH
;setup PORT
clrf TRISA
; PA tutti out
clrf TRISB
; PB tutti out
movlw b'00001111' ; PC0-3 in , altri out
movwf TRISC
; slew rate normale
clrf SLR |
Non c'è altro da toccare, perchè, come detto, i rimanenti moduli sono
già disabilitati, compresi i malefici comparatori (finalmente i progettisti
hanno ascoltato il gemito che sale dall' utenza?).
Abilitati ci sarebbero solo i weak pull-up, ma riguardano solo PORTA e PORTB,
che non usiamo.
Ci si può chiedere come fare a sapere tutto ciò. Niente di più semplice:
basta leggersi il foglio dati !
Urca, come una condanna alla fucilazione...
Invece no, perchè le tabelle riportano chiaramente lo stato dei registri
al POR e da queste, senza leggersi altro, si ricava immediatamente lo stato.
In particolare la tabella 3.2 (pag. 37-38 del foglio dati DS41365E) li
raccolgono in un unico blocco, mentre le
pagine dedicate ai singoli registri li dettagliano maggiormente. Ad esempio,
non esiste più un OPTION_REG e Timer0
è gestito da un opportuno registro:
Però vediamo che anche questo Timer, che nei PIC minori è sempre attivo (free
running) qui è comandabile da un bit e per default è spento. Per usarlo
dobbiamo accenderlo. Dato che nel TX non serve, lo lasciamo al suo default.
Mentre il funzionamento a 16 bit è pure da attivare, dato che al default è
disabilitato; questo consente la "legacy" con programmi scritti per
PIC che non hanno questa opzione.
Degno di nota é la mancanza di azione su switches di banco per accedere
agli SFR, dato che i PIC18F utilizzano una modalità particolare Access RAM,
che l' Assembler MPASM compila automaticamente in relazione agli indirizzi
richiesti. Un enorme sollievo per il programmatore Assembly che non deve più
farcire i sorgenti di banksel.
Altra particolarità di questa famiglia è l' accesso al latch dei port:
;inizializzazione I/O
clrf LATA
; clear port latch
clrf LATB
clrf LATC |
che evita il problema R-M-W che affligge Baseline e Midrange. In scrittura
useremo LATx, in lettura PORTx.
Ci sono, però, nascosti altre trappole meno visibili. Una riguarda l'
oscillatore interno che parte (non si sa in base a quali considerazioni) non a
4MHz, ma a 1MHz. Occorre variare il registro di controllo:
; oscillatore interno a 4MHz
movlw b'01010000'
movwf OSCCON |
Nessuna modifica nelle righe successive!
Hardware RX-18F
Continuiamo ad usare PORTC:
Il circuito va bene per tutti i PIC a 20 pin.
Data la sovrabbondanza di I/O il circuito potrà essere usato, adattando le
uscite, anche per comandare il display a 7 segmenti o per le estensioni
descritte più avanti.
Il software - TX.
Le modifiche al sorgente originale sono le stesse indicate sopra.
Unica differenza sono l' assegnazione degli I/O e la necessità di
abilitare Timer0, che dobbiamo accendere:
; timer0 on, 1:256, clock interno
movlw b'11000111'
movwf T0CON |
Inoltre ci scontriamo con alcune differenze nel set di istruzioni.
Baseline e Midrange hanno una sola forma di shift, a destra o sinistra (rrf
e rlf) , che coinvolge il
Carry. I PIC18F dispongo di istruzioni di rotazione doppie, una che coinvolge
il Carry (rlcf e
rrcf) e una che non lo modifica (rlncf e rrncf). Dovremo quindi
sostituire l' opcode:
; timer0 on, 1:256, clock interno
movlw b'11000111'
movwf T0CON |
Occorrono anche alcune modifiche qua e là, per l' esattezza riguardanti
gli opcodes:
- nel set di 18F il rotate è espresso in due modi diversi, a seconda che
comprenda il carry o no. Qua non importa, per cui dobbiamo trasformare
la rrf in rrcf
.
- MPASM non accetta gli pseudo opcodes dei Baseline e dei Midrange, per
cui la skpnz (skip next line if resut not zero)
va sostituita con un bnz (branch if not zero),
istruzione del set 18F, che però richiede una label in oggetto relativa
alla destinazione del branch.
- inoltre va considerato che le routines di tempo sono scritte usando il
simbolo $ (valore PC corrente). Però nei 18F le
istruzioni sono codificate al minimo su 2 bytes (mentre nei Baseline
occupano costantemente 1 byte) e questo richiede la duplicazione degli
indici.
Non sono, però, necessarie modifiche nel resto delle istruzioni, che sono
le stesse da Baseline a 18F . Anche per chi realizza la versione con uscita a
7 segmenti non occorre modificare la struttura della lookup table: anche se i
PIC18F dispongono di un modo molto più efficiente e meno critico per
realizzare l' accesso a tabelle, il sistema visto funziona senza problemi.
Enhanced Midrange.
Non presento esempi per questa famiglia, che mescola nuove funzioni, nuove
istruzioni e caratteristiche dei PIC18F su una base Midrange (con tutti i suoi
difetti), perchè si tratta di chip molto recenti e non ancora finiti nei
"must" del web hobbistico.
E, forse, anche perchè non li trovo molto simpatici; sono adatti ad una
programmazione C dove le "librerie" e gli automatismi rendono
abbastanza trasparenti le asperità dell' hardware, ma lo sono un po' meno per
chi vuole usarli in Assembly, dove gli SFR e la RAM sono sparpagliati anche su
32 banchi, la memoria è paginata e, in sostanza, imperano i limiti dei
Midrange, anche se sono stati inseriti sistemi per renderli meno ostili (ad
esempio l' accesso ai LATx per evitare R-M-W, ecc.), comprese nuove istruzioni
(che, però, se usate rendono il sorgente incompatibile con qualsiasi altra
famiglia, compresi i 18F...).
Le nuove periferiche sono interessanti, ma l' unica ragione della
sperimentazione nei Midrange è da supporre essenzialmente in una drammatica
differenza di costo tra il loro core e quello dei 18F; ovvero si tratta di
scelte dettate da attenzione ai problemi economici.
Comunque, anche qui, per i semplici programmi che stiamo considerando, non
ci sono particolari difficoltà per la migrazione; basterà considerare i
punti indicati.
I "fogli dati" esorbitanti le 400 pagine sono scremabili in base ai
principi indicati prima.
ACHTUNG - I !
A questo punto dovrebbe parrebbe che la migrazione di un sorgente da un
chip ad un' altro sia cosa alquanto semplice.
Va detto però che i programmi in esame sono volutamente semplici per
fungere da esempio didattico. Inoltre hanno documentazione e commenti più che
esaurienti.
Nella realtà è possibile trovarsi davanti programmi di grande
complessità, in cui a prima vista non è facile districarsi. E se sono usate
periferiche che possono presentare piccole, ma significative differenze fra i
diversi chip.
Però, anche in questi casi, fatte salve le linee essenziali dichiarate all'
inizio (ovvero la possibilità della migrazione solo se il sorgente originario
non usa funzioni non presenti sul chip di destinazione), è sempre possibile
venire a capo della situazione considerando con un po' di attenzione gli
elementi chiave indicati.
Attenzione che se il sorgente originale è scritto con la parte opposta
della testa, senza forma, senza commenti nè indicazioni utili per capire cosa
stia facendo, magari usando assoluti a go-go, allora le cose possono
complicarsi alquanto.
Il software.
Nessuno dei sorgenti forniti è stato provato!!!
Sono stati solamente compilati per verificare che non contengano madornali
svarioni formali. Ma non ci sono ragioni per cui, a meno delle solite distrazioni, questi non
funzionino.
In effetti, queste pagine non sono è la descrizione di una realizzazione,
ma un compito a casa. Ovvero: chi è interessato alla realizzazione, usando PIC diversi da quelli
proposti all' origine, ha qui alcuni esempi e linee guida per poter traslare
il sorgente.
E chi è interessato a sperimentare qualcosa di Assembly, può benissimo
provare i sorgenti proposti come esercitazione.
Ovviamente, se ci sono difficoltà, a disposizione (entro limiti
ragionevoli...) per trovare eventuali bug in quanto scritto.
Addendum al ricevitore per display a 7
segmenti.
Abbiamo visto (puntata II) che, attraverso la lookup table, otteniamo la
conversione del dato a 4 bit in ingresso in una delle 16 possibili
combinazioni in uscita.
Per avere maggiore chiarezza sulle possibilità offerte da questo metodo,
aggiungiamo alcuni altri esempi. Infatti la tabella non è limitata alla sola
gestione di display a 7 segmenti, ma si presta a molte altre azioni.Ad
esempio, vogliamo comandare 4 relè, collegati ai 4 bit di uscita del
ricevitore a 8 pin. Con un dato a 4 bit possiamo ottenere l' azionamento di
ogni singolo relè e di tutte le combinazioni possibili. Nella tabella le X
indicano i relè attivati, ad esempio, secondo la seguente logica binaria:
Dato a 4 bit |
Bit-relè |
3 |
2 |
1 |
0 |
0 |
- |
- |
- |
- |
1 |
|
|
|
X |
2 |
|
|
X |
|
3 |
|
|
X |
X |
4 |
|
X |
|
|
5 |
|
X |
|
X |
6 |
|
X |
X |
|
7 |
|
X |
X |
X |
8 |
X |
|
|
|
9 |
X |
|
|
X |
A |
X |
|
X |
|
B |
X |
|
X |
X |
C |
X |
X |
|
|
D |
X |
X |
|
X |
E |
X |
X |
X |
|
F |
X |
X |
X |
X |
Per ottenere questo basterà modificare la lookup table:
; segment data table
segtbl andlw
0x0F
; solo nibble
basso
addwf
PCL,f ;
punta PC
; RY4|RY3|RY2|RY1
retlw
b'00000000' ;
"0" - | - | - | -
retlw
b'00000001' ;
"1" - | - | - |on
retlw
b'00000010' ;
"2" - | - |on | -
retlw
b'00000011' ;
"3" - | - |on |on
retlw
b'00000100' ;
"4" - |on | - | -
retlw
b'00000101' ;
"5" - |on | - |on
retlw
b'00000110' ;
"6" - |on |on | -
retlw
b'00000111' ;
"7" - |on |on |on
retlw
b'01111111' ;
"8" on| - | - | -
retlw
b'01101111' ;
"9" on| - | - |on
retlw
b'01110110' ;
"A" on| - |on | -
retlw
b'00111000' ;
"B" on| - |on |on
retlw
b'01110011' ;
"C" on|on | - | -
retlw
b'01000000' ;
"D" on|on | - |on
retlw
b'01100011' ;
"E" on|on |on | -
retlw
b'00000000' ;
"F" on|on |on |on |
Osserviamo l' utilità di una forma "grafica" ordinata, il che
rende immediata la comparazione tra gli oggetti della lookup table e la
tabella vista prima: mantenendo forma nel sorgente si facilita di gran lunga
il lavoro.
La corrispondenza tra dato in ingresso e dato in uscita della lookup table
è ampio: è possibile un elevato numero di altre combinazioni, come questa:
Dato a 4 bit
|
Bit-relè |
3 |
2 |
1 |
0 |
0 |
|
|
|
|
1 |
|
|
|
X |
2 |
|
|
X |
|
3 |
|
X |
|
|
4 |
X |
|
|
|
5 |
X |
|
|
X |
6 |
X |
|
X |
|
7 |
X |
X |
|
|
8 |
|
|
|
|
9 |
|
|
|
|
A |
|
|
|
|
B |
|
|
|
|
C |
X |
X |
X |
X |
D |
|
|
|
|
E |
|
|
|
|
F |
|
|
|
|
a cui corrisponde la seguente tabella:
; segment data table
segtbl andlw
0x0F
; solo nibble
basso
addwf
PCL,f ;
punta PC
; RY4|RY3|RY2|RY1
retlw
b'00000000' ;
"0" - | - | - | -
retlw
b'00000001' ;
"1" - | - | - |on
retlw
b'00000010' ;
"2" - | - |on | -
retlw
b'00000100' ;
"3" - |on | - | -
retlw
b'00001000' ;
"4" on| - | - | -
retlw
b'00001001' ;
"5" on| - | - |on
retlw
b'00001010' ;
"6" on| - |on | -
retlw
b'00001100' ;
"7" on|on | - | -
retlw
b'00000000' ;
"8" - | - | - | -
retlw
b'00000000' ;
"9" - | - | - | -
retlw
b'00000000' ;
"A" - | - | - | -
retlw
b'00000000' ;
"B" - | - | - | -
retlw
b'00001111' ;
"C" on|on |on |on
retlw
b'00000000' ;
"D" - | - | - | -
retlw
b'00000000' ;
"E" - | - | - | -
retlw
b'00000000' ;
"F" - | - | - | - |
o qualsiasi delle altre combinazioni possibili.
L' elemento comune è costituito esclusivamente dalla necessità di limitare
l' ampiezza della tabella al numero di righe che può indirizzare (nel nostro
caso, 2^4).
Quindi, la corrispondenza 4 bit in ingresso- 4 bit in uscita è solo una
delle possibilità. Con il PIC a 14 pin abbiamo visto che 7 uscite sono
prontamente disponibili e il limite è solo quello ribadito prima; possiamo
comandare 1, 2, 3, 4, 7 relè, sempre con 16 combinazioni. Ad esempio:
Dato a 4
bit |
Bit-relè |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
|
|
|
|
|
|
1 |
|
|
|
|
|
|
X |
2 |
|
|
|
|
|
X |
|
3 |
|
|
|
|
X |
|
|
4 |
|
|
|
X |
|
|
|
5 |
|
|
X |
|
|
|
|
6 |
|
X |
|
|
|
|
|
7 |
X |
|
|
|
|
|
|
8 |
X |
|
|
|
|
|
X |
9 |
X |
|
|
|
|
X |
|
A |
X |
|
|
|
X |
|
|
B |
X |
|
|
X |
|
|
|
C |
X |
|
X |
|
|
|
|
D |
X |
X |
|
|
|
|
|
E |
|
|
|
|
|
|
|
F |
X |
X |
X |
X |
X |
X |
X |
a cui corrisponde la seguente tabella:
; segment data table
segtbl andlw
0x0F
; solo nibble
basso
addwf
PCL,f ;
punta PC
; RY7|RY6|RY5|RY4|RY3|RY2|RY1
retlw
b'00000000' ;
"0" - | - | - | - | - | - | -
retlw
b'00000001' ;
"1" - | - | - | - | - | - |on
retlw
b'00000010' ;
"2" - | - | - | - | - |on | -
retlw
b'00000100' ;
"3" - | - | - | - |on | - | -
retlw
b'00001000' ;
"4" - | - | - |on
| - | - | -
retlw
b'00010000' ;
"5" - | - |on |
- | - | - | -
retlw
b'00100000' ;
"6" - |on |
- | - | - | - | -
retlw
b'01000000' ;
"7" on| - | - | - | - | - | -
retlw
b'01000001' ;
"8" on| - | - | - | - | - |on
retlw
b'01000010' ;
"9" on| - | - | - | - |on | -
retlw
b'01000100' ;
"A" on| - | - | - |on | - | -
retlw
b'01001000' ;
"B" on| - | - |on | - | - | -
retlw
b'01010000' ;
"C" on| - |on | - | - | - | -
retlw
b'01100000' ;
"D" on|on | - | - | - | - | -
retlw
b'00000000' ;
"E" - | - | - | - | - | - | -
retlw
b'01111111' ;
"F" on|on |on |on |on |on |on |
o così:
Dato
a 4 bit |
Bit-relè |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
|
|
|
|
|
|
1 |
|
|
|
|
|
|
X |
2 |
|
|
|
|
|
X |
|
3 |
|
|
|
|
X |
|
|
4 |
|
|
|
X |
|
|
|
5 |
|
|
X |
|
|
|
|
6 |
|
X |
|
|
|
|
|
7 |
X |
|
|
|
|
|
|
8 |
|
|
|
|
|
|
|
9 |
|
|
|
|
|
|
|
A |
|
|
|
|
|
|
|
B |
|
|
|
|
|
|
|
C |
|
|
|
|
|
|
|
D |
X |
X |
X |
X |
X |
X |
X |
E |
|
|
|
|
|
|
|
F |
|
|
|
|
|
|
|
a cui corrisponde la seguente tabella:
; segment data table
segtbl andlw
0x0F
; solo nibble
basso
addwf
PCL,f ;
punta PC
; RY7|RY6|RY5|RY4|RY3|RY2|RY1
retlw
b'00000000' ;
"0" - | - | - | - | - | - | -
retlw
b'00000001' ;
"1" - | - | - | - | - | - |on
retlw
b'00000010' ;
"2" - | - | - | - | - |on | -
retlw
b'00000100' ;
"3" - | - | - | - |on | - | -
retlw
b'00001000' ;
"4" - | - | - |on
| - | - | -
retlw
b'00010000' ;
"5" - | - |on |
- | - | - | -
retlw
b'00100000' ;
"6" - |on |
- | - | - | - | -
retlw
b'01000000' ;
"7" on| - | - | - | - | - | -
retlw
b'00000000' ;
"8" - | - | - | - | - | - | -
retlw
b'00000000' ;
"9" - | - | - | - | - | - | -
retlw
b'00000000' ;
"A" - | - | - | - | - | - | -
retlw
b'00000000' ;
"B" - | - | - | - | - | - | -
retlw
b'00000000' ;
"C" - | - | - | - | - | - | -
retlw
b'01111111' ;
"D" on|on |on |on |on |on |on
retlw
b'00000000' ;
"E" - | - | - | - | - | - | -
retlw
b'00000000' ;
"F" - | - | - | - | - | - | - |
e qualsiasi altra combinazione nel limite complessivo di 16.
Così, con l' intermediazione di una lookup table adeguata, sarà possibile
ottenere una vasta casistica di carichi, come lampade, relè, LED, ecc.
Ad esempio, posiamo comandare 15 uscite, una alla volta, con una posizione di
off generale, ma anche 16 uscite, sempre una alla volta, o qualsiasi altra
combinazione ammissibile nell’ ambito delle 16 uscite possibili dalla
tabella (alimentata da 4 bit).
Dato a 4 bit |
Bit-relè |
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
X |
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
X |
|
3 |
|
|
|
|
|
|
|
|
|
|
|
|
X |
|
|
4 |
|
|
|
|
|
|
|
|
|
|
|
X |
|
|
|
5 |
|
|
|
|
|
|
|
|
|
|
X |
|
|
|
|
6 |
|
|
|
|
|
|
|
|
|
X |
|
|
|
|
|
7 |
|
|
|
|
|
|
|
|
X |
|
|
|
|
|
|
8 |
|
|
|
|
|
|
|
X |
|
|
|
|
|
|
|
9 |
|
|
|
|
|
|
X |
|
|
|
|
|
|
|
|
A |
|
|
|
|
|
X |
|
|
|
|
|
|
|
|
|
B |
|
|
|
|
X |
|
|
|
|
|
|
|
|
|
|
C |
|
|
|
X |
|
|
|
|
|
|
|
|
|
|
|
D |
|
|
X |
|
|
|
|
|
|
|
|
|
|
|
|
E |
|
X |
|
|
|
|
|
|
|
|
|
|
|
|
|
F |
X |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ovviamente in questo caso si rende necessario un chip che disponga di 20
pin:
Vdd/Vss |
2 |
I/O per i relè |
15 |
serial in |
1 |
LED |
1 |
non utilizzato oppure uscita 16 |
1 |
Ad esempio 16F527 o 16F677, ma anche 16F876/877 o 18F2321 o qualsiasi altro
PIC con 20 pin o più.
Dovrebbe essere chiaro ora che con la trasmissione di soli 4 bit possiamo
azionare ben più di 4 carichi in uscita.
La limitazione principale è quella delle 2^4 combinazioni in uscita, per
aumentare le quali occorre aumentare il numero di bit trasmessi.
Per quanto riguarda l' interfaccia, niente di nuovo sotto il sole: soliti
open collector/open drain o buffer integrati. Ad esempio, per 7 relè:
Lasciamo alla fantasia o alla necessità dei lettori lo studio di altre
applicazioni.
Altre risorse.
|