Wednesday, March 28, 2012

Watch-Dog

Il Watch-Dog e' un oscillatore RC secondario inserito all'interno del microcontrollore. Tale oscillatore non richiede alcun componente esterno per funzionare ed e' completamente indipendente da quello che regola il funzionamento del PIC: cio' significa che il Watch-Dog continua a funzionare anche nel caso in cui viene a mancare il segnale di clock esterno. Il Watch-Dog ha associato un tempo di default pari a 18 ms terminato il quale effettua il reset del microcontrollore (oppure, se in modo sleep, lo risveglia). Se si desiderano tempi piu' lunghi e' possibile associare il prescaler al Watch-Dog settando a 0 il bit PSA del registro OPTION_REG e poi impostare il rapporto di moltiplicazione tramite i bit PS0,PS1 e PS2 (il prescaler, quando viene associato al Watch-Dog, funziona da moltiplicatore anziche' da divisore come invece accadeva quando associato al TIMER0). In sostanza lo scopo del Watch-Dog e' quello di attendere il periodo di tempo selezionato (di default 18 ms) e poi scatenare automaticamente il reset del microcontrollore (nel caso il PIC sia in modalita' sleep viene semplicemente risvegliato continuando l'esecuzione del programma). L'unico modo per prevenire il reset del PIC e' quello di resettare il Watch-Dog, cioe' quello di riazzerare il suo conto alla rovescia tramite l'esecuzione dell'istruzione CLRWDT.

Il Watch-Dog e' utile in tutti quei casi in cui non si vuole che, per qualche errore di programmazione, il microcontrollore si blocchi in un loop infinito in qualche parte del programma. Si predispongono le istruzioni di CLRWDT lungo tutto il codice del programma in maniera tale da riazzerare ogni volta il Watch-Dog senza quindi farlo mai scattare; se il PIC si inserisce in qualche loop indesiderato dal quale non puo' piu' uscire non avra' modo di riazzerare il Watch-Dog che quindi provvedera' (dopo il tempo di time-out) al reset. Ovviamente questo esempio vale solo nel caso in cui nel codice di loop non sia presente anche la stessa istruzione CLRWDT.
Il Watch-Dog parte automaticamente all'accensione del PIC, ma puo' essere disabilitato del tutto in fase di programmazione.
In figura si riporta lo schema logico di collegamento del Watch-Dog e del prescaler (in questo caso chiamato postscaler): 



Indirizzamento indiretto

L'indirizzamento indiretto e' una delle caratteristiche piu' interessanti del PIC 16F84. Grazie a questo sistema e' possibile accedere sia in lettura che in scrittura ad un dato registro GPR in modo indirietto, ovverosia specificandone l'indirizzo sotto forma di dato contenuto in un altro registro.
All'apparenza il meccanismo potrebbe apparire come una complicazione non strettamente necessaria, in realta' e' estremamente utile. Un esempio aiutera' a capirne l'ambito di utilizzo: normalmente per poter accedere in scrittura ad un dato registro occorre specificarne l'indirizzo direttamente nell'istruzione.
Ad esempio, il codice seguente carica il registo 0x0C con il valore 0xA3:

MOVLW 0xA3
MOVWF 0x0C

Il valore 0x0C e' ovviamente specificato nell'istruzione MOVWF. Fin qui niente di male. Ma come si potrebbe fare per caricare tutti i registri GPR con il medesimo valore 0xA3? Con il metodo tradizionale l'unico sistema e' quello di ripetere l'istruzione MOVWF per tutti i registri, in questo modo:

MOVLW 0xA3
MOVWF 0x0C
MOVWF 0x0E
MOVWF 0x0F
...
...
...
MOVWF 0x4F

L'operazione richiede quindi la ripetizione di MOVWF ben 68 volte, con grande spreco di memoria di programma. In effetti non si possono creare cicli per ripetere MOVWF in quanto l'indirizzo del registro corrente deve essere necessariamente codificato nell'istruzione (non e' un dato che si puo' incrementare di uno).
Per risolvere il problema ci viene in contro il sistema dell'indirizzamento indiretto. Grazie ad esso si puo' accedere ad un dato registro GPR tramite due registri di appoggio:

FSR
INDF

FSR si trova all'indirizzo di memoria 0x04 ed e' mappato in entrambi i banchi RAM.
INDF si trova all'indirizzo di memoria 0x00 ed e' mappato in entrambi i banchi RAM.
Per vedere la loro posizione in memoria RAM consultare la sezione "Memoria RAM/FLASH/EEPROM".

Il registro FSR serve per specificare l'indirizzo di memoria del registro che vogliamo accedere; per farlo e' sufficiente scrivere il relativo indirizzo in questo registro. Una volta fatto questo, tutte le eventuali letture e scritture effettuate nel registro INDF saranno svolte come se si stesse effettivamente accedendo al registro in questione e puntato da FSR.

Esempio

Scrivere una subroutine che cancella tutti i registri GPR (il primo registro GPR e' alla locazione 0x0C e l'ultimo alla locazione 0x4F)

FSR EQU 0x04
INDF EQU 0x00
STATUS EQU 0x03

:clearall

MOVLW 0x0C ;inizializzo il puntatore al primo registro GPR
MOVWF FSR ;e lo scrivo nel registro FSR
next:
CLRF INDF ;cancello il contenuto di INDF
INCF FSR ;incremento di uno il puntatore
MOVF FSR,0
SUBLW 0x50
BTFSS STATUS,2 ;se FSR=0x50 vai a RETURN, altrimenti vai a next
GOTO next
RETURN

Modalità sleep

Lo sleep e' una particolare modalita' nella quale il microcontrollore cessa momentaneamente di eseguire istruzioni e si porta in uno stato di stand-by durante il quale i consumi di energia sono ridotti al minimo; e' possibile poi "risvegliare il PIC" in qualsiasi momento successivo. Questa modalita' e' utile nel caso in cui si voglia usare il PIC in sistemi alimentati a batteria o comunque dove i consumi sono un aspetto critico.

Entrare in modalita' sleep

Per far entrare il microcontrollore in modo sleep occorre eseguire l'istruzione SLEEP. I bit PD e TO del registroSTATUS vengono rispettivamente portati a 0 e 1, e l'oscillatore interno del pic viene arrestato (l'esecuzione del programma si ferma all'istruzione SLEEP). Inoltre le porte di I/O mantengono lo stato che avevano prima che il sistema si fermasse.

Risveglio dalla modalita' sleep

Il microcontrollore puo' essere risvegliato dalla modalita' grazie al verificarsi di uno dei seguenti eventi esterni: Reset del microcontrollore (pin MCLR a massa) Watch-Dog time-out Interrupt dal piedino RB0/INT Cambio di stato dei piedini RB0..RB7 Completamento della fase di scrittura della EEPROM Al risveglio il microcontrollore si comportera' consistentemente all'evento esterno verificatosi: nel primo caso (Reset) si avra' effettivamente un reset, nel secondo il PIC continuera' con l'esecuzione del programma dall'istruzione successiva a SLEEP. Negli ultimi tre casi invece, se gli interrupt sono abilitati (GIE=1) verranno "eseguiti" gli interrupt (esecuzione del programma a partire dalla locazione 0x0004 e cosi' via) altrimenti (GIE=0) si proseguira' con l'istruzione successiva a SLEEP. 

Memoria EEPROM

La memoria EEPROM e' un modulo di memoria all'interno del microcontrollore in grado di mantenere le informazioni anche a sistema spento. La memoria e' costituita da 64 byte in tutto, accessibili sia in lettura che in scrittura tramite quattro appositi registri, cioe':

EECON1
EECON2
EEDATA
EEADR

Il registro EEDATA, mappato in RAM alla locazione 0x08 e banco 0, funziona da porta di ingresso/uscita per i dati rispettivamente da e verso la EEPROM; in soldoni si puo' dire che tale registro contiene il byte da leggere/scrivere nella EEPROM.
EEADR, mappato in RAM alla locazione 0x09 e banco 0, serve per specificare la locazione di memoria da accedere in memoria EEPROM (cioe' per specificare in che locazione della EEPROM andra' scritto il byte contenuto in EEDATA, oppure per specificare la locazione della EEPROM da leggere) .
La EEPROM permette unicamente di leggere o scrivere un byte alla volta. Una scrittura implica automaticamente la cancellazione del byte precedentemente memorizzato in quella cella di memoria, mentre una lettura non produce alcuna modifica nei dati della EEPROM.
I registri EECON1 e EECON2 sono due registri ausiliari utilizzati per "comandare" la EEPROM posizionati rispettivamente alle locazioni 0x08 e 0x09 del banco 1 della RAM.
EECON1 e' il registro di controllo con implementati solo i cinque bit meno significativi. I bit di controllo RD e WR avviano rispettivamente il processo di lettura e scrittura delle EEPROM; questi due bit possono solo essere settati ad 1, mentre invece vengono riportati a 0 dal pic al completamento della fase di lettura (se RD) e scrittura (se WR).
Il bit WREN (WRite ENable) abilita o disabilita le scritture nella EEPROM; quando viene settato ad 1 permette di effettuare le scritture, quando e' settato a 0 le scritture sono inibite. Al reset del microcontrolle tale bit e' settato a 0.
Il bit WRERR viene settato ad 1 dal pic quando o un reset oppure un time-out del watch dog ha interrotto prematuramente una scrittura nella EEPROM (va ricordato che la scrittura nella EEPROM e' una operazione relativamente lenta se rapportata alla velocita' di esecuzione delle istruzioni di programma).
Il bit EEIF funge da indicatore per il completamento della fase di scrittura. Prima di iniziare una scrittura deve essere posto a 0 e viene posto automaticamente ad 1 dal pic quando la scrittura e' terminata.





Registro EECON1




Il registro EECON2 e' un semplice registro di appoggio utilizzato esclusivamente nella fase di scrittura della EEPROM. Prima di poter scrivere un byte nella EEPROM occorre scrivere in EECON2 una serie prestabilita di valori, cioe' una specie di sequenza di avvio, in grado di abilitare la EEPROM a ricevere il byte in questione. La sequenza deve essere ripetuta ogni volta che si vuole memorizzare un byte.

Lettura

Leggere un byte dalla EEPROM e' estremamente semplice. Per prima cosa occorre scrivere in EEADR l'indirizzo del byte che si vuole leggere e poi settare ad 1 il bit di avvio di lettura (bit RD del registro EECON1). Al prossimo ciclo macchina (4 colpi di clock) il registro EEDATA si carica automaticamente con il valore del byte richiesto che quindi puo' essere letto.

Esempio:

Leggere dalla EEPROM il byte alla locazione 0x0C e memorizzarlo nel registro di lavoro W

BCF 0x03,5 ;selezione del banco RAM 0

MOVLW 0x0C ;l'indirizzo al quale leggere
MOVWF 0x09 ;lo metto in EEADR BSF 0x03,5 ;selezione del banco RAM 1
BSF 0x08,0 ;setto a 1 il bit RD di EECON1;adesso EEDATA contiene il valore del byte cercato

BCF 0x03,0 ;selezione del banco RAM 0
MOVF 0x08,0 ;copio il valore di EEDATA in W

Scrittura
L'operazione di scrittura di un byte in EEPROM e' relativamente piu' complicata. Per prima cosa occorre disabilitare gli interrupt impostando a 0 il bit GIE di INTCON: in questo modo eventuali interruzioni non verranno prese in considerazione e non andranno a disturbare il processo di scrittura in EEPROM. Adesso occorre impostare in EEADR l'indirizzo al quale vogliamo scrivere il byte ed il registro EEDATA deve essere caricato con il byte in questione. Poi il bit WREN di EECON1 deve essere portato ad 1 per abilitare la scrittura.
Fatto cio' occorre seguire una sequenza standard in grado di attivare la scrittura in EEPROM:

Scrittura del valore 0x55 in EECON2 
Scrittura del valore 0xAA in EECON2 
Impostare ad 1 il bit WR di EECON1 per avviare la scrittura 
Riabilitare gli interrupt impostando a 1 il bit GIE di INTCON 

Tale sequenza deve essere ripetuta per ogni byte che si vuole scrivere in EEPROM. La disabilitazione degli interrupt non e' obbligatoria ma e' considerata una buona pratica per evitare problemi di scrittura qualora questa venisse interrotta prematuramente da una interruzione esterna.
Al termine della scrittura il bit WR viene automaticamente impostato a 0 mentre il bit EEIF viene posto a 1.
Il programma utente puo' sapere quando avviene il completamento della scrittura semplicemente verificando in un loop il valore del bit WR oppure tramite il piu' efficiente meccanismo delle interruzioni.
Da notare che il bit WREN di abilitazione NON viene riportato a 0 automaticamente, quindi per effettuare una nuova scrittura occorrera' reipostarlo ad 1.
Ecco un esempio di scrittura in EEPROM:

Esempio:

Scrive nella EEPROM il valore 0x02 alla locazione 0x10

BCF 0x03,5 ;selezione del banco RAM 0

MOVLW 0x02
MOVWF 0x08 ;scrive 0x02 in EEDATAMOVLW 0x10
MOVWF 0x09 ;scrive 0x10 in EEADR

BSF 0x03,5 ;selezione del banco RAM 1BCF 0x0B,7 ;disabilita tutti gli interrupt
;inizio sequenza di avvio scrittura
BSF 0x08,2 ;imposta ad 1 il bit WREN
MOVLW 0x55
MOVWF 0x09 ;inserisco 0x55 in EECON2
MOVLW 0xAA
MOVWF 0x09 ;inserisco 0xAA in EECON2
BSF 0x08,1 ;bit WR ad 1 -> inizio scrittura
BSF 0x0B,7 ;riabilita gli interrupt
;fine della sequenza

Interrupt

Il sistema di interrupt e' stato gia' introdotto a grandi linee alla sezione "Memoria RAM/FLASH/EEPROM". Grazie alla gestione degli interrupt, il microcontrollore puo' essere istruito in maniera tale da "porsi in ascolto" di eventi esterni durante l'esecuzione normale del programma; quando uno di questi eventi si manifesta il program counter viene temporaneamente salvato nello stack e si salta alla locazione di memoria 0x0004 (vettore di interrupt). Compito del programmatore e' quello di inserire, a partire da questa locazione, una subroutine in grado di gestire l'attuale istanza di interruzione. La subroutine di gestione delle interruzioni dovra' terminare con l'istruzione RETFIE: questa istruzione ricarica automaticamente l'ultimo program counter salvato nello stack e cosi' permette la normale continuazione del programma precedentemente interrotto. E' molto simile a RETURN e RETLW ma in piu' riporta a 1 il bit GIE del registro INTCON.
La figura sottostante ripropone il flusso di controllo che il microcontrollore segue al manifestarsi di una interruzione esterna:





Gli eventi di interruzione che possono essere gestiti dal pic 16F84 sono di quattro tipi:
  • Interrupt dal pin RB0/INT
  • Interrupt per cambio di stato dei pin RB4..RB7
  • Interrupt per completamento della fase di scrittura della EEPROM interna
  • Interrupt dal timer
Esiste un registro opportuno, tale INTCON, grazie al quale e' possibile abilitare o disabiltare tutti o in parte i quattro eventi di interrupt elencati sopra. Inoltre alcuni suoi bit vengono settati dal controllore stesso e permettono (se si vuole) di sapere, all'interno della subroutine, quale interrupt tra i quattro possibili si e' appena verificato.
Gli interrupt possono essere disabilitati del tutto settando a 0 il bit GIE (Global Interrupt Enable) del registroINTCON (il valore di default al reset e' proprio questo). Un programma che voglia far uso del sistema di interrupt dovra' preoccuparsi di porre ad 1 questo bit. Quando si verifica una interruzione, il microcontrollore setta automaticamente a 0 il bit GIE: in questo modo si evita che possano verificarsi altri interrupt durante la gestione di quello attuale. L'istruzione RETFIE, oltre a ripassare il controllo al programma interrotto, riabilita automaticamente gli interrupt, settando ad 1 il bit GIE.

Interrupt dal pin RB0/INT

L'interruzione sul piedino RB0/INT e' scatenata dal comportamento del segnale TTL su questo piedino. L'interruzione su RB0/INT viene abilitata settando ad 1 il bit INTE del registro INTCON. Ovviamente deve essere settato ad 1 anche il bit GIE.Quando il bit INTE e' settato a 0 oppure il GIE a 0 il piedino RB0/INT e' a tutti gli effetti la prima linea della porta B (RB0) e come tale puo' essere usata. Questo e' il comportamento di default del piedino. Quando pero' si attiva l'interrupt il pin non puo' piu' essere usato come linea della porta B ma esclusivamente come linea per ricevere le interruzioni dall'esterno.Esistono due modalita' di interrupt:
  • Rising edge
  • Falling edge
Con la prima (rising edge) l'interrupt viene attivato nel momento in cui la tensione sulla linea INT passa da 0 a +5 volt, quindi si presume che normalmente il livello di tensione sia il primo (0 volt). La seconda invece attiva l'interrupt quando la tensione sul piedino INT passa da +5 volt a 0, presupponendo quindi che +5 volt sia la tensione standard.
La modalita' (rising/falling edge) viene impostata settando opportunamente il bit INTDEG del registroOPTION_REG.
Una volta che il microcontrollore ha lanciato l'interruzione viene automaticamente settato ad 1 il bit INTF del registro INTCON. Questo bit puo' essere controllato dalla routine di gestione dell'interrupt per sapere se si e' verificato proprio l'interrupt associato alla linea INT oppure era qualche altra interruzione. Nel primo caso la routine dovra' provvedere a riportare a 0 tale bit altrimenti saranno inibiti i prossimi interrupt dal piedino INT.

Interrupt dal timer


Quando il contatore TIMER0 va in overflow (cioe' passa dal valore 0xFF a 0x00) viene lanciata una interruzione. L'interruzione deve pero' essere prima abilitata settando ad 1 il bit T0IE del registro INTCON. Inoltre, al verificarsi della interruzione, viene automaticamente settato ad 1 il bit T0IF del registro INTCON, e deve essere riportato a 0 dalla routine di gestione definita dal programmatore per poter mantenere abilitato il sistema di interruzione dal timer.

Interrupt per cambio di stato dei pin RB4..RB7

In questo caso viene sollevata una interruzione quando avviene un cambio di stato qualsiasi (cioe' un cambio di tensione) tra uno o piu' dei piedini RB4,RB5,RB6 e RB7. Questo tipo di interrupt puo' essere abilitato o disabilitato settando opportunamente il bit RBIE del registro INTCON.
Al lancio della interruzione viene automanticamente settato ad 1 il bit RBIF del registro INTCON.

Interrupt per completamento della fase di scrittura della EEPROM interna

Senza addentrarci troppo nel sistema di lettura/scrittura della EEPROM interna si puo' dire che, siccome la fase di scrittura e' estremamente lenta (20 ms) comparata con la velocita' tipica di esecuzione delle istruzioni del microcontrollore, e' stato pensato di permettere alla EEPROM di lanciare una interruzione al completamento della fase di scrittura. In questo modo il programma utente puo' dare il comando di scrittura e continuare subito con le istruzioni successive, per poi gestire con comodo il completamento della scrittura rilevando l'interruzione.
Questo tipo di interruzione si abilita tramite il bit EEIE del registro INTCON. Per rilevare questa interruzione occorre controllare assieme i bit RBIF,INTF e T0IF: se sono tutti a 0 allora l'interruzione e' stata lanciata dalla EEPROM.

Timer interno


Il TIMER0 e' un dispositivo interno al microcontrollore in grado di assolvere alla duplice funzione di contatore e temporizzatore. Le due modalita' sono mutualmente esclusive e possono essere scelte via software. In ogni caso il modulo e' ad 8 bit, cio' significa che e' solo in grado di contare in step di 1 unita' e ripetere ciclicamente i valori nell'intervallo da 0 a 255. Al TIMER0 e' associato un prescaler in grado di rallentare la velocita' di incremento dei valori in 8 possibili modalita' (1:2, 1:4, 1:8, 1:16, 1:32, 1:64, 1:128, 1:256). Inoltre, se si vuole, e' possibile impostare il modulo in maniera tale da produrre un interrupt ogni volta che si ha un overflow del TIMER0, cioe' ogni volta che il modulo passa dal valore 255 (0xFF) a 0 (0x00). Al TIMER0 e' associato un registro, il TMR0 (mappato nel banco 0 alla locazione di memoria 0x01); in questo registro e' possibile leggere lo stato attuale di avanzamento del contatore oppure impostarne il valore.

Modalita' temporizzatore o contatore

Il TIMER0 funziona in due modalita': temporizzatore o contatore. Nella prima il TIMER0 si incrementa ad ogni istruzione (questo in assenza di prescaler, altrimenti secondo il rapporto imposto). Il valore del registro TMR0 e' impostato a 0 per default, ma puo' essere modificato in qualsiasi momento tramite operazioni di scrittura.
Per selezionare la modalita' temporizzatore occorre impostare a 0 il bit T0CS del registro OPTION_REG.
Veniamo ora alla modalita' contatore. In questa modalita' il TIMER0 si incrementa ad ogni rising-edge o falling-edge del segnale applicato sul pin RA4/T0CKl; la modalita' di incremento (rising o falling-edge) e' selezionata impostando in maniera opportuna il bit T0SE del registro OPTION_REG (T0SE=0 per il rising-edge, T0SE=1 per il falling-edge). T0CS a 1 imposta la modalita' contatore.

Generazione dell'interrupt dal TIMER0

Ogni volta che il TIMER0 passa dal valore 255 (0xFF) a 0 (0x00) viene lanciata una interruzione che automaticamente setta ad 1 il bit T0IF del registro INTCON. L'interrupt puo' essere inibito settando a 0 il bit T0IE. T0IF deve necessariamente essere riportato a 0 dall'eventuale routine di gestione dell'interrupt affinche' possa verificarsi un nuovo interrupt. 

Prescaler

Il prescaler e' un modulo per "rallentare" la frequenza di aggiornamento del TIMER0 tramite 8 fattori di divisione prestabiliti. Il prescaler puo' essere assegnato al TIMER0 oppure (in maniera mutualmente esclusiva) al Watch-Dog interno (il Watch-Dog e' un modulo aggiuntivo del microcontrollore spiegato piu' avanti nella guida). Il bit PSA del registro OPTION_REG determina a chi associare il prescaler (al TIMER0 con PSA=0 oppure al Watch-Dog con PSA=1). I tre bit PS0,PS1 e PS2 determinano una tra gli 8 possibili rapporti di divisione di frequenza cioe' 1:2, 1:4, 1:8, 1:16, 1:32, 1:64, 1:128, 1:256. Ovviamente se il prescaler non viene assegnato al TIMER0 (cioe' PSA=1) otteniamo automaticamente un rapporto di divisione di 1:1.
Quando il prescaler e' associato al TIMER0, ogni istruizione che vada a modificare il registro TMR0 (ad esempio, CLRF 0x01, MOVWF 0x01, BSF 0x01,3 etc...) comporta automaticamente il reset a 0 dei tre bit PS0,PS1 e PS2.
Per finire, nella figura seguente sono mostrati i collegamenti interni che collegano il prescaler al TIMER0 e al Watch-Dog:





Esempio pratico: led lampeggiante


A titolo dimostrativo viene proposto un piccolo circuito in cui un led viene fatto lampeggiare. Le fasi da seguire sono essenzialmente quelle descritte alla sezione precedente e sono: creazione del progetto in MPLAB, scrittura del programma, compilazione, debugging, inserimento del codice nel microcontrollore e realizzazione del circuito. 

Il programma

Una possibile soluzione per poter far lampeggiare un led e' quella ad esempio di avere una linea di I/O che emette un segnale in cui si alternano le tensioni di 0 e +5 volt. A tale linea collegheremo in serie il led ed una resistenza limitatrice di corrente. Allo scopo puo' essere utilizzato il programma precedente che alterna i valori 0 e 1 sul bit meno significativo (il primo bit) del registro PORTB.Riportiamo il codice del programma:


;****************************************************** ; Programma di prova ; Alterna 1 e 0 sul primo bit di PORTB ogni 100ms ;****************************************************** ;direttive PROCESSOR 16F84A RADIX HEX ;definizioni R1 EQU 0x20 R2 EQU 0x21 R3 EQU 0x22 PORTB EQU 0x06 TRISB EQU 0x06 TRISA EQU 0x05 PORTA EQU 0x05 PORTB EQU 0x06 STATUS EQU 0x03 FSR EQU 0x04 INDF EQU 0x00 ;inizio programma ORG 0x0000 bsf STATUS,5 movlw 0x00 movwf TRISB bcf STATUS,5 loop: bsf PORTB,0 call wait bcf PORTB,0 call wait goto loop ;routine di attesa (circa 100ms) wait: movlw 0xBE movwf R1 longloop1: movlw 0xBE movwf R2 longloop2: decfsz R2,1 goto longloop2 decfsz R1,1 goto longloop1 return ;fine del programma END

In ogni caso andremo ad utilizzare un oscillatore al quarzo da 4Mhz quindi in ICPROG occorrera' selezionare l'oscillatore XT. Il Watch-Dog non serve percio' deve essere disabilitato (WDT non selezionato). Possiamo lasciare disabilitate le rimanenti due opzioni PWRT e CP. 

Circuito di prova

Una volta compilato e programmato correttamente il PIC occorrera' realizzare questo piccolo circuito:






In alto abbiamo il modulo alimentatore, costituito da un regolatore di tensione 78L05. DCIN deve essere collegato ad una tensione continua da almeno 9 volt.
In basso abbiamo il circuito principale costituito dal pic e da pochi altri componenti. Al piedino #MCLR e' collegato il circuito standard di reset visto nella prima sezione mentre in OSC1 e OSC2 e' collegato l'oscillatore da 4Mhz al quarzo (tipo XT). VDD e VSS sono ovviamente il piedino del positivo e di massa. Ad RB0 sono collegati il led e la resistenza limitatrice: dato che i pin di I/O del pic possono assorbire/fornire all'incirca 20mA ciascuno, allora la resistenza dovra' avere un valore non inferiore a:
(5-0.7)volt / 0.02A = 215 ohm

Dove 0.7 e' la caduta di potenziale introdotta dal led e 5 e' la tensione massima sul piedino (corrispondente al livello logico 1). Per stare sicuri e non stressare la linea con assorbimenti al limite e' stata inserita una resistenza da 330ohm.
Di default le linee della porta A sono impostate come input e siccome non vengono utilizzate occorre inserire delle resistenze di pull-up da 10K per definirne i valori di tensione. Queste resistenze possono essere evitate semplicemente impostando da programma le linee della porta A come output.