Corso programmazione PICMicro in C – Lezione 1 – Cos’e´ un microcontrollore, caratteristiche, note introduttive, come scegliere programmatore e linguaggio di programmazione.

Aggiornamento Ottobre 2017
La Microchip ha rilasciato nuovi tool per lo sviluppo: MPLAB X IDE e i compilatori XC. Per far fronte alle novità e per non riscrivere tutti gli articoli daccapo, ho scritto delle lezioni integrative per consentire il passaggio dai vecchi strumenti a quelli nuovi. Le nozioni teoriche riportate negli articoli “vecchi” sono ancora valide. Per quanto concerne la scrittura del codice, l’utilizzo dell’IDE, i codici di esempio ecc, fate riferimento alle nuove lezioni che si trovano nella categoria PICmicro nuovo corso.

Ho deciso di realizzare questo piccolo corso, tra una cosa e l’altra, perchè in molti mi hanno chiesto come si fa a programmare un microcontrollore, che linguaggio si usa, quali programmi e programmatori utilizzare ecc.

Premetto già da ora che l’argomento è davvero complesso perchè tocca davvero molti rami, bisogna avere comunque delle basi di elettronica, una certa attitudine alla programmazione e tanta tanta voglia di imparare e soprattutto costanza e capacità di non scoraggiarsi, nonchè fantasia e creatività. Se questi articoli avranno successo (le persone li gradiscono, mi lasciano commenti, richieste ecc) allora continuerò su questa strada. Oggetto di questa trattazione saranno i microcontrollori PIC della Microchip, i famosi PICMicro (o PIC come ancora a qualcuno piace chiamarli) e il linguaggio che preferisco per programmarli: il C. Prima di cominciare a parlare di come si programma un picmicro, bisogna per forza di cose dare una visione d’insieme del protagonista di questa trattazione.

Cos’è un microcontrollore? Un microprocessore e un microcontrollore sono la stessa cosa?

Chiariamo innanzitutto che un microcontrollore è qualcosa di molto più elaborato di un microprocessore. In parole molto povere: un microprocessore è un circuito integrato destinato unicamente ad effettuare calcoli. Un microcontrollore contiene al suo interno un microprocessore (CPU – sempre destinato a fare calcoli) più numerose altre periferiche che gli permettono di interagire con il mondo esterno: linee di comunicazione, un certo quantitativo di memoria per immagazzinare dati e programmi, convertitori analogico/digitali ecc. Si capisce quindi che un microcontrollore è in realtà un computer completo racchiuso all’interno di un circuito integrato; non per niente una delle definizioni che viene data della sigla PIC è proprio “Programmable Intelligent Computer” anche se io preferisco la definizione più classica “Programmable Interface Controller”. E’ chiaro che quando parlo di PIC o PICMicro mi riferisco sempre ai circuiti integrati prodotti dalla Microchip, ma di microcontrollori ne esistono una grande varietà, ognuno diverso dall’altro nell’architettura, sviluppo, linguaggi di programmazione disponibili, costi ecc (ci sono gli AVR della Atmel, gli OOPic – che sono sempre PICMicro venduti preprogrammati ma non dalla Microchip -, i Basic stamp della Parallax ecc) .

La Microchip commercializza i suoi microcontrollori con il nome di PICMicro e non PIC (PIC era il nome che avevano inzialmente quando venivano prodotti da un’altra società chiamata General Instruments)

Un microcontrollore generico viene anche identificato con la sigla MCU (Micro Controller Unit – Unità a micro controllore).

I microcontrollori PIC hanno una architettura di tipo RISC (Reduced Instruction Set Computer) ovvero questi MCU sono in grado di svolgere tutte le loro funzioni facendo affidamento ad un set ridotto di istruzioni (si parte dai PICMicro semplici che hanno soltanto 35 istruzioni per arrivare a quelli di ultima generazione che ne hanno 77), in parole povere: per scrivere il nostro programma in un linguaggio di basso livello (assembler) avremo bisogno di imparare soltanto 33 istruzioni. Se invece programmiamo in un altro linguaggio… Allora dovremo imparare le istruzioni del linguaggio che abbiamo deciso di utilizzare.

Quali sono le periferiche di cui possono essere dotati i PICMicro?

Una delle “periferiche” principali di cui è dotato un microcontrollore è sicuramente la memoria interna. La memoria di un microcontrollore ha il compito principale di immagazzinare il programma che deve eseguire e quindi anche di immagazzinare i dati (le variabili) provenienti dall’esterno o elaborate dal programma. Generalmente vengono utilizzati microcontrollori che hanno una memoria di tipo Flash (perchè più pratica e riutilizzabile). Le memorie Flash sono una varietà di memoria EEPROM (o E2PROM) (Electrically Erasable and Programmable Read Only Memory – memoria a sola lettura programmabile e cancellabile elettricamente): i dati vengono immagazzinati all’interno della memoria e lì rimangono anche in assenza di alimentazione elettrica (come le memorie delle macchine fotografiche o le pendrive insomma), quando si ha bisogno possono anche essere cancellati elettricamente. Esistono anche microcontrollori “finestrati” che hanno bisogno della luce ultravioletta per la cancellazione della memoria o anche microcontrollori che possono essere programmati una volta sola (OTP – One Time Programming) e non possono più essere cancellati (ovviamente questa è una scelta pessima per un hobbysta!).

Rimanendo in tema di memoria, bisogna aggiungere che i PICMicro hanno anche un’architettura di tipo Harvard: questo significa che la memoria è sezionata: vengono mantenute separate la memorizzazione dati e le istruzioni. Difatti la memoria dei PICMicro è suddivisa in 2 o più banchi. Programmando in linguaggi di basso livello (assembler) per eseguire le operazioni è necessario difatti specificare su quale banco di memoria stiamo lavorando, nei linguaggi di alto livello (C, Basic ecc) non è necessario specificare il banco di memoria dal momento che queste istruzioni vengono aggiunte direttamente dal compilatore senza che ce ne preoccupiamo (questo è uno dei tanti vantaggi dei linguaggi ad alto livello).

Linee di I/O. Tramite le linee di Input/Output, che non possono mai mancare in nessun microcontrollore, il nostro PICMicro è in grado di rilevare “stimoli” digitali provenienti dall’ambiente esterno (Input: pressione di un tasto, ricezione di un segnale digitale, chiusura di un contatto ecc) oppure trasmetterli (Output: accensione di un led, di un relè, azionamento di una valvola o di una serratura, scritte su un display ecc). Difatti tramite il programma che andremo ad inserire nel nostro microcontrollore, saremo in grado di dire ad esso quali pin (piedini) dovranno funzionare come ingressi (input) e quali come uscite (output).

Convertitori analogico/digitali (A/D). Tramite questo tipo di periferiche siamo in grado di acquisire un segnale analogico proveniente dall’esterno e convertirlo in un segnale digitale per poterci lavorare su ed elaborarlo nel nostro programma (es: sonde di temperatura, sonde analogiche in generale ecc). Una bella cosa davvero se dobbiamo realizzare , ad esempio, un sistema di irrigazione per il nostro giardino! Scriveremo un programma che leggerà la temperatura esterna e l’umidità del terreno, se questi dati letti rientrano in un certo intervallo, allora faremo aprire l’elettrovalvola dell’acqua per innaffiare le piante. Magari potremo farlo soltanto se è sera (leggiamo la luminosità esterna tramite una fotoresistenza!) o soltanto se siamo in una fascia oraria stabilita. Ovviamente questa è soltanto una delle innumerevoli applicazioni che possono essere realizzate da un PICMicro ma rende bene l’idea delle potenzialità di questi dispositivi, della loro capacità di interfacciarsi con oggetti di uso comune e di renderci facile il lavoro!

Moduli PWM. I moduli PWM sono in grado di generare delle onde quadre che possiamo utilizzare per svariate applicazioni, la più comune è quella della regolazione della velocità dei motori, della luminosità delle lampade ecc. Per conoscere bene il PWM fate riferimento all’ottimo tutorial scritto da Mauro Laurenti, accessibile dall’area Risorse di Settorezero.

Bus di comunicazione. Tramite i bus di comunicazione (che non sono nient’altro che linee di I/O seriali) siamo in grado di comunicare con altri dispositivi: USB, CAN, SPI, USART, I2C. L’Usart ci permette di comunicare con la porta seriale RS232 del pc o di altri strumenti (e non solo), e quindi scambiare informazioni o dare istruzioni. Il protocollo di comunicazione CAN ad esempio è molto utilizzato sulle automobili per far comunicare tra loro i vari dispositivi. Il protocollo I2C è usatissimo per comunicare con piccoli dispositivi tipo integrati realtime-clock (orologi), misuratori di distanza ad ultrasuoni, integrati che permettono di espandere gli I/O ecc ecc.

Timer. I timer o temporizzatori sono importantissimi e indispensabili. Ogni PICMicro ha almeno un timer ad 8 bit. Il compito di queste periferiche è appunto quello di effettuare conteggi in maniera regolare e vengono utilizzati un po’ per tutto: generare onde quadre, eseguire operazioni allo scadere di un tempo prefissato, realizzare applicazioni multitasking ecc.

pic12F675Ovviamente non tutti i PICMicro hanno al loro interno tutti questi moduli, ci sono PICMicro che li contengono tutti o quasi (ad esempio il PIC16F877A, un vero e proprio cavallo di battaglia della Microchip, con il suo package da 40 pin e tutte le periferiche che ha… è uno dei più versatili, così come il fratello minore PIC16F876 o il maggiore PIC18F4520 per citarne alcuni), altri che non ne contengono qualcuno ecc. (ma non mancano mai gli I/O e almeno un timer). Per cui: quando decidiamo di realizzare qualcosa, bisogna sempre sapere quale PICMicro utilizzare. A volte la cosa bella risiede proprio nel fatto che anche se il nostro PICMicro non ha questo o quell’altro dispositivo al suo interno, se siamo bravi, possiamo sempre emularlo via software o tramite dei circuiti esterni che possono comunicare con il nostro dispositivo!

La scelta di uno o dell’altro microcontrollore molto spesso risiede anche in motivi di compattezza e/o economicità del dispositivo che intendiamo realizzare e quindi ci ritroviamo a scegliere PICMicro con solo 8 pin che magari possono non avere delle periferiche, ma se riusciamo ad emularle via software, qual è il problema? Soprattutto se si può risparmiare? Nell’immagine vediamo ad esempio (sul mio dito!) un PIC12F675: in uno spazio così compatto (solo 8 pin) abbiamo 6 linee di I/O delle quali 4 utilizzabili come convertitori A/D, 2 timer di cui uno a 16bit, un oscillatore interno che ci permette di minimizzare la circuiteria esterna, e una tensione di funzionamento che arriva fino a 2Volt soltanto, per un prezzo davvero irrisorio (si può acquistare per 2 euro circa). Questo ad esempio lo utilizzo personalmente per fare i telecomandi a infrarossi (anche se è sprecato per questo scopo, ma perlomeno è facile da reperire).

Quali sono i linguaggi di programmazione che si possono utilizzare per scrivere il programma da inserire nel nostro PICMicro?

Il linguaggio di programmazione predefinito dei PICMicro è l’assembler. L’assembler è sicuramente un modo molto potente di gestire il nostro microcontrollore ma non è certo il più semplice da apprendere. Per programmare in assembler bisogna avere prima di tutto una profonda conoscenza dell’architettura interna del PICMicro che stiamo utilizzando e  una mente davvero molto elastica: realizzare le cose in assembler richiede spesso davvero molte righe di codice, che magari in C vengono scritte in maniera molto più semplice e/o intuitiva. Ma l’assembler in alcuni rari casi è davvero necessario. Le istruzioni assembler disponibili per ogni PICMicro sono contenute nel suo Datasheet, così come la descrizione della segmentazione della memoria e di tutte le funzioni. Per cui: quando programmate un PICMicro, abbiate sempre l’accortenza di avere a portata di mano il suo Datasheet, che si può scaricare gratuitamente dal sito della Microchip. I Datasheet sono disponibili unicamente in inglese e questo non dovrebbe costituire un problema dal momento che chi si appresta a fare una cosa del genere dovrebbe sapere in partenza che la grande maggioranza del materiale è sempre scritto in inglese (ma questa “regola” è valida per qualsiasi disciplina in generale).

Il linguaggio che personalmente preferisco per la programmazione dei PICMicro è il C. Ogni casa produttrice di software ha implementato (purtroppo) una propria versione del C, questo porta ad una tragica conseguenza: non tutti i programmi scritti in C per un compilatore possono funzionare con un  diverso compilatore C per PICMicro. I linguaggi C che seguono gli standard vengono chiamati ANSI-C, uno di questi è l’HITEC-C della HTSoft (che però è a pagamento, a meno che non si scarichi la versione Lite, gratuita anche per scopi commerciali, che però presenta delle limitazioni – ed è questa quella che utilizzeremo in questi articoli). Oltre all’assembler e al C, esistono anche il Basic e di recente anche il Pascal. Ma procediamo per passi: a cosa serve il compilatore?

Noi scriviamo il nostro programma col linguaggio che preferiamo: ovvero digitiamo una serie di istruzioni per dire al PICMicro COSA deve fare, COME si deve comportare ecc. Ovviamente il PICMicro non è in grado di eseguire questo programma così come noi l’abbiamo scritto, per cui allo stesso modo con cui si scrive un programma per PC è necessario in qualche modo convertire (passatemi il termine, assolutamente inappropriato)  il nostro codice sorgente in codice eseguibile (linguaggio macchina), ovvero: interpretabile dal dispositivo che lo deve eseguire.

Il compilatore esegue appunto questa operazione: trasforma il codice sorgente in linguaggio macchina. Nel caso dei PICMicro, il compilatore che sceglieremo avrà il duro compito di analizzare innanzitutto il programma che abbiamo scritto per andare alla ricerca di errori, e successivamente compilarlo per tirare fuori un file con l’estensione .HEX:  è questo il file (il programma scritto in linguaggio macchina) che andrà ad essere inserito nel Microcontrollore tramite un programmatore.

Possiamo fare affidamento ad una grande varietà di linguaggi: teniamo conto, però, che non tutte le suite di programmazione possono essere integrate in MPLAB, anche se esistono altri sistemi di sviluppo (elencati più in basso):

C

XC8, XC16, XC32 sono le nuove versioni dei compilatori Microchip, disponibili sia come free (con limitazioni sull’ottimizzazione e sulla grandezza massima del codice) e a pagamento.
Hitec-C OBSOLETA, sostituita dai compilatori XC della Microchip
Mikro-C (a pagamento, la versione demo è completamente funzionante ma limita l’HEX a 2Kwords)
SDCC (completamente Free e Open Source, segue lo standard ANSI, ma a quanto pare è difficile da integrare nel sistema di sviluppo della Microchip, è possibile però integrarlo in Piklab, vedi sotto)
CCS-C (a pagamento)
BoostC e BoostC++ (a pagamento e free con limitazioni)
MPC C Compiler
(a pagamento, disponibile versione dimostrativa)
CC5X (a pagamento e free)
CPik (solo per Linux e per PIC18)

BASIC
PicBasic (a pagamento)
GCBasic (Free, Open Source)
MikroBasic (a pagamento)
BoostBasic (a pagamento e free con limitazioni)

PASCAL
JAL (free)
JALV2 (free)
MikroPascal (a pagamento)
PMP (Pic Micro Pascal) (Free)

FLOW CHART/ALTRO
Flowcode (a pagamento)
KTechLab (open source, per Linux)
Visual Parsic (Editor visuale,  ? pare che lo sviluppo sia fermo)
Ladder Logic (Compilatore linguaggio Ladder, free)

SUITE DI SVILUPPO
Microchip MPLAB IDE (free)
Microchip MPLAB X (free, cross-platform)
Piklab (free – molti sistemi operativi supportati)
Pikdev (free, solo per Linux, supporta solo assembler e C per PIC18)
GPUtils (free – attualmente non c’è la versione per windows)
Pic Simulator Ide (free e a pagamento) – Suite di sviluppo e simulazione in Basic

L’unico che ho utilizzato io (per ora) è HITEC-C della HTSoft, ed è con questo che illustrerò le lezioni. Il motivo di tale scelta (HITEC-C) è semplice: segue lo standard ANSI e, in applicazioni del genere, seguire uno standard per me è una caratteristica che deve essere primaria: vuol dire che potremo utilizzare lo stesso codice sorgente anche per altri compilatori, su più piattaforme, senza la necessità di dover fare adattamenti, poi è supportato ufficialmente dalla Microchip (difatti il compilatore C di base viene integrato automaticamente nel setup di MPLAB).

Appena ho tempo mi piacerebbe riuscire ad utilizzare l’SDCC (che è completamente free ed opensource) abbinato alla suite Piklab. Appena ci riuscirò, pubblicherò di certo qualcosa.

Esistono anche le versioni C18 del C. Il C18 viene utilizzato unicamente per le ultime generazioni dei PICMicro (i 18Fxx e successivi) e comprendono un set di istruzioni più ampio (perchè i 18F e successivi hanno appunto un set di istruzioni maggiorato). La stessa HTSoft ha una versione C18, nonchè la Microchip che ne distribuisce una versione gratuita per gli studenti (C18 Student Edition).

Ovviamente il C18 può essere utilizzato esclusivamente per programmare i PICMicro della famiglia PIC18, PIC24, PIC32 e dsPIC, per cui non può essere utilizzato con le altre famiglie (PIC12, PIC16 ecc).

I compilatori possono essere utilizzati così come sono oppure essere integrati nel sistema di sviluppo della Microchip: l’MPLab IDE, che è la soluzione che preferisco, anche perchè l’HITEC-C è a riga di comando e viene integrato in automatico nell’MPLab, per cui non devo fare tanta fatica per compilare il programma ;)

Aggiornamento importante!

La Microchip ha abbandonato MPLAB IDE 8 ed è passata ad MPLAB X IDE, ha abbandonato i compilatori Hi-Tech PICC, il C18, C30 e C32 e ha unificato il tutto con i compilatori XC: Fate riferimento a questo nuovo articolo per tutti gli aggiornamenti

Quale programmatore utilizzare?

Beh… Qui la scelta dipende molto dai gusti personali, da cosa si vuole programmare ecc. Generalmente si inizia sempre con un programmatore autocostruito, questa è sicuramente una buona scelta perchè ci permette di capire il meccanismo con il quale i PICMicro vengono programmati ed è una cosa che consiglio di fare a tutti anche perchè avere un programmatore costruito con le proprie mani da sicuramente molta soddisfazione.

Anni fa molti utilizzavano un programmatore su porta seriale con pochissimi componenti (l’arcinoto JDM programmer), che riusciva a programmare (a stento per il vero) i PIC16F84 e 16C84. La costruzione di un programmatore del genere la sconsiglio vivamente: i PIC per essere programmati hanno bisogno che vengano rispettate delle specifiche altrimenti o la programmazione non va a buon fine (e starete a sbattere la testa pensando che è il PIC ad essere difettoso, quando invece la colpa è soltanto del programmatore) o in rari casi il PIC viene danneggiato irreparabilmente.  Molti ignorano che per far entrare un PICMicro in modalità programmazione è necessario fornire esattamente 13.5 Volt sul pin denominato MCLR, e tanti programmatori tralasciano questa semplice, necessaria, regola.

fisertek_programmerUn programmatore molto buono e semplice da costruire è quello ideato da Sergio Fiocco che è basato su uno schema molto classico. Potete trovare schema e descrizione sul suo sito (al quale ho fatto riferimento pure io per incominciare la programmazione in C). Tale programmatore è un classico a prova di bomba, l’unico neo (forse) è che prevede l’uso della porta parallela per il collegamento al PC, per cui sui portatili di ultima generazione non lo potete utilizzare (a meno che non utilizziate un adattatore usb/parallelo… ma per esperienza vi dirò che questi adattatori fanno tutto fuorchè il lavoro per il quale sono stati progettati! E non immaginate che nervi!). Sui portatili sprovvisti di parallela, se si ha la fortuna di disporre di uno slot PCMCIA si può ricorrere all’utilizzo di schede pcmcia che forniscono una porta parallela (questa soluzione è sicuramente funzionante rispetto all’utilizzo di un adattatore usb anche se il costo è elevato).

Ogni programmatore ha poi ovviamente bisogno del suo software di programmazione: ovvero un programma che ha il compito di leggere il file HEX generato dal compilatore e quindi comunicare con il programmatore per farli inserire il programma all’interno del PICMicro. Io per anni, insieme al programmatore di Fiser ho utilizzato il mitico IC-Prog (Free).

Personalmente dopo il programmatore autocostruito di Fiser, mi sono rivolto a uno strumento ideato dalla stessa Microchip: il PICKit2, un vero piccolo gioiello (oggi giunto alla versione 3 ma con un prezzo molto più elevato, anche perchè viene fornito con una scheda di sviluppo):

picckit2

Tale programmatore oltre a presentare il netto vantaggio di essere davvero piccolo e funzionante su USB senza alimentazioni aggiuntive, ha anche altri lati positivi: costa poco, il firmware è aggiornabile, lo si può utilizzare anche come tester per segnali digitali e ha un suo software di programmazione realizzato dalla stessa Microchip. Il “problema” dei 13.5 Volt è stato risolto dalla Microchip in questo programmatore con un survoltore integrato in grado di elevare la 5 volt fornita dall’usb al voltaggio richiesto. La stessa Microchip ha anche reso disponibile lo schema elettrico di questo piccolo prodigio della tecnica, e questa è sicuramente una cosa degna di nota.

Per quelli che si chiedono: come fa il PICKit2 a programmare i PICMicro se su di esso non  c’è nessuno zoccolo? La risposta è: il PICKit2 utilizza un connettore ICSP (continua a leggere) per la programmazione dei PICMicro: la programmazione avviene direttamente sulla scheda in cui è montato il microcontrollore, oppure potete farvi voi una schedina con gli zoccoli e il connettore ICSP.

Aggiornamento
Abbiamo inserito un articolo su come realizzarsi una piccola scheda adattatrice per programmare i vari tipi di picmicro e le eeprom con il pickit2:
Adattatore multizoccolo per pickit2

I PICMicro possono essere programmati in vari modi qualora il PICMicro scelto abbia disponibile la modalità di programmazione desiderata. Di default tutti i PICMicro possono essere programmati in maniera standard, ovvero con i normali programmatori che danno i 13.5 V sull’MCLR più i normali segnali di programmazione e alimentazione.

Molti altri PICMicro hanno anche disponibile la funzione LVP (Low Voltage Programming) che permette la programmazione a basso voltaggio (ovvero non dovremo più fornire i 13.5 V sul pin MCLR ma soltanto 5V) ma richiede per la programmazione l’utilizzo di un pin aggiuntivo (contrassegnato come PGM, normalmente non utilizzato per la programmazione standard).

Altra buona modalità di programmazione di alcuni PIC è quella tramite BootLoader: si programma per la prima volta il PIC in maniera normale, inserendo al suo interno un programma particolare che prende il nome  di Bootloader (ne esistono tanti, la stessa MicroChip ne rende disponibile una sua versione), che occupa poco spazio. Le volte successive, quando dobbiamo riprogrammarlo, si farà utilizzo unicamente della porta seriale del PC: sarà il PIC, tramite le funzioni svolte dal bootloader, a capire se si deve mettere in modalità di programmazione oppure in modalità di esecuzione programma.

Quest’ultima è sicuramente una soluzione molto comoda, a parte il fatto che il Bootloader andrà ad occupare parte di memoria che verrà sottratta alla nostra applicazione, ma permette di non smontare il PIC dal circuito e di non disporre di un programmatore vero e proprio (almeno per le volte successive alla prima in cui è comunque necessario un normale programmatore per caricare il bootloader).

Predisponendo però opportunamente il nostro circuito, possiamo programmare il PIC in modalità normale (quindi senza bootloader e senza programmazione a basso voltaggio) anche mantenendolo montato nel circuito di utilizzo. In questi casi si fa uso di quella comodissima funzione chiamata ICSP (In-Circuit Serial Programming) che ormai tutti i PICMicro hanno già di serie e questa è la modalità che preferisco: programmazione normale, senza problemi di ingegnerizzazione (a patto di avere un buon programmatore) e soprattutto senza smontarlo dal circuito di utilizzo.

» Vai all’ indice delle lezioni e delle risorse del corso di programmazione

Se questo articolo ti è piaciuto, condividilo su un social:
Se l'articolo ti è piaciuto o ti è stato utile, potresti dedicare un minuto a leggere questa pagina, dove ho elencato alcune cose che potrebbero farmi contento? Grazie :)