Indice |
Introduzione
Ultimamente ho ripreso lo studio dei PIC grazie agli articoli che FrancescoFP ha scritto per introdurci al mondo dei PICmicro: sono interessanti e adatti ai principianti perchè vengono spiegati tutti i passaggi senza dare nulla per scontato.
Ho voluto realizzare il primo programma seguendo due articoli che spiegano come accendere due LED alla pressione di due pulsanti:
Let's start! Il primissimo programma 1a parte
Let's start! Il primissimo programma 2a parte
Ma non è filato tutto liscio al primo tentativo perchè:
- ho incontrato delle difficoltà
- ho commesso degli errori
- ho apportato delle modifiche perchè non sempre si può, o si vuole, seguire al 100% le spiegazioni di un articolo
In particolare ho voluto usare un PIC16F84A anzichè il PIC16F887 perchè diversi anni fa mi avevano regalato qualche PIC16F84A ed anche perchè FrancescoFP stesso scrive "Qualsiasi PIC potrebbe andare bene, in quanto quello che dobbiamo fare è semplicissimo!".
Proseguo raccontandovi le prime difficoltà che ho incontrato nel realizzare il circuito e programmare il micro perchè ritengo possano essere di aiuto a molti di voi.
PIC16F84A
Mi sono subito reso conto che il mio PIC aveva 18 pin a differenza dei 40 pin del PIC di FrancescoFP, ma non è stato difficile capire come collegare i componenti del semplice circuito proposto.
Il PIC16F887 arriva sino alla porta D mentre il mio PIC ha solamente la porta A e B: ho quindi usato alcuni pin della PORTA B del mio PIC per collegare i pulsanti ed i LED, e questo è stato facile.
L'alimentazione del mio PIC inoltre è più semplice perchè avviene solo su 2 pin anzichè 4, anche in questo caso rendermene conto tramite il datasheet ed alimentare i PIN corretti è stato semplice.
E' stato invece molto più difficile capire come collegare le uscite ICSPDAT/PGD e ICSPCLK/PGC del programmatore PicKit3 al PIC perchè non trovavo sul datasheet questi riferimenti.
Ho scoperto come fare sul sito picprojects.org trovando questo pdf con le corrette indicazioni.
Ed eccoci all'ultima differenza rispetto alla configurazione usata da FrancescoFP: il mio PIC non ha un'oscillatore interno, quindi utilizzo un quarzo da 4MHz collegato ai pin 15 e 16 e due condensatori da 22pF collegati fra questi pin ed il potenziale di riferimento VSS.
Il programma
Uso l'ambiente di sviluppo MPLAB X IDE versione 1.51.
Copio e incollo il programma scritto da FrancescoFP
#include <htc.h> #define LED_0 PORTDbits.RD2 #define LED_1 PORTDbits.RD3 #define BTN_0 PORTDbits.RD0 #define BTN_1 PORTDbits.RD1 __CONFIG(CONFIG1&FOSC_INTRC_NOCLKOUT&WDTE_OFF&PWRTE_OFF&MCLRE_ON&CP_OFF&CPD_OFF&BOREN_OFF&IESO_OFF&FCMEN_OFF&LVP_OFF&DEBUG_OFF); __CONFIG(CONFIG2&WRT_OFF); void main(void){ TRISD=0b11110011; // Uguale a scrivere TRISD=0xF3, cioè tutti ingressi tranne RD2/3 uscite while(1){ LED_0=!BTN_0; LED_1=!BTN_1; } }
Innanzitutto come scritto sopra ho usato alcuni pin della PORTA B per collegare i pulsanti ed i led, quindi la prima parte del codice va modificata così:
#include <htc.h> #define LED_0 PORTBbits.RB0 #define LED_1 PORTBbits.RB1 #define BTN_0 PORTBbits.RB2 #define BTN_1 PORTBbits.RB3 ...
Poi la finestra dell'editor mi segnala degli errori sulle istruzioni __CONFIG.
Provo a controllare il datasheet trovando la parte 6.1 che spiega i CONFIGURATION BITS ed effettivamente il mio PIC sembra supportare solo la configurazione
- dell'oscillatore (Oscillator Selection bits)
- del watchdog timer (Watchdog Timer Enable bit)
- del timer di attesa all'accensione (Power-up Timer Enable bit)
- della protezione del codice (Code Protection bit)
però non ho ancora chiaro come scrivere correttamente il codice.
Inizio una ricerca infinita, trovo e scarico le Release Notes del compilatore XC8 versione 1.12:
MPLAB ® XC8 C Compiler Version 1.12 Release Notes
Al punto 1.4 trovo questa cosa interessante:
1.4. Devices Supported This compiler supports all known 8-bit PIC devices at the time of release. See pic_chipinfo.html (in the compiler's doc directory) for a list of all supported baseline and mid-range devices and pic18_chipinfo.html for a list of all supported PIC18 devices. '''These files also list configuration bit settings for each device'''.
Vado subito a cercare la cartella della documentazione del compilatore sul mio computer, che trovo in
C:\Program Files\Microchip\xc8\v1.10\docs
e lì trovo anche il file pic_chipinfo.html
Lo apro e mi si presenta una maxi tabella dove cerco il PIC16F84A, lo trovo, ci clicco sopra e mi viene aperto il file
C:/Program Files/Microchip/xc8/v1.10/docs/chips/16f84a.html
che contiene queste informazioni:
16F84A Support Information #pragma config Usage #pragma config <setting>=<named value> For example: // Oscillator Selection bits: XT oscillator // Watchdog Timer: WDT disabled // Code Protection bit: Code protection disabled // Power-up Timer Enable bit: Power-up Timer is disabled #pragma config FOSC = XT, WDTE = OFF, CP = OFF, PWRTE = OFF ... #pragma config Settings Register: CONFIG @ 0x2007 FOSC = Oscillator Selection bits XT XT oscillator LP LP oscillator EXTRC RC oscillator HS HS oscillator WDTE = Watchdog Timer OFF WDT disabled ON WDT enabled CP = Code Protection bit OFF Code protection disabled ON All program memory is code protected PWRTE = Power-up Timer Enable bit OFF Power-up Timer is disabled ON Power-up Timer is enabled
La riga del codice di configurazione di esempio fa esattamente al caso mio:
- imposta l'oscillatore per l'uso con un cristallo esterno (il quarzo da 4MHz scritto sopra)
- disabilita il watchodg timer
- disabilita la protezione del codice
- disabilita l'attesa all'accesione
quindi copio la riga e la incollo nell'editor di MPLAB sostituendo le due righe __CONFIG originali.
L'editor sembra gradire la modifica: non segnala più errori, segno che sono sulla buona strada.
TRISB
TRISD=0b11110011; // Uguale a scrivere TRISD=0xF3, cioè tutti ingressi tranne RD2/3 uscite
Nella parte principale del programma trovo questa istruzione che serve ad impostare i pin della PORTA D come ingressi o come uscite. Avendo usato dei pin della PORTA B del mio PIC, questa istruzione va modificata opportunamente! Ad esempio così:
TRISB=0b00001100;
Un errore stupidissimo che ho commesso e mi ha fatto perdere molto tempo è stato questo:
credevo che leggendo l'istruzione da sinistra a destra, il primo bit servisse ad impostare il pin RB0, il secondo il pin RB1 e così via...
Invece è esattamente il contrario! Il bit meno significativo, cioè quello finale in fondo a destra, è quello relativo al pin RB0, poi il penultimo è quello relativo al pin RB1 e così via sino al pin RB7.
Conoscere la sintassi corretta, come vedete, è fondamentale!
Device was not found
Una volta che tutto il programma è stato corretto si passa alla fase di programmazione "fisica", nel mio caso tramite il programmatore PicKit3. Ecco che in questa fase ottengo l'errore:
“Target device was not found. You must connect to a target device to use PICkit 3″
Anche in questo caso il motivo dell'errore è stupido, ed è altrettanto banale la sua soluzione.
Il problema è dovuto al fatto che nel mio circuito non esiste alcuna fonte di alimentazione alternativa al programmatore.
Il programmatore può alimentare il microcontrollore in fase di programmazione, ma affinchè lo faccia va impostato nell'interfaccia di MPLAB!
Seguite questi passaggi:
File (nel menù in alto) Project Properties Categories: PICkit 3 (a sinistra) Option categories: Power (in alto) Spuntare la voce "Power target circuit from PICkit3." ed impostare un adeguato voltaggio.
Modifiche personali
Ho voluto modificare un po' il programma per fare in modo che ogni pulsante pilotasse due led anzichè uno. La versione finale del mio codice è la seguente:
#include <xc.h> #define LED_0 PORTBbits.RB0 #define LED_1 PORTBbits.RB1 #define LED_2 PORTBbits.RB6 #define LED_3 PORTBbits.RB7 #define BTN_0 PORTBbits.RB2 #define BTN_1 PORTBbits.RB3 #pragma config FOSC = XT, WDTE = OFF, CP = OFF, PWRTE = OFF void main(void){ TRISB=0b00001100; while(1){ LED_0=!BTN_0; LED_1=!BTN_1; LED_2=!BTN_0; LED_3=!BTN_1; } }
Video
Ecco un video del circuito programmato e funzionante.
PicKit 3
Perchè procurarsi un "costoso" programmatore PicKit 3 anzichè usare uno dei tanti "cloni" a basso costo? La risposta è semplicemente "perchè funziona bene e quando incontriamo dei problemi ci permette di concentrarci sul codice e sul circuito in quanto possiamo essere ragionevolmente certi che la programmazione sia avvenuta correttamente!".
La Microchip produce il programmatore PicKit 3 ed anche i PICMicro: questa è un'ottima cosa perchè significa che il programmatore è realizzato dalla azienda che conosce a pieno le caratteristiche dei PIC.
Il programmatore quindi rispetta tutte le specifiche che regolano la programmazione del microcontrollore.
Ho scoperto che alcuni programmatori "a basso costo" spesso non rispettano tantissime specifiche e quindi programmano "male" il microcontrollore (ad esempio non forniscono la corretta tensione ad alcuni piedini del PIC in fase di programmazione, oppure eliminano il valore di calibrazione dell'oscillatore interno di alcuni PIC).