PIC16F18313
- Gli oscillatori interni
|
PIC16F313 è un microcontroller abbastanza recente e
piuttosto nominato in rete. E', dotato di
numerose funzioni, tipiche degli Enhanced, a cui si aggiunge una struttura del
modulo oscillatore originale, comune ad altri PIC della serie 16F183xx (16F18
323/324/325/326 a 14 pin e /344/345/346 a 20 pin).
Un modulo oscillatore
analogo è presente anche su altri Enhanced del gruppo 16F18xxx.
Le opzioni del modulo oscillatore rendono complesso districarsi nei datasheet che occupano ormai
500 e più pagine. Una possibilità offerta da MPLABX è quella di usare il
Configurator MCC che facilita il lavoro. In ogni caso, per sfruttare appieno
il componente è indispensabile avere una chiara idea delle funzioni dei vari
parametri e registri, dato che MCC fornisce soluzioni, ma senza
particolari spiegazioni. Nè, peraltro, il foglio dati è sempre
sufficientemente chiaro alla prima lettura.
Per chi ha in mano il componente per la prima volta, dunque, alcuni aspetti
possono non essere di immediata comprensione.
Si può dire che in questi Enhanced è particolarmente curato il modulo
oscillatore per semplificare il cambio del clock durante l'esecuzione del
programma (Clock Switching), l'avvio con doppio clock, generazione di frequenze
diverse, ecc..
Sono implementabili numerose modalità di sorgenti oscillatore esterne
e tre sorgenti interne, tutte dotate di PLL e divisori, definibili in
configurazione iniziale.
Tutto questo a scapito di una
complicazione maggiore rispetto al modulo clock a cui ci hanno abituati i
Midrange non-Enhanced.
Vediamo di capire qualcosa di più su questo modulo oscillatore,
puntando essenzialmente alle modalità di clock interno, che solitamente sono
quelle che per prime andiamo a sperimentare. Le modalità di clock esterno sono
trattate in altre pagine.
La via
migliore per comprendere il modulo oscillatore è quella di tenere presente il
diagramma a blocchi.
Per prima cosa osserviamo che il modulo è composto da tre parti, da
sinistra a destra :
-
blocco degli oscillatori veri e propri, in cui sono presenti due oscillatori esterni (EXTOSC
e SOSC) e due oscillatori interni
(LFINTOSC e HFINTOSC).
Gli oscillatori esterni impiegano almeno un pin (o due) e il progettista
ha stabilito che al default ci sia un pin (OSC1)
con la funzione CLKIN,
cosa non comune nei PIC più datati e causa di problemi inaspettati. Nelle
modalità con cristallo, i pin impiegati sono due e quindi di default c'è
anche il conosciuto CLKOUT, sul pin OSC2.
Il segnale CLKOUT è, come solito, la
frequenza Fosc/4.
-
blocco del multiplex. Troviamo qui anche due PLL
con rapporto fisso, che possono moltiplicare x4 il clock esterno e x2 quello interno. Il multiplex permette di selezionare quale clock passa
al blocco successivo, mentre alcune sorgenti sono inviate alle
periferiche.
-
blocco divisore: il clock scelto dal multiplex viene passato ad
un divisore programmabile da 1/1 a 1/512. L'uscita del divisore è
condizionata dalla modalità sleep.
Possiamo considerare anche la presenza del moduli FSC
(Fail Safe Clock Monitor) che è alimentato dal LFINTOSC
a 31kHz e controlla la presenza del clock all'uscita del multiplex. Da
osservare che FSC è attivo per oscillatori
interni.
Dunque, va tenuto presente che la programmazione del primo blocco è effettuata nella configurazione
iniziale.
Qui abbiamo due opzioni per la scelta dell'oscillatore:
Le scelte possibili con RSTOSC
sono:
-
_RSTOSC_HFINT32
seleziona HFINTOSC 2x PLL (32MHz)
-
_RSTOSC_EXT4X
seleziona EXTOSC con 4x
PLL
-
_RSTOSC_SOSC
seleziona SOSC esterno (31kHz)
-
_RSTOSC_LFINT
seleziona LFINTOSC (31kHz)
-
_RSTOSC_HFINT1
seleziona HFINTOSC (1MHz)
-
_RSTOSC_EXT1X
seleziona EXTOSC
oscillatori interni
oscillatori esterni
EXT4X e EXT1X
sono condizionati dalla selezione effettuata con FEXTOSC
Questo parametro riguarda solo gli oscillatori esterni:
-
_FEXTOSC_LP LP oscillatore a cristallo
32.768 kHz
-
_FEXTOSC_XT XT oscillatore a cristallo 100kHz-4 MHz
-
_FEXTOSC_HS HS
oscillatore a cristallo oltre 4 MHz
-
_FEXTOSC_OFF Oscillatore esterno non abilitato
-
_FEXTOSC_ECL EC clock esterno fino a 100 kHz
-
_FEXTOSC_ECM EC clock esterno da 100 kHz a 8 MHz
-
_FEXTOSC_ECH EC clock esterno
oltre 8 MHz
esclude
oscillatore esterno e libera RA4
In più, troviamo il bit _CSWEN_(ON/OFF)
di sicurezza che impedisce o permette la modifica dei bit del registro OSCCON1
durante il funzionamento del programma. Il bit
è normalmente ON permettendo la modifica; se programmarlo OFF
impedisce
il cambio del clock durante il programma.
Come accennato prima, il chip ha come scelte "Basis" , cioè di
default della
configurazione, anche i due bit:
-
_CLKOUTEN_(ON/OFF)
che abilita o meno l'uscita del clock FOSC/4
il che occupa un pin (RA4). Questa
opzione è comune ad altri PIC.
-
_FEXTOSC_(ON/OFF)
che abilita l'oscillatore esterno e occupa il pin di ingresso (RA5).
Questa opzione è meno comune e si deve prestare attenzione se si vuole
usare RA5 come I/O
Come nota essenziale, se non desiderate oscillatore
esterno, ma il libero uso dei pin relativi (RA4 e
RA5), dovete
inserire obbligatoriamente nel config CLKOUTEN=OFF
e FEXTOSC=OFF. |
Dunque, queste selezioni effettuate nel config hanno valore per tutto il programma successivo.
Riassumendo, nel config, queste sono le azioni necessarie nel config per ottenere
l'oscillatore interno e tutti i pin liberi:
#pragma config RSTOSC=LFINT
// LFINTOSC (31kHz)
oppure
#pragma config RSTOSC=HFINT1 // HFINTOSC (1MHz)
oppure
#pragma config RSTOSC=HFINT32 //
HFINTOSC (32MHz)
#pragma config FEXTOSC=OFF // libera RA5 - no
clockin
#pragma config CLKOUTEN=OFF // libera RA4 - no
clockout
La scelta di_RSTOSC
tra le tre disponibili viene chiarita più avanti.
Come dichiarato all'inizio, non trattiamo qui le specifiche degli oscillatori esterni, che sono simili
a quelle generali dei PIC, a partire da quelli più "antichi"e
possono essere facilmente comprese dal foglio dati. Vediamo invece gli
oscillatori interni.
Al blocco degli oscillatori fa seguito il multiplex che va gestito da
programma, attraverso i bit COSC<2:0> del
registro OSCCON1.
-
L'oscillatore LFINTOSC, calibrato in produzione, produce
esclusivamente la frequenza di 31kHz. Viene selezionato da COSC=0b100.
Non dispone di PLL.
-
L'oscillatore HFINTOSC è anch'esso calibrato in
produzione. Dispone di un PLL x2, selezionabile dal multiplex. E' diviso in due
sezioni e produce da 1 a
32MHz; la frequenza dipende dai bit HFFRQ<3:0>,
che si trovano nel registro OSCFRQ .
Combinando HFFRQ e COSC
si possono selezionare diverse frequenze a seconda che si parta da HFINT1
o HFINT32.
Vediamo che HFFRQ consente di
scegliere un clock a 1, 2, 4, 8,
12, 16, 32MHz se è stato selezionato HFINT1. Se è selezionato
HFINT32, si
possono scegliere le frequenze di 16, 24, 32MHz.
Da osservare che il valore di default per HFFRQ
è 0110 , ovvero 16MHz, frequenza possibile sia con HFINT1
che con HFINT32.
Per riassumere:
-
l'oscillatore interno è selezionato dal config
iniziale
-
LFINT genera 31kHz
fissi.
-
HFINT1 e HFINT32
generano le frequenze viste sopra, agendo nel programma sul registro OSCFRQ
e OSCCON1
Il multiplex, comandato dai bit COSC<2:0> di
OSCCON1 permette 8 selezioni.
Osserviamo dallo schema iniziale che i due HFINT
possono essere selezionati anche con un PLL x2.
L'ultimo blocco è il Postscaler Divider, con fattori da 1 a 512, comandato dai bit
CDIV<4:0>.
I segnale del clock, prelevato da diversi punti, alimenta le periferiche e,
in uscita, è condizionato dalla modalità sleep.
Multiplexer e Divider sono gestiti da registri interni che vanno modificati
dal programma.
Essenzialmente si tratta del registro OSCFRQ visto
sopra, e del registro OSCON1
nel quale
troviamo i bit NOSC<2:0>
(New Oscillator Sources) e NDIV<3:0>
(New Divider) che permettono lo switch fra le diverse sorgenti di clock
Il PLL x2 opera solo con le frequenze 8, 12,16 per generare i
valori di HFINT32.
I bit NOSC<2:0>
selezionano la sorgente; abbiamo, per l'oscillatore interno, le scelte LFINT,
HFINT1 e HFINT32.
Da
notare che inizialmente, (per default) NOSC è uguale a RSTOSC
della configurazione. Questo semplifica un po' le cose.
Le altre 4 opzioni riguardano clock esterno.
I bit NDIV<3:0> selezionano il
fattore di divisione, secondo la table 7.2 qui sopra.
Si può pensare che la presenza di tutti questi registri e opzioni non aiuta certamente a dipanare
l'intricata matassa degli oscillatori, ma la situazione non è poi così
tragica; vediamo di chiarire attraverso alcuni esempi.
Prima consideriamo lo stato di default dei bit di
configurazione al POR.
-
CSWEN è a 1, abilitando
la modifica del clock da programma. Se non la desideriamo dobbiamo portare
il bit a 0:
#pragma config
CSWEN = OFF
Attenzione che con CSWEN disabilitato non c'è
la possibilità di commutare la frequenza del clock durante l'esecuzione del
programma.
-
RSTOSC
è al default 0x111, ovvero seleziona l'oscillatore esterno EXT1X.
Per usare un oscillatore interno si rende necessario impostare 0x110 (HFINTOSC1)
oppure 0x100 LFINTOSC oppure 0x000 HFINTOSC32
#pragma config RSTOSC =
HFINTOSC1/HFINTOSC32/LFINTOSC
-
FEXTOSC
è 0x111 che seleziona il modo ECH. Per escludere oscillatori
esterni occorre
modificare con 0x100 che disabilita gli oscillatori esterni.
#pragma config FEXTOSC =
OFF
-
CLOCKOUTEN
è, stranamente a 1, disabilitando l'uscita del clock. Se vogliamo l'uscita occorre
portarlo a 0.
#pragma config CLKOUTEN =
ON
-
FCMEM è a 1, abilitando
il fail safe monitor. Se non interessa:
#pragma config
FCMEM = OFF
impostazione utile
impostazione indispensabile
Per i registri interessati al clock i default sono:
-
OSCCON1=0b0qqq 0000. Da
notare che NOSC è uguale a RSTOSC
in configurazione. Quindi, se, ad esempio, è stato scelto RSTOSC=HFINT1 nel config, sarà automaticamente
NOSC=0b110.
NDIV seleziona
al default il divisore 1/1. Occorre modificarlo se serve un diverso valore.
-
OSCFRQ=0b0000 0110,
ovvero HFFRQ seleziona 16MHz, possibile
sia con HFINT1
che con HFINT32 . Occorre
modificarlo se serve un diverso valore.
Vediamo alcuni esempi:
Per avere al default un clock a 31KHz:
#pragma config RSTOSC = LFINTOSC
// NOSC = 0b100 per LFINTOSC, NDIV=0b0000 per div. 1/1
// OSCCON1=0b01000000; // LFINT 1/1
Non serve modificare nessun registro perchè:
-
OSCCON1 per default seleziona LFINT1
e un divisore 1/1
|
Per avere al default un clock
di 1MHz, con i pin OSC1/2 liberi:
#pragma config FEXTOSC = OFF, RSTOSC = HFINT1
#pragma config CLKOUTEN = OFF, CSWEN = ON
Non serve modificare nessun registro perchè:
- OSFRQ
per default seleziona una frequenza di 16MHz
-
OSCCON1 per default seleziona HFINT1
e un divisore 1/16
|
Per modificare la
scelta precedente a 4MHz.
OSCFRQ=0b00000110;
// HFFRQ=0b110 per 16MHz
// NOSC=0b110 per HFINT1, NDIV=0b0010 divisore 1/4
OSCCON1 = 0b01100010; // HFINT1 div. 1/4
oppure
OSCCON1bits.NOSC = 0b110; // HFINT1
OSCCON1bits.NDIV = 0b0000; // Div. 1/1
OSCFRQbits.HFFRQ = 0b0111; // = 4 MHz
|
Se vogliamo un clock a 32MHz basterà nel config:
#pragma config FEXTOSC = OFF, RSTOSC = HFINT32
#pragma config CLKOUTEN = OFF, CSWEN = ON
oppure
OSCCON1bits.NOSC = 0b000; // HFINT32
OSCCON1bits.NDIV = 0b0000; // Div. 1/1
OSCFRQbits.HFFRQ = 0b0110; // 32 MHz
OSCENbits.HFOEN = 1; // HFINTOSC enabled
|
Se
vogliamo impostare il clock di default del sistema a 2MHz:
#pragma
config RSTOSC = HFINT32
#pragma
config CSWEN = ON
OSCFRQbits.HFFRQ
= 0b0011; // 8 MHz con 4 MHz x2
OSCCON1bits.NDIV
= 0b0010; // divisione è 1:4 FOSC=2MHz
|
Se
vogliamo impostare il clock di sistema a 8MHz.
#pragma
config RSTOSC = HFINT32
OSCFRQbits.HFFRQ = 0b0011; // 8MHz con
4MHz x2
|
Quando stiamo lavorando con un clock e vogliamo passare ad un altro valore,
basta agire sui registri interni.
Ad esempio, vogliamo passare a 8MHz da una qualsiasi altra frequenza:
OSCCON1bits.NOSC=0b110; // HFINT1
OSCCON1bits.NDIV=0; // div. 1/1
OSCFRQ=0b011; // 8MHz
|
Agendo
sul divisore si potranno ottenere numerosi valori sottomultipli di un
clock.
Una applicazione di test.
Occorre:
-
un oscilloscopio o un frequenzimetro
-
e un tools adeguato (SNAP, PICKIT4 o 5,
ICD4 o 5, ICE4).
Con questi PIC non è più possibile utilizzare tools come PICKIT3.
-
si consiglia di aggiornare MPLABX all'ultima
versione disponibile
Collegate lo strumento a OSC2
(RA4).
Collegate i pin ICSPDAT, ICSPCLK e MCLR ad un connettore adatto a ICSP/ICD
Scrivete un semplice sorgente e utilizzate il debug in circuit per lanciarlo e
verificare i registri OSCCON1 e OSCFRQ
Esempio di sorgente per un clock di 32MHz:
/**********************************************************
prova clock 18313
*********************************************************/
PORTA
| RA5 | RA4 | RA3 | RA2 | RA1 | RA0 |
|-----|------|------|-----|-----|-----|
| - |clkout| MCLR | - | CLK | DAT |
*********************************************************/
#include <xc.h>
#pragma config FEXTOSC = OFF // FEXTOSC disable
#pragma config RSTOSC = HFINT32 //
#pragma config CLKOUTEN = ON // CLKOUT Fosc/4 su RA4
#pragma config CSWEN = ON // Clock Switch Enable
#pragma config MCLRE = ON // MCLR/VPP
#pragma config LVP = ON // LVP
on per SNAP
// *****************************************************
void main() {
asm ("NOP");
// per debug
// OSCFRQ=0b00000110; // HFFRQ=0b110 per 16MHz
// NOSC=0b110 per HFINTOSC, NDIV=0b0010 per divisore 1/4
// OSCCON1 = 0b01100010; // HFINT1 1/4
while(1);
}
-
Nel Config sono toccati solo i punti essenziali.
La riga LVP=ON va introdotta se
utilizzate SNAP
-
asm ("NOP");
serve come punto di stop nel debug prima di eseguire eventuali linee di
programma.
-
Le linee di programma qui sono commenti, ma possono essere
inserite per modificare il clock di default.
Se nessuna riga di programma è scritta, sul pin CLKOUT
sarà visibile la frequenza di default prodotta dalla configurazione
scelta.
-
Nella finestra di visione dei registri del debugger, si
aggiungeranno quelli che si voglio monitorare, essenzialmente OSCFRQ
e OSCCON1.
-
Se si modifica il default aggiungendo linee di istruzioni,
si potrà aggiungere un breakpoint alla riga asm
("NOP"); in modo da poter analizzare i registri sia
al default, sia dopo l'esecuzione delle istruzioni.
L'oscilloscopio o il frequenzimetro rileveranno su RA4
la frequenza Fosc/4.
E gli altri registri del
clock?
Per inciso, ci si può chiedere perchè non si è parlato
degli altri registri del modulo oscillatore.
La loro situazione è questa:
-
OSCCON2 è la replica
in sola lettura di OSCCON1. Ha
funzioni di verifica.
-
OSCCON3 è un registro
di controllo e flag degli oscillatori.
-
OSCSTAT è un registro
di flag di stato degli oscillatori
-
OSCEN riguarda le
modalità di abilitazione degli oscillatori.
-
OSCTUNE è il registro
di modifica del clock
La loro situazione al default è tale da non creare problemi
con la scelta dell'oscillatore e vanno manipolati solo nei casi in cu siano
richieste specifiche prestazioni o controlli. Per questo, consultare il foglio
dati, sezione 7, DS40001799E-page 66 e seguenti.
|