Corso programmazione PICMicro in C – Lezione 3 – Il primo programma in C: scrivere un semplice programma in C per PICMicro, impostare MPLAB e flashare il PICMicro con il PICKit2. Facciamo lampeggiare un LED!


Scritto da Giovanni Bernardo in data 18 agosto 2009

primo_programma_picmicro_in_c_flashare_con_pikcit2_circuitoFinalmente dopo le precedenti due lezioni, per lo più introduttive, eccoci alla parte pratica! In questa lezione scriveremo il nostro primo programma in C, lo compileremo e lo caricheremo sul PICMicro per vederlo in azione.

Ovviamente il primo programma è sempre qualcosa di molto molto semplice: faremo lampeggiare un diodo led. Certo non è un qualcosa di molto entusiasmante, ma bisogna partire a piccoli passi per comprendere a fondo tutto quello che c’è dietro ai programmi più complessi.

Ricordate lo schema elettrico del circuito di base presentato nella seconda lezione? Bene, andremo a collegare sul pin n° 19 (che rappresenta la porta RD0, ovvero la prima delle porte D) un diodo led, con in serie una resistenza da 330Ω (che ha la funzione di limitare la corrente che circola nel LED, in maniera tale da non farlo bruciare). Realizzeremo  quindi il seguente schema:

primo_programma_picmicro_in_c_mplab_schema_thumb

Quando andrete a montare il LED, tenete conto che il terminale più corto dei due è quello che va verso massa. Se lo montate al contrario non si accenderà. Fate una prova alimentandolo con 5 volt e con la resistenza da 330Ω: vedrete che in un senso si accenderà e dall’altro no. Anche se emette luce, si tratta pur sempre di un diodo ed è quindi capace di far circolare la corrente in un verso soltanto.

La porta RD0 è stata scelta a caso, avremmo potuto collegare il LED su qualsiasi altra porta indifferentemente: ci serve difatti unicamente la funzione di I/O digitale, che come abbiamo visto nelle lezioni precedenti, è a disposizione di qualsiasi porta.

Se state utilizzando per questi esperimenti la scheda Freedom di Mauro Laurenti, per poter utilizzare le varie porte per gli esperimenti, potete crearvi una piattina che da un lato si innesta nella scheda di sviluppo e dall’altro invece presenta uno strip da 10 contatti in linea che possiamo utilizzare facilmente per la connessione con una breadboard:

primo_programma_picmicro_in_c_adattatore_freedom_breadboard

Parte 1 -- Scriviamo il programma

Dopo aver montato tutto il circuito, possiamo procedere alla scrittura del nostro primo programma. Personalmente per scrivere il programma in C, utilizzo Notepad++ (mi piace perchè è freeware, evidenzia le parole chiave con colori diversi, ha il supporto della sintassi per molti linguaggi, la numerazione delle righe ecc). Voi ovviamente potete utilizzare ciò che più vi piace, anche il blocco note di windows (anche se non lo consiglio affatto, è buono avere un editor tipo Notepad++ che evidenzia la sintassi).

Questo è il primo programma che andremo a scrivere (sarà comunque possibile scaricarlo in fondo all’articolo per gli utenti iscritti: è gratis!), creiamo un file di testo vuoto, diamogli il nome “main.c” e incolliamoci all’interno il seguente codice:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//*************************************************
// CORSO PROGRAMMAZIONE PICMICRO
// www.settorezero.com
//
// modulo: main.c
// autore: Bernardo Giovanni
// data: 18/08/09
// descrizione: lampeggia un led su RD0
// picmicro: PIC16F877A
// clock: 20MHz
//
//*************************************************
 
#define  XTAL_FREQ 20MHZ // questo è utilizzato dalle routine di ritardo contenute in Delay.C
#include <pic.h> // contiene i nomi mnemonici di registri e porte
 
// Fuses di configurazione
__CONFIG (HS & WDTDIS & PWRTEN & BORDIS & LVPDIS & DUNPROT & WRTEN & DEBUGDIS & UNPROTECT);
 
#include "delay.c" // routine per ritardi
#define    LED    RD0 // invece di scrivere RD0, scriverò LED, così mi è più facile ricordare
 
// funzione principale, eseguita all'avvio del picmicro
void main(void)
 {
 
 // imposto i registri tristato in maniera tale che tutte le porte siano configurate come pin di uscita
 TRISA=0b00000000;
 TRISB=0b00000000;
 TRISC=0b00000000;
 TRISD=0b00000000;
 TRISE=0b00000000;
 
 while(1) // eseguo un ciclo finito
 {
 LED=LED^1;
 DelayMs(250);
 }// Fine ciclo continuo
 
 } // Fine main

Analizziamo quindi il programma. Quello che si trova dietro il doppio backslash (//) sono semplici annotazioni, verranno ignorate dal compilatore, servono soltanto al programmatore a “ricordarsi” cosa succede. E’ sempre buona norma mettere all’inizio del programma un’intestazione con le date ecc, e che specifica autore, scopo del programma e quant’altro vogliamo, se non altro ci aiuterà tra qualche anno quando dovremmo rimettere mano a un codice per modificarlo o migliorarlo.

14
#define  XTAL_FREQ 20MHZ

Le righe che iniziano con il cancelletto (#) sono direttive inviate al compilatore, ovvero non si tratta di vere e proprie istruzioni di programma, ma di istruzioni inviate al compilatore e che non occuperanno spazio in memoria programma. In questa riga in particolare, l’istruzione define dice al compilatore che quando all’interno del programma troverà la scritta “XTAL_FREQ”, la dovrà sostituire con il valore “20MHz”. Non si tratta affatto dell’assegnazione del valore ad una variabile, stiamo soltanto definendo un nome alternativo per un valore, il che ci aiuta molto a ricordare. Questa riga in particolare è utilizzata da una routine (che vedremo in seguito) che serve a generare ritardi.

15
#include <pic.h>

è un’altra direttiva (vedete? c’è il cancelletto): stiamo dicendo al compilatore di includere in quel punto, il file “pic.h”.  In pratica tale direttiva leggerà il contenuto di quel file e lo inserirà in quel punto. Questo è un buon modo per scrivere codice “portabile”: una volta scritta una porzione di codice riutilizzabile, non ci sarà bisogno di riscriverla sempre nei nostri programmi, basterà “includerla”. Quando tale direttiva include un file contenuto nella cartella “include” dell’installazione del compilatore, tale file va scritto tra < e >, quando invece il file da includere si trova in un altro percorso, allora va incluso tra virgolette ” ” (in particolare se tra virgolette indichiamo unicamente il nome del file, il compilatore assume che tale file da includere si trovi nello stesso percorso del file principale, ovvero main.c).

Il file pic.h in particolare, che già si trova nella cartella “include” di installazione dell’Hitec-C, contiene tutte le definizioni dei nomi delle porte e dei registri dei vari picmicro. In pratica non dovremo ricordarci tutti gli indirizzi di memoria (che sono numerici!) del nostro PICMicro: basterà ricordarsi i nomi “mnemonici”, molto più facili da ricordare perchè i loro nomi rispecchiano in un certo qual modo le funzioni dei registri. Impareremo man mano a utilizzare i nomi mnemonici quando ne avremo bisogno. In particolare il file pic.h includerà a sua volta un altro o più file con estensione .h a seconda del PICMicro che sceglieremo durante la compilazione del programma.

Quando programmerete in C, incontrerete essenzialmente due tipi di file di testo, con estensione .c (che  contengono funzioni, programmi principali) e con estensione .h. h sta per Header, ovvero “intestazione”, si tratta in genere di files ausiliari che contengono settaggi, prototipi di funzioni ecc, necessari per il funzionamento delle funzioni principali, si tratta in pratica di una convenzione e buona pratica di programmazione. Ovviamente noi potremmo scrivere tutto il nostro codice in un unico file, ma avere il file principale, soprattutto se si tratta di programmi complessi, suddiviso in più files c e h ci aiuterà molto a concentrarci su una parte di programma e ci permetterà di rendere il nostro programma, o le nostre funzioni, riutilizzabili in altri ambiti anche totalmente differenti da quelli per cui sono stati progettati.

Date una sbirciatina nella cartella “include” del compilatore (C:\Programmi\HI-TECH Software\PICC\PRO\9.65) : vedete? Ci sono un sacco di files .h, ognuno che contiene vari #define a seconda del picmicro che andremo a scegliere. Il file pic.h è quello generico, che si accorgerà di quale pic abbiamo scelto (durante l’operazione di compilazione che vedremo dopo) e che provvederà a includere il file .h adatto: in particolare per il PIC16F877 sarà incluso il file pic1687x.h.

Andiamo avanti con la spiegazione del programma:

18
__CONFIG (HS & WDTDIS & PWRTEN & BORDIS & LVPDIS & DUNPROT & WRTEN & DEBUGDIS & UNPROTECT);

Questa parte qui è un po’ più complicata… Si tratta in pratica di una funzione (chiamata appunto “__CONFIG” definita nel file pic.h) che serve a settare i FUSES (o fusibili) di configurazione del picmicro e di cui abbiamo già accennato qualcosina nelle precedenti lezioni. Ogni picmicro ha un suo registro di configurazione con i propri valori (vedete pag. 144 del datasheet del PIC16F877A) e che serve per impostare le modalità di funzionamento. I valori che si trovano tra parentesi (ovvero gli argomenti della funzione) sono nomi mnemonici (ogni parola, tipo HS è in realtà un valore numerico, definito da vari #define contenuti nei file h del picmicro scelto), che vengono combinati tramite AND logici per ottenere la word di configurazione adatta. In particolare questo settaggio dice:

HS (High Speed) = intendiamo utilizzare un oscillatore al quarzo ad alta frequenza.

WDTDIS (Watch Dog Timer DISabled) = disabilitiamo il Watch Dog Timer: si tratta di un timer che ha la funzione di resettare il pic se il programma si blocca e quindi far ripartire il programma daccapo, noi per ora (e forse mai) non utilizzeremo questo timer, dobbiamo programmare bene per fare in modo che il programma non si blocchi!! In realtà tale funzione a volte è utile, ma noi probabilmente non la useremo.

PWRTEN (PoWeRup Timer ENabled) = il pic aspetta alcuni microsecondi all’accensione prima di avviare il programma, in maniera tale da far stabilizzare la tensione e l’oscillatore.

BORDIS (Brown Out Reset DISabled) = il brown out è una funzione che permette di resettare il pic se la tensione di alimentazione scende al di sotto di un dato valore, tale funzione non ci serve, quindi la disattiviamo.

LVPDIS (LowVoltage Programming DISabled) = disabilitiamo la programmazione a bassa tensione (abbiamo visto nelle lezioni precedenti di cosa si tratta).

DUNPROT (Data UNPROTected) = la memoria dati non sarà protetta

WRTEN (WRite ENabled) = scrittura memoria flash abilitata

DEBUGDIS (DEBUG DISabled) = funzioni di debugging disabilitate, il debug non è disponibile con il pickit2

UNPROTECT = non protegge la memoria programma

Questi sono i settaggi ideali per gli esperimenti: proteggere la memoria dati, programma, eeprom, disattivare la scrittura, potrebbe difatti renderci impossibile riprogrammare il PIC una seconda volta, quindi se sbagliamo, il pic sarà da buttare! Quindi non proteggiamo assolutamente nulla!

20
#include "delay.c"

Stiamo includendo il file delay.c (scaricabile insieme a tutto il progetto in fondo all’articolo, per gli utenti iscritti) che si trova nello stesso percorso del file principale. Tale file include delle routine per creare ritardi (delay). Includendo questo file avremo a disposizione nel nostro programma due funzioni: DelayMs(n) che ci permetterà di eseguire ritardi di n millisecondi (con n da 0 a 255) e DelayUs(n) che ci permetterà di eseguire ritardi di n microsecondi. I ritardi sono funzioni molto importanti nei programmi.

21
#define    LED    RD0

Ancora un’altra direttiva! Stiamo dicendo al compilatore che quando leggerà la parola “LED” all’interno del programma, gli dovrà sostituire il valore RD0 (ricordate lo schema? Abbiamo collegato il led alla porta RD0, è più facile ricordarsi LED, sapendo che li cè collegato un led, piuttosto che RD0, vi pare?). La parola (o forse meglio il SIMBOLO) RD0 è a sua volta definito in uno di quei file h che abbiamo incluso all’inizio e contiene l’indirizzo di memoria che “mappa” la porta RD0, non ci dovremo preoccupare a quale indirizzo si trova la porta RD0, tanto abbiamo già tutti i nomi mnemonici già definiti per il nostro pic (definiti da pic.h, incluso all’inizio). Quindi come c’è RD0, ci sarà anche RA1, RB3 ecc ecc, comodo no?

Finalmente inizia il programma vero e proprio:

24
25
void main(void)
 {

Chiariamo innanzitutto una cosa, qui stiamo scrivendo una funzione, questa funzione si chiama “main” (scritto minuscolo!, ricordate che il C è case-sensitive! Ovvero fa distinzione tra maiuscole e minuscole!). La funzione chiamata main è quella che viene eseguita all’accensione del picmicro, per cui tutti i nostri programmi avranno sempre una funzione chiamata così.

Il “void” scritto all’inizio indica che tale funzione non restituisce valori (void=vuoto), il void scritto tra parentesi dopo main, indica che tale funzione non accetta valori in ingresso. La funzione main difatti non può nè deve accettare/restituire valori. Ci saranno altre funzioni che potranno accettare valori per eseguirci su dei calcoli e quindi restituire un valore, altre che restituiranno un valore ma non accetteranno niente in ingresso, altre ancora che accetteranno valori in ingresso ma non restituiranno niente.

Una cosa del genere ad esempio:

int somma(int a, int b)

definisce una funzione chiamata “somma”, che restituisce un numero intero (int), e accetta in ingresso due variabili (a e b) interi anch’essi. L’int messo davanti (al posto del void) specifica appunto un intero, int è uno specificatore del tipo di dato. Fate riferimento alla pagina 83 del file “manual.pdf” contenuto nella cartella docs del compilatore (C:\Programmi\HI-TECH Software\PICC\PRO\9.65\docs) per vedere quali sono i tipi di dato disponibili in C. Qui vi riporto un estratto:

tipi_di_dato_hitec_c

Ricordate inoltre: tutto ciò che deve essere eseguito dalla funzione, deve trovarsi tra parentesi graffe! Per cui: ricordiamoci di chiudere le parentesi dopo che le abbiamo aperte. E’ sempre buona norma mettere sempre prima entrambe le parentesi (aperta e chiusa) e quindi successivamente scriverci tutto all’interno.

Ovviamente qui qualcuno andrà nel pallone non trovando le parentesi graffe sulla tastiera. Le parentesi graffe si inseriscono tenendo premuto ALT (quello a sinistra, NO ALT GR) e quindi digitando in sequenza 1-2-3 sul tastierino numerico (ho detto sul tastierino! Non funziona con i numeri sopra alle lettere!) e quindi rilasciando il tasto ALT per la parentesi aperta, stessa cosa ma digitando 1-2-5 per la parentesi chiusa, e così anche per tutti gli altri caratteri che non trovano posto sulla tastiera.

Proseguiamo nella lettura del programma con qualcosa di più interessante:

28
29
30
31
32
TRISA=0b00000000;
TRISB=0b00000000;
TRISC=0b00000000;
TRISD=0b00000000;
TRISE=0b00000000;

I registri TRIS (regisatri tristato, ve ne ho accennato nella lezione 2) ci sono per ogni gruppo di porte (TRISA è il registro tristato delle porte A, e… TRISB ?). Notate innanzitutto che dopo l’uguale abbiamo uno 0b, questo zero-bi indica al compilatore che il numero che segue è in formato binario, se avessimo messo 0x (zero-ics) voleva dire che il numero che seguiva era scritto in esadecimale, invece senza notazione alcuna sarebbe stato scritto in decimale). Vi rimando ad un mio precedente articolo sulla numerazione binaria ed esadecimale, imparare queste cose non fa mai male. Sempre a pagina 83 del manuale dell’Hitec-C troviamo un’altra tabella con i prefissi da usare per specificare la base con cui scriviamo i numeri:

tipi_di_formato_numerico_hitec_c

Scrivendo

TRISA=0b00000000;

Stiamo dicendo che tutti i bit del registro tristato delle porte A, devono essere impostati su ZERO. Cosa significa? Impostare nel registro tristato un bit a zero equivale a impostare quella porta (quel pin) come USCITA (Output, per aiutarvi a memorizzarlo ricordate la somiglianza tra lo zero e la lettera O di Output…), impostare un bit a 1 equivale rendere quella porta (quel pin) un ingresso (Input, 1 somiglia alla lettera I, giusto? ;) ). In particolare il bit più significativo (ovvero l’ottavo bit) è quello più a sinistra: quello più vicino alla lettera b, andando verso destra troviamo il bit 7, 6 ecc fino ad arrivare al bit1 che viene detto bit meno significativo. Il bit1 mappa la porta 0, il bit2 mappa la porta 1 e così via. In pratica se noi scriviamo:

TRISA=0b00000010;

Diremo al PICMicro che la porta RA1 dovrà essere una porta di ingresso (abbiamo messo l’uno sul secondo bit, che mappa la seconda porta, ovvero la RA1) mentre tutte le restanti porte dovranno essere pin di uscita. Abbastanza semplice non trovate? Per questo motivo il settaggio delle porte lo scrivo in binario, così visivamente mi accorgo di quale porta sto impostando come ingresso e quale come uscita, ovviamente nulla mi vietava di scrivere 0x2 (notazione esadecimale) oppure 2 (notazione decimale) al posto di 0b00000010 … (usate la calcolatrice di windows in modalità scientifica per capire che ho detto se non ci siete arrivati…).

Ovviamente alcuni banchi di porte non disporranno di tutti e 8 i bit: ricordate l’immagine del datasheet del PIC16F877? Osservate: Le porte A sono soltanto 6 (da RA0 a RA5), quando vorremo settare questa porta, è buona norma per noi mettere comunque tutti e 8 i bit, ovviamente i bit 7 e 8 li metteremo a zero, tanto pure se li mettiamo a 1 non avranno effetto perchè le porte RA6 e RA7 su questo PIC non esistono… (per non parlare delle porte E che sono soltanto 3… Qui avremo a disposizione soltanto i bit 1, 2 e 3, gli altri bit da 4 a 8 li metteremo sempre a zero perchè tali porte non esistono).

Bene, abbiamo quindi settato tutte quante le porte del nostro PIC16F877 come uscita!

Quando nel nostro circuito rimarranno pin non utilizzati, è sempre bene impostare tali porte come uscite, perchè se le impostiamo come ingressi e non vengono utilizzate, potrebbero captare disturbi di natura elettromagnetica che dobbiamo sempre evitare come la peste.

Proseguiamo:

34
35
while(1) // eseguo un ciclo finito
 {

Qui abbiamo un ciclo while (vi rimando all’ottima lettura TrickyC presente nell’area risorse del sito, pagina 79, per capire come funzionano i 3 tipi di cicli disponibili in C) che verrà eseguito all’infinito perchè vi abbiamo messo 1 come condizione, che è sempre vera. All’interno di questo ciclo troviamo la parte interessante:

36
37
LED=LED^1;
DelayMs(250);

Qui stiamo accendendo e spegnendo il led!! Ma come? Iniziamo col dire che DelayMs(250) esegue una pausa di 250 millisecondi (ricordate le funzioni DelayMs incluse nel file delay.c di cui abbiamo parlato più in alto?), in pratica il led rimarrà acceso 250 ms e spento altri 250ms per poi ricominciare daccapo. L’accensione e lo spegnimento del led vengono eseguiti dall’istruzione LED=LED^1. Chiariamo innanzitutto che il simbolo ^ in C non è l’elevamento a potenza ma rappresenta la funzione di XOR, in pratica quando su un bit viene eseguito l’XOR con 1, viene invertito lo stato del bit: diventerà 1 se era 0 e viceversa.

Fate riferimento a questo nostro articolo per conoscere come si effettuano le operazioni di algebra booleana.

Scrivere LED=1 significa “dare tensione” a quel pin (ricordate? LED=RD0), quindi se scrivo LED=1 la porta RD0 si porterà in condizione di livello logico alto, ovvero da quel pin usciranno 5volt, per cui il led si accenderà, scrivere LED=0 porterà la porta RD0 in stato logico basso, per cui da quel pin usciranno zero volt (massa) e il led si spegnerà, scrivere LED=LED^1 significa semplicemente invertirne lo stato… Dal momento che dopo viene una pausa, si avrà l’effetto di vedere il led accendersi e spegnersi ogni 250ms (se avete la fortuna di avere un oscilloscopio, vedrete su tale pin un’onda quadra con la frequenza di 2Hz).

Difatti per portare un’uscita a livello logico alto (far uscire 5 volt), basta impostare tale porta a 1, per renderla bassa, si imposta a zero. Non dovrebbe risultare complicato.

Ci tengo a far notare che tutte le istruzioni devono terminare con un punto e virgola, altrimenti si verificheranno errori strani e incomprensibili durante la compilazione, e spesso gli errori vengono segnalati in una parte di programma che non c’entra nulla quando mancano il punto e virgola o non viene chiusa una funzione.

Abbiamo infine la chiusura del ciclo while e quindi della funzione main:

38
39
40
}// Fine ciclo continuo
 
} // Fine main

Ok… Abbiamo scritto il nostro primo programma (ok l’abbiamo copiato oppure scaricato!), abbiamo capito (si spera) come funziona… Non ci resta che compilarlo, caricarlo sul PICMicro e vedere come funziona!


Parte 2 -- Compiliamo il programma

Abbiamo questa situazione: in una cartella ci sono i files: main.c, delay.c e delay.h scaricati in fondo all’articolo. Avviamo MPLAB IDE, Selezioniamo Project -> Project Wizard

primo_programma_picmicro_in_c_mplab_01

Comparirà la finestra del wizard (ovvero la procedura guidata) :

primo_programma_picmicro_in_c_mplab_02

Clicchiamo su Avanti, ci verrà chiesto di selezionare il dispositivo (il PICMicro) che intendiamo utilizzare per questo progetto:

primo_programma_picmicro_in_c_mplab_03

Scorriamo la lista e troviamo PIC16F877A, premiamo quindi Avanti. Ci verrà mostrata la finestra nella quale dobbiamo scegliere quale suite di linguaggio intendiamo utilizzare:

primo_programma_picmicro_in_c_mplab_04

Dal menù Active Toolsuite selezioniamo HI-TECH Universal ToolSuite come nella figura (l’abbiamo installato nella lezione 2, ricordate?), premiamo quindi Avanti, dovremo dare un nome al nostro progetto:

primo_programma_picmicro_in_c_mplab_05

Premiamo sul tasto Browse e andiamo a trovare la cartella in cui abbiamo salvato main.c e tutto il resto, nella casella nome file mettiamo un nome facile da ricordare: lampeggia_led, come in figura:

primo_programma_picmicro_in_c_mplab_06

Premiamo quindi salva, ritorneremo nella finestra precedente:

primo_programma_picmicro_in_c_mplab_07

Clicchiamo su Avanti, ci verrà chiesto di aggiungere dei files al progetto:

primo_programma_picmicro_in_c_mplab_08

Selezioniamo soltanto main.c e premiamo sul tasto Add>> per aggiungerlo al progetto, premiamo quindi Avanti. Sarà mostrata una finestra di riepilogo:

primo_programma_picmicro_in_c_mplab_09

Possiamo quindi premere Fine, verremo riportati alla finestra principale di MPLab:

primo_programma_picmicro_in_c_mplab_10

Vedete sulla sinistra c’è una finestra più piccola in cui è evidenziato il nostro codice sorgente main.c, anche se non abbiamo incluso gli altri file nel progetto durante il wizard, funzionerà tutto lo stesso perchè saranno inclusi dal compilatore grazie alle direttive #include che abbiamo scritto nel programma. Possiamo passare a compilare il programma. Vedete nella barra degli strumenti ci sono due tasti: uno nero e uno rosso:

primo_programma_picmicro_in_c_mplab_11

Quello nero è per compilare la prima volta, quello rosso è per RI-compilare nel caso avessimo già compilato e modificato qualcosa (verranno cancellati dei file “di appoggio” e ricompilato tutto daccapo). Premiamo il tasto nero. La compilazione prenderà generalmente meno di un minuto (dipende da tanti fattori) e se tutto è andato per il meglio, sarà presentata una finestra di riepilogo con le operazioni di compilazione e una scritta BUILD SUCCESSFUL alla fine:

primo_programma_picmicro_in_c_mplab_12

Vedete in questa finestra ci sono molte informazioni: quanta memoria programma abbiamo utilizzato (lo 0.9%, ma ricordate che stiamo utilizzando la versione LITE che non ci permette di utilizzare tutta la memoria programma disponibile ma ha un limite di 2000h words, con una versione PRO lo spazio a disposizione è molto di più, inoltre con la versione pro viene abilitata una funzione, chiamata Omniscient Code Generation, che permette di risparmiare ulteriore spazio, fino al 52% in meno, dal momento che ottimizza ancor più il codice compilato).

Quando qualcosa andrà storto, ci sarà invece scritto BUILD FAILED, con l’elenco dei numeri di riga che hanno dato l’errore, in questo caso dovremo individuare l’errore, correggerlo e ricompilare (premendo il tasto rosso anzichè quello nero). Errori tipici dei principianti sono:

  • dimenticanza del punto e virgola alla fine di una riga che lo prevede
  • dimenticanza della chiusura di una o più parentesi graffe
  • dimenticanza che il C è case sensitive, per cui se abbiamo dichiarato una “VarIABILE” e la richiamiamo come “variabilE”, non sarà riconosciuta, stessa cosa per le funzioni e per tutto il resto: rispettate maiuscole e minuscole!

Andiamo a controllare la cartella dove avevamo messo main.c, vedete, ci sono un sacco di altri file, a noi ne interessa in particolar modo uno soltanto: lampeggia_led.hex, quello con estensione HEX! E’ questo qui che dobbiamo caricare nel PICMicro? Come?

Parte 3 -- Carichiamo il programma compilato nel PICMicro

Colleghiamo il PICKit2 alla porta USB del computer e innestiamolo nel connettore ICSP del circuito (ricordatevi di non tenere alimentato il circuito, anzi staccategli proprio i fili dell’alimentazione quando lo programmate).

Per sapere come va collegato il PICKit2 ai vari tipi di PICmicro (e anche alle memorie EEPROM), può esservi utile questo nostro articolo: Adattatore multizoccolo per PICKit2.

Avviamo il programma PICKit2:

primo_programma_picmicro_in_c_flashare_con_pikcit2_01

Dovrà essere presente il messaggio “PICkit2 found and connected” come in figura, dal menù “Device”, dove c’è scritto “-Select Part-”, scorriamo fino a scegliere PIC16F877A

Se PIC16F877A non è presente nell’elenco potrebbe essere necessario andare sul menù “Device Family” e selezionare Midrange -> Standard

primo_programma_picmicro_in_c_flashare_con_pikcit2_02

Come vedete cambia il valore di Configuration (che è il valore che sarà assegnato al registro di configurazione, non curiamoci di quello che esce scritto in questa fase, dal momento che il programma non l’abbiamo ancora caricato) e il valore di Checksum. Il Checksum in particolare è un valore che in un certo qualmodo identifica il programma che abbiamo caricato, quando faremo piccole o grandi modifiche a uno stesso programma, vedremo che tale valore cambierà, quindi due programmi perfettamente uguali avranno lo stesso checksum, è un buon modo per identificare un programma.

Andiamo avanti, dobbiamo caricare il nostro programma in memoria. Dal menù File selezioniamo “Import Hex”:

primo_programma_picmicro_in_c_flashare_con_pikcit2_03

Cerchiamo la cartella con il programma e selezioniamo “lampeggia_led.hex”:

primo_programma_picmicro_in_c_flashare_con_pikcit2_04

Premiamo quindi Apri, il file Hex sarà importato in memoria e cambieranno tutti i valori nell’interfaccia:

primo_programma_picmicro_in_c_flashare_con_pikcit2_05

In particolare cambierà il valore di configuration, che per i nostri esperimenti sarà sempre 2F02. Vedete che il campo program memory adesso contiene tanti valori, quei valori rappresentano appunto il nostro programma compilato: ovvero convertito da codice sorgente (comprensibile per gli esseri umani) a linguaggio macchina (comprensibile per il dispositivo).

Avete collegato il PICKit2 al circuito vero? Bene… Premiamo il tasto Write:

primo_programma_picmicro_in_c_flashare_con_pikcit2_06

Attendiamo un po’ che il nostro fido programmatore carichi nella memoria del PIC tutto il necessario: configurazione e programma. Dopodichè, se tutto va per il meglio, deve apparire la magica scritta:

primo_programma_picmicro_in_c_flashare_con_pikcit2_07

Ovviamente c’è un certo senso di soddisfazione: adesso il programma che abbiamo scritto è memorizzato all’interno del microcontrollore! Non ci resta che staccare il programmatore, e dare alimentazione al circuito. Il risultato che otterremo è questo:

Certo non è molto entusiasmante, ma avete visto quanto mi ci è voluto per insegnarvelo? Spero che abbiate capito tutto. Lasciate commenti e se potete, supportate il sito e chi ci lavora per passione. Nella prossima puntata cercheremo di fare di meglio ;)

Downloads

File di supporto alla terza lezione del corso di programmazione picmicro in C (237)

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

Articoli che potrebbero interessarti:

L'articolo ti è piaciuto o ti è stato utile per risolvere un problema? Supporta e mantieni in vita questo sito, ci basta soltanto un caffè o una birra

  1. #1 da Piero Vigliocco il 30 agosto 2009

    Buon giorno Gianni,
    ho scaricato e letto le prime due parti del corso di programmazione C per picmicro, non sono un guru della programmazione e per questo sono caduto in molti tranelli come acqiustare un libro di programmazione consigliato per un certo HW per poi scoprire che avevano poco a che fare l’uno con l’altro. ( Tutto fà anche imparare sbagliando )
    Sara per questo motivo che del Tuo corso trovo molto valido nonchè onesto il modo di consigliare che cosa usare, come usare e perchè usare una cosa al posto dell’altra.
    Le due prime parti che ho letto le ho trovate molto ben spiegate e spero ( ne sono quasi certo ) che leggendo anche la terza parte dove ho intravisto del codice sia spiegato altrettanto bene ( mi piacerebbe fosse spiegato un semplice programma in C per pic16F877A con pulsante e led, ” pulsante a uno led a uno, pulsante a zero led a zero ).
    Per me quello che stai facendo è un ottimo lavoro. Grazie e a presto.

  2. #2 da Gianni il 30 agosto 2009

    Ti ringrazio davvero di cuore per ciò che mi dici. Io in realtà non sono un professionista, sono un appassionato che lavora con queste cose fin da piccolo, seguendo il lavoro del padre con passione maniacale. Accetto volentieri i tuoi consigli e le tue richieste e di sicuro ci sarà una lezione sui dispositivi di input, come i pulsanti, anche se nella prossima avrei intenzione di parlare degli interrupt, che è una cosa essenziale per lavorare in multitasking, e quindi gestire più eventi in contemporanea. Purtroppo a causa di vari problemi non riesco a dedicare molto tempo a questa mia passione, per cui le lezioni non saranno pubblicate con cadenza regolare, anche perchè essendo un po’ certosino voglio essere sicuro di non commettere errori prima di pubblicare qualcosa. Il programma di questa lezione l’ho commentato abbastanza, cercando di far capire bene tutto, generalmente non spiattello mai le cose senza far capire cosa si sta facendo e cerco sempre di dare esempi ed alternative perchè per me è l’unico modo di apprendere bene una cosa e fissarla in mente. Se hai problemi o se qualcosa non si capisce bene, chiedi pure senza problemi.

  3. #3 da Fabrizio il 2 settembre 2009

    Ottimo lavoro, veramente, con un minimo di basi di elettronica e programmazione in 3 lezioni si può fare già qualcosa di concreto…
    Inoltre mi hai risposto ad alcune domande che mi sono sempre chiesto lavorando sui PICMicro.
    Attendo la tua lezione sugli interrupt e il multitasking (fork sui PICMicro?).
    Quando parlerai di ingressi cerca di spiegare bene anche la parte “elettrica” quindi come collegare un semplice pulsante oppure come ricevere segnali da altri apparecchi. Stessa cosa anche per le uscite, un led è semplice ma se volessi collegare un rele le cose si complicano.
    Non sono domande (ho già un po di esperienza) ma consigli da uno che si è sbattuto per anni per queste cose e conosce bene i problemi pratici… e visto che sai scrivere in modo semplice continua queste lezioni!!!
    Grazie e complimenti

  4. #4 da Gianni il 2 settembre 2009

    No non si tratta di fork (anche se in realtà pur conoscendo il termine non sono a conoscenza delle tecniche reali con cui si realizza tale modalità). In realtà con i PICMicro si sfrutta l’interrupt sul timer0 per incrementare altri contatori e creare processi asincroni: si fissa una scadenza per ogni funzione da eseguire e all’occhio umano sembra avvenire tutto in contemporanea ma in realtà non è così. Pilotare un relè pure è una cosa semplicissima, ovviamente non lo si può collegare direttamente all’uscita di un picmicro, si utilizza sempre un transistor in “modalità interruttore”. Ok metterò pure questo…Grazie dei consigli… L’argomento è qualcosa di fin troppo vasto… Come detto sopra non sono un esperto… Anch’io mi sono sbattuto su queste cose per tantissimo tempo e non immagini che difficoltà proprio perchè spesso si fa affidamento a qualche testo su internet che ti piazza le cose davanti senza spiegarle mandandoti ancora più nel pallone…Così ho capito che l’unica soluzione era mettersi di santa pazienza a studiare per bene i datasheet, le application note, i manuali forniti a corredo del compilatore e affidandomi ai consigli di gente esperta, ma esperta davvero: esperta col cuore. Voglio ricordare qui Sergio Fiocco e Guido Ottaviani, due robottari per passione.
    Un’altra cosa che odio sono i “professori” in alcuni forum che non ammettono di aver sbagliato, che portano avanti tesi senza senso alcune volte affermando anche che le cose sui datasheet sono sbagliate… Assurdo…
    Nessuno è perfetto e tutto questo sito e i suoi contenuti sono soltanto spunti per continuare ad imparare e fornire iniziative di discussione…. Spero di trovare una mezza giornata di tempo per scrivere il prossimo articolo sugli interrupt. Grazie di cuore, critiche e consigli sono sempre molto ben accetti :)

  5. #5 da Edoardo il 5 settembre 2009

    Ciao gianni….anche io volevo congratularmi con te per il lavoro svolto finora. io sono uno studente di ingegneria e sto preparando la tesi su un picmicro…più in particolare il pic 16F690…un pò + piccolo di quello dell’esempio. io devo lavorare sulla comunicazione tra dipositivi utilizzando il protocollo spi. ho trovato molto interessante questa terza lezione che si basa proprio sulla programmazione…quello di cui avevo bisogno in questo momento. se ho problemi posso contattarti????se si lo devo fare sempre tra queste pagine????grazie mille e buon lavoro.

  6. #6 da Gianni il 5 settembre 2009

    Sono molto felice di quello che mi dici. Sulla comunicazione SPI non sono ferrato perchè non l’ho mai utilizzata, ma non è difficile trovare esempi in giro, potrei aiutarti a cercare, per fare degli esperimenti potresti usare delle EEprom SPI (quelle della serie 25XX se non erro, che vengono anche usate come BIOS su alcune schede madri, il PICKit2 ne supporta alcuni modelli), non penso che a livello software sia molto differente dagli altri tipi di comunicazione. Per il resto si puoi contattarmi come vuoi o qui tra i commenti o via email, se gli argomenti sono attinenti all’articolo, preferisco qui tra i commenti perchè possono essere d’aiuto anche ad altri o comunque generare argomento di discussione (per me l’unica soluzione ai problemi è parlare, confrontarsi e sperimentare). Nel mio piccolo sarò ben lieto di aiutarti.

  7. #7 da Valerio il 12 settembre 2009

    Ciao Gianni, ti volevo ringraziare per la messa on line di questo tutorial molto utile. Mi sto avvicinando ora alla programmazione dei PIC (già conosco cmq il C) e ti volevo chiedere dove si può trovare l’ elenco dei fuses da configurare con _CONFIG. Io in particolare utilizzo un pic18f2025 e la guida di C18 mi riporta al datasheet del pic. Ma (a causa dell’ inesperienza) non riesco a trovare nulla.. :-( Mi sapresti consigliare? Anche per i pic16 (almeno per capire in che sezione-sottosezione.. andarli a reperire) se nn lavori in particolare con i pic18.
    Grazie mille e complimenti ancora..

  8. #8 da Gianni il 12 settembre 2009

    Io generalmente per avere l’elenco dei fuses do un occhio sia al Datasheet, in cui viene riportata la locazione di memoria del registro di configurazione e quindi anche dei valori ad esso associati, sia ai file che vengono inclusi in pic.h quando vai a programmare, faccio un confronto e capisco quali sono i valori che mi interessano.

    I pic della serie 18 non li ho ancora utilizzati, so che hanno più di un registro di configurazione, difatti anche nel pickit quando li selezioni, escono più word da configurare. Se non erro per la serie 18 non si utilizza più il comando __config (o ne è stato sconsigliato l’utilizzo) per settare i fuses ma si settano uno ad uno utilizzando delle direttive #pragma.

    Il pic che utilizzi probabilmente è il 18F2520 (hai scritto 2025 e non trovavo nulla), sto dando un occhio al datasheet. Come tutti i datasheet della microchip, il registro di configurazione viene descritto nella sezione “Special features of the cpu”, precisamente pag.249 (251 da adobe reader). Ci sono 7 registri a 16 bit da configurare, ma penso che per un utilizzo normale non sia necessario settarli tutti quanti. Dai un occhio nella cartella del compilatore se trovi qualche file .h interessante nel quale recuperare le informazioni che possono servire, poi ti consiglio soprattutto di dare un occhio all’ottimo lavoro di Mauro Laurenti sulla programmazione in C18 a questo indirizzo:
    http://www.laurtec.com/Italiano/Tutorial/C18%20step%20by%20step/Tutorial.html

  9. #9 da Gianni il 12 settembre 2009

    Ok penso di aver trovato ciò che ti interessa. Innanzitutto ciò che dicevo pare sia confermato: per la serie 18 non si utilizza più __config ma si usano le direttive #pragma, per cui si userà una cosa tipo: #pragma config [parametro] = [valore], tipo per il quarzo high speed si farà: #pragma config OSC = HS.
    Il problema è appunto quello di trovare i nomi mnemonici dei parametri e dei valori da associare…
    Nella pagina: http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2123&param=en024286 si fa riferimento ad un “PIC18 Configuration Settings Addendum” che elenca la lista dei bit di configurazione per i dispositivi C18 supportati da MPLABC18, e che è disponibile attraverso il “sistema di aiuto dell’MPLAB” … Stranamente in tale pagina non è linkato e non vedo perchè devono far impazzire le persone a cercarselo… comunque facendo una ricerca con google lo si trova subito. Ti riporto qui il link:
    http://ww1.microchip.com/downloads/en/DeviceDoc/51537A.pdf
    I fuses di configurazione del PIC18F2520 sono descritti da pagina 81 (87 su adobe reader) a pagina 84. Spero sia quello che cercavi… Ci ho messo un po di tempo a cercare informazioni ;) facci sapere

  10. #10 da Gianni il 12 settembre 2009

    Già che mi trovavo e che ho notato che è molto difficoltoso riuscire a trovare quel documento sul sito della Microchip, ho aggiunto nella sezione risorse:

    http://www.settorezero.com/wordpress/risorse/

    sia il documento con l’elenco dei fuses di configurazione per i PIC18, sia la guida per l’MPLAB C18, la quale spiega anche come vanno utilizzate le varie direttive, tra cui la #pragma

  11. #11 da valerio il 13 settembre 2009

    proprio quello che cercavo.. grande.. :-) beh grazie mille. adesso ci incomincio a lavorare. appena ho news interessanti ti dico. grazie ancora..

  12. #12 da mauri il 2 dicembre 2009

    Compilando l’esempio di Lampeggia_led, del corso di programmazione, mi escono due messaggi di errore:
    Error [800] C:\Users\Lab_3\AppData\Local\Temp\s4s4.; 41. undefined symbol “WRTEN”
    Error [800] C:\Users\Lab_3\AppData\Local\Temp\s4s4.; 41. undefined symbol “DUNPROT”.
    Cosa significa?

  13. #13 da Giovanni Bernardo il 2 dicembre 2009

    Significa che quei due simboli non sono stati definiti. Molto probabilmente non stai usando il 16F877 ma un altro pic. WRTEN e DUNPROT sono due simboli (definiti dalla direttiva #define) presenti nel file h del 16F877 e di altri pic che hanno queste due funzioni. Se utilizzi un pic differente (che quindi non ha questi 2 fuse di configurazione) oppure un altro linguaggio diverso dall’Hitec-C, quei due simboli non ti vengono definiti. In linea di massima puoi procedere a cancellare quei due simboli dalla funzione config anche se ti conviene spiegare meglio che pic stai usando e se hai fatto modifiche al codice.

  14. #14 da Giovanni Bernardo il 2 dicembre 2009

    Non la prendere come un monito, ma se leggevi bene l’articolo, ci saresti potuto arrivare da solo a capire l’errore, lo dico pure per te, così arrivi ad afferrare per bene i concetti e a capire cosa vogliono dire eventuali errori. Gli errori difatti recitano testualmente: “Simbolo non definito “WRTEN”" ecc. Vuol dire difatti che il compilatore incontra una parola a lui sconosciuta, questo perchè WRTEN e DUNPROT in qualche modo non sono stati descritti da nessuna parte. Fanno parte dei fuse di configurazione e se hai usato il codice così com’è, con un pic16f877A e con l’hitec-C questo errore non deve essere restituito. Se apri il file pic.h (incluso all’inizio del codice), noti che al suo interno richiama un ulteriore file .h in base al tipo di pic scelto (settato da mplab in fase di progetto), in questo ulteriore file sono definiti tutti i simboli che mappano le variabili e le varie locazioni di memoria del pic, tra cui appunto i valori dei fuses di configurazione.

  15. #15 da maverik46 il 17 gennaio 2010

    Ciao Giovanni, bellissima guida, pero’ non ho capito bene il sorgente delay.h e delay .c :

    1) #define MHZ *1000L –>1000L , cosa sta’ a significare L , per caso loop?

    2)#if XTAL_FREQ >= 12MHZ –>perche’ metti questa condizione ?

    3)#define DelayUs(x) { unsigned char _dcnt; \
    _dcnt = (x)*((XTAL_FREQ)/(12MHZ)); \
    while(–_dcnt != 0) \
    continue; }

    –> Di questa e della successiva non ho capito ne’ la sintassi ne cosa sta’ a significare

    Riguardo delay.c potresti spiegare l’ algoritmo che usi per fare il ritardo ?

  16. #16 da Giovanni Bernardo il 17 gennaio 2010

    Ciao,
    le routine di delay non le ho scritte io, si trovano un po’ dappertutto, se vai sul sito http://www.microchipc.com ce ne sono tante altre, tra cui una con precisione migliorata, il senso di mettere la condizione della frequenza del quarzo serve proprio a cambiare le routine di ritardo per permettere di avere una precisione migliore. La L dovrebbe stare a significare “LONG” nel senso che effettuando la moltiplicazione si comunica al compilatore che il valore che si ottiene è di tipo long (cioè a 32bit). Le routine in delay.c sono semplici cicli, al posto del for utilizzano un ciclo do/while: la parte di codice che si trova nel DO viene eseguita fintanto che la condizione verificata dal while rimane vera, il decremento del contatore viene fatto stesso nella condizione del while. Effettuare il ciclo al contrario come specificato in una lezione, rende il codice più snello (ovvero traducendolo in linguaggio macchina si ottengono meno istruzioni rispetto al ciclo fatto in incremento).

  17. #17 da maverik46 il 17 gennaio 2010

    Ma quindi per ogni pic modello di pic la MIchrochip mette a disposizione le routine delay ? dove devo cercarle esattamente sul sito ? perche’ e’ un po’ confusionario quel sito pieno di link

  18. #18 da maverik46 il 17 gennaio 2010

    Scusa la grammatica dell’ ultimo messaggio !!! Un’ altra cosa , in delay.c sai per caso il perche’ di quei valori 996 e 250 ?

  19. #19 da Giovanni Bernardo il 17 gennaio 2010

    Il sito che ho linkato non è un sito della microchip, facci caso che ha una C finale: microchipC. E’ un sito che fornisce codici scritti in C per dispositivi microchip. Le routine di delay sono valide per tutti i pic: non è che esiste una routine delay per ogni pic: una va bene per tutti. Ce ne sono varie sicuramente: alcune piu precise, altre meno precise ecc. Il motivo di quei numeri è che sono stati fatti dei calcoli per ottenere dei ritardi precisi tenendo conto del tempo impiegato dalle istruzioni. Fare retro-engineering per capire da dove saltano fuori è faticoso sicuramente, ma dal momento che queste due routine sono usate in ambito universale, le tengo per buone e non mi va di verificarle, anche perchè i delay non devono essere necessariamente precisi per le applicazioni che sviluppo io. Una routine di interrupt lo deve essere, ma un semplice ritardo per antirimbalzo o altro non fa saltare il circuito o il programma se sgarra di qualche microsecondo.

  20. #20 da McGyver86 il 7 febbraio 2010

    Ciao Giovanni, che dire se non COMPLIMENTI… Bravissimo veramente utilizzi un linguaggio semplicissimo anche per spiegare istruzioni non proprio immediate (almeno per me che ho appena intrapreso la strada dei PICmicro..)! Approfitto per chiederti una info: io utilizzo un pic16f84A… Ho provato a cambiare il sorgente adattandolo al mio PICmicro, non riesco però a capire una cosa: ho compilato il tutto su hitec c, con il risultato build successfull, dopodichè ho lanciato pickit2 programmer e ho importato il file .hex! a questo punto sulla finestrella gialla di pickit2 mi compare questa scritta: ‘Warning: No configuration wordss in hex file. In MPlab use file-export to save hex with config.’ Ho provato da mplab a importare l’hex ma sulla finestra di program memory vengono scritti soltanto i primi 4 bit(??).. per caso mi sapresti illuminare sull’accaduto?? Scusami se ti disturbo e grazie mille per le lezioni che metti a disposizione di tutti!!

    Un Saluto!!

  21. #21 da Giovanni Bernardo il 7 febbraio 2010

    La config word per il 16f877 è differente da quella del 16F84A. Sostituiscila con:
    __CONFIG (WDTDIS & PWRTEN & UNPROTECT & DATUNPROT & HS);

  22. #22 da McGyver86 il 7 febbraio 2010

    Grazie per la risposta, l’avevo già cambiata!! questo è il codice:

    #define XTAL_FREQ 4MHZ // questo è utilizzato dalle routine di ritardo contenute in Delay.C
    #include // contiene i nomi mnemonici di registri e porte

    // Fuses di configurazione
    __CONFIG (WDTDIS & PWRTEN & UNPROTECT & HS);

    #include “delay.c” // routine per ritardi
    #define LED RB0 // invece di scrivere RB0, scriverò LED, così mi è più facile ricordare

    // funzione principale, eseguita all’avvio del picmicro
    void main(void)
    {

    // imposto i registri tristato in maniera tale che tutte le porte siano configurate come pin di uscita
    TRISA=0b00000000;
    TRISB=0b00000000;

    while(1) // eseguo un ciclo finito
    {
    LED=LED^1;
    DelayMs(250);
    }// Fine ciclo continuo

    } // Fine main

    grazie per il tempo dedicatomi!

  23. #23 da McGyver86 il 7 febbraio 2010

    Caro Giovanni ho risolto da solo (non proprio solo, le tue pagine mi hanno fatto da guida!) qualche prova qua e la e sono riuscito ad accendere un led!! che soddisfazione.. eheheheheh!! Grazie mille, ma non pensare di esserti liberato di me così facilmente!! eheeheh!!

    Un Saluto!!

  24. #24 da McGyver86 il 8 febbraio 2010

    Ciao giovanni, posso rubarti 2 minuti?? una domanda… non so perchè ma quando imposto i registri tristato per la portb, il PICmicro programmato non esegue questa impostazione e devo scrivere ogni porta per impostare il bit.. mi spiego meglio se nel file settings scrivo

    TRISB=0b00000000; tutte porte output,
    il programma non mi ‘vede’ questa impostazione e mi accende tutti i led collegati alle porte b, se invece scrivo:

    RB0=0;
    RB1=0;

    ecc ecc, il programma allora mi ‘vede questa impostazione e i led rimangono spenti.. non so spiegarmi il motivo, per la porta invece tutto bene (sono collegati 4 pulsanti e se scrivo TRISA=0b00000001; il programma riconosce come input il pulsante connesso all’uscita RA0!!)

    grazie per la tua disponibilità! un saluto!

  25. #25 da Giovanni Bernardo il 8 febbraio 2010

    Chiariamo innanzitutto che il TRIS serve per settare la funzione I/O dei pin, mentre il PORT (e quindi anche i singoli bit RA1,RA2,RB1 ecc ecc) serve per settare il livello alto/basso di un pin impostato come uscita. La Microchip dice che (anche se può sembrare strano) devi impostare prima il PORT e poi il TRIS. Quindi fai prima PORTB=0 e poi TRISB=0.

  26. #26 da McGyver86 il 8 febbraio 2010

    GRAZIE MILLE, mi sfuggiva proprio questo particolare dell’impostazione di PORT. Grazie ancora.. Forse a quest’ora non è il caso di offrirti un caffè ma un ammazza caffè te lo offro più che volentieri..

    Cin Cin..

    Un Saluto!

  27. #27 da McGyver86 il 10 febbraio 2010

    … mi chiedevo… ma l’ammazza caffè ti è arrivato??

  28. #28 da Giovanni Bernardo il 11 febbraio 2010

    Si. Grazie di cuore :)

  29. #29 da McGyver86 il 12 febbraio 2010

    ciao Giovanni, ho un problemuccio!! ho scritto un codice per pic16f84A che mi permette l’accensione (e spegnimento) in sequenza di 8 led, una cosa tipo supercar… Il problema è che i ritardi di accensione dei led non sono costanti, mi spiego meglio… ho scritto il codice in maniera che ogni 250 Ms si accenda un led e si spenga il precedente, ogni ritardo è stato incrementato di 250 Ms (led1 si accende dopo 250 Ms, led2 dopo 500 e spengo il led1 ecc ecc) solo che al momento dell’esecuzione del programma i led non si accendono in maniera costante rispettando i 250 Ms tra un’accensione e un’altra, ma senza rispettare i ritardi… sapresti darmi un consiglio??

    Grazie in anticipo…
    Saluti, Alessio.

  30. #31 da McGyver86 il 12 febbraio 2010

    i cicli for mi attendono… studiare, studiare, studiare, studiare e ancora studiare!!!

    Grazie mille!

  31. #32 da Giovanni Bernardo il 12 febbraio 2010

    Scarica il manuale Tricky C dall’area risorse

  32. #33 da linchip il 21 febbraio 2010

    Ciao! Bella guida. Ho una domanda? Ho caricato il programma per far lampeggiare il led con un programmatore jdm autocostruito e utilizzo MPLAB con il c18 per programmare. Questo è il mio primo programma ed è la prima volta che utilizzo i pic. I componenti elettronici del programmatore, il pic e il led per testare il programma sono attualmente montati su una breadboard sperimentale. Scusa le premesse, ma la mia domanda è: esiste la maniera di programmare tramite C affinchè la linea MCLR sia collegata a +5V in maniera interna al pic senza ogni volta scollegare la linea di programmazione e portarla a +5V? Ho letto in giro che è possibile, ma non ho capito quale comando bisogna utilizzare. Grazie.

  33. #34 da Giovanni Bernardo il 21 febbraio 2010

    Il modo per programmare i pic con 5V su MCLR esiste. Si chiama LVP, Low Voltage Programming. Va impostato nella word di configurazione ma si deve utilizzare anche il pin denominato PGM. Ma il JDM ovviamente non supporta tale modalità a meno che non fai tu qualche modifica al circuito, e dubito fortemente che ti possa funzionare e che comunque possa interessare a qualcuno, dal momento che chi vuole programmare i pic non si affida mai ad un programmatore su rs232.
    Non posso esserti d’aiuto perchè quel tipo di “programmatore” (chiamarlo programmatore è davvero un’offesa per i programmatori veri) ha fatto perdere tempo e voglia a parecchie persone e personalmente lo aborro. I pic18 poi… Non la prendere a male ma …. Detto tra noi… Vuoi provare a programmare un pic18 con un JDM?!?!?! O_O SHHHH!!!!

  34. #35 da linchip il 22 febbraio 2010

    Veramente non è quello che chiedevo….ho letto che esiste la maniera per portare alta la linea MCLR internamente al chip tramite programma…senza usare la resistenza di pull up esterna….non mi riferivo alla programmazione LVP che disabilito sempre nella configurazione. Per quanto riguarda il JDM funziona alla perfezione con il PIC18F1220 che mi sono trovato sotto banco come campione. Quindi non si tratta di provare, ma già funziona alla grande e scarico tramite ic-prog il file hex generato da MPLAB e C18. Non si tratta neanche di fortuna poichè in realtà basta verificare se le tensioni necessarie ci sono senza perdere nessun tempo. Mi sono avvicinato ai microcontrollori della Microchip per curiosità e non avevo la necessità di passare a un programmatore della casa, visto che utilizzo AVR e piattaforma Arduino da circa un anno con estremo entusiasmo e permettimi di dirmi che è tutto un altra cosa ( lo dico semplicemente per l’architettura assurda dei PIC). Attualmente mi interessa cercare solo la soluzione al mio quesito. Grazie comunque e complimenti ancora per l’impegno e la divulgazione tecnica.

  35. #36 da Giovanni Bernardo il 22 febbraio 2010

    Che io sappia non esiste tale modalità di programmazione. Le modalità di programmazione dei pic sono 3: normale con i 13,5 volt su MCLR, LVP con 5 volt su MCLR e pullup sul pin PGM oppure tramite bootloader, senza sfruttare mclr ma caricando un bootloader sul pic che acquisisce il programma tramite seriale e opportuni software, e basta… Non mi risultano altre modalità di programmazione, puoi pure provare a chiedere sul forum della microchip, in inglese.

    Per quanto riguarda la questione “fortuna” permettimi di dire che è proprio così, perchè la microchip fornisce delle specifiche ben precise, e se il pic si programma senza 13,5Volt su MCLR (e il JDM non li potrà mai fornire essendo alimentato con la seriale, potrebbe arrivare massimo a 12volt, o forse qualcosa di più ma a questo punto dipende dal pc in uso e non più dal programmatore) vuol dire che si è fortunati, perchè è capitato tra le mani un pic più “tollerante”, o si è usato un pc più datato che fornisce una buona tensione su seriale. La prossima volta potrebbe non capitare con lo stesso pic oppure ancora se si utilizza un computer differente. La bontà di un programmatore sta difatti nella capacità di programmare i controllori per cui è stato progettato indipendentemente da altri fattori esterni (come appunto il pc in uso). Ma questo non sono nemmeno io a dirlo, se ti rivolgi a forum più specializzati, come quello di roboitalia, probabilmente i “guru” ti diranno la stessa identica cosa. Prova ad esempio ad usare il jdm con un adattatore usb/seriale: li la rs232 non supera i 10v e difficilmente qualche pic potrà essere programmato. Si tratta di specifiche tecniche, difatti tutti i programmatori buoni (ma anche quelli cinesi, cloni del pickit2, che costano pure 4 soldi) hanno sempre un’alimentazione esterna o un gruppo survoltore a bordo. Il JDM era buono anni fa, con i vecchi pc (che avevano buona tensione su seriale) e i vecchi pic. Io col JDM su un vecchio pc non sono mai riuscito a programmare più di un 16F84, già l’84A non mi veniva programmato e non sai per quanto tempo pensavo fosse il pic guasto fino a che non ho fatto un programmatore su parallela alimentato esternamente.

    Per gli AVR non ti so dire nulla perchè non li ho mai provati, ma su alcuni forum vengono criticati a favore dei pic. Purtroppo in questo campo penso non si possa dire questo è meglio dell’altro, tutto è in funzione di troppe variabili. Io (per esempio) potrei dire che gli avr sono pessimi solo perchè non li trovo nei negozi di elettronica o perchè si trova meno materiale in giro rispetto ai pic. Ma questo è solo un esempio. In moltissimi si trovano bene pure con i basic stamp (che alla fine sono pic preprogrammati) solo perchè sono relativamente facili da programmare. Certo è che se vuoi realizzare un semplice automatismo, come pure un semplice telecomando a infrarossi, o un semplice timer ecc, non conviene certo utilizzare arduino e un pic puo essere ancora piu economico e funzionale di un ne555 a patto di saperlo programmare. Non si puo confrontare un sistema arduino con un pic : sono due cose forse troppo diverse e tutto dipende dal risultato finale che si vuole ottenere, e nel risultato finale vanno inclusi anche prezzi e disponibilità a buon mercato. Sulla piattaforma arduino nulla da discutere, ma un pic programmato bene è capace davvero di fare mille cose ad un prezzo decisamente inferiore. A me piacciono i pic perchè con pochi euro riesco a fare dei bei automatismi e ho tutto a portata di mano senza spendere cifre esagerate, e posso realizzare mille dispositivi averli in casa funzionanti, perciò mi sono mosso verso i picmicro. Se ad esempio acquisto arduino e poi voglio farmi un timer, un orologio, un robottino, una centralina di allarme, un termostato ecc… quanto mi viene a costare? A parte che sarebbero applicazioni sprecate per un sistema come arduino: perciò non si puo confrontare l’uno con l’altro e tutto sta a ciò che si vuole fare e ottenere. Per me è tutto buono e non disprezzo niente e ogni cosa ha la sua funzione.

  36. #37 da linchip il 22 febbraio 2010

    Concordo pienamente con quello che dici ed è appunto per fare cose semplici ma nello stesso tempo “complete” che mi stò dedicando alla programmazione dei PIC. In un certo senso la mia “fortuna” è sicuramente dettata dal fatto di utilizzare una seriale “vecchio stampo”. Cmq ritornando al mio quesito ho risolto cercando su forum stranieri. Forse non mi sarò spiegato bene, ma quello che intendevo non si riferiva alla programmazione. Io volevo evitare di collegare la linea MCLR alla tensione positiva durante il normale funzionamento del microcontrollore e in aggiunta a questo ho scoperto che è anche possibile utilizzare MCLR come pin di I/O aggiuntivo. Ho letto meglio il settaggio dei Fuses e quindi c’è l’istruzione per abilitare/disabilitare MCLR con #pragma config MCLRE=OFF. In questa maniera dopo la programmazione evito di portare il pin alto, visto che il jdm me lo porta basso a programmazione terminata. Grazie per l’attenzione e buon lavoro.

  37. #38 da Giovanni Bernardo il 22 febbraio 2010

    AAAAAAAAAAAAh! Ecco!! Da come stai scrivendo, mettendo in mezzo pure il programmatore, si capiva tutt’altro!
    Allora… Ci sono alcuni pic per i quali questo non è possibile e MCLR deve essere per forza collegato al positivo tramite pullup, altrimenti il pic non parte. Altri hanno la possibilità di non fare questo ma soltanto perchè MCLR può essere utilizzato come normale I/O (es.: il 16F628, per il quale si possono usare come I/O pure i due pin del quarzo). Ovviamente usandolo come I/O non lo si deve piu portare alto. I pic serie 18 come hai visto hanno le direttive pragma per settare i fuses e hai già trovato la soluzione. Sui pic16 (mi riferisco al 16F628, su alcuni potrebbe essere diverso) basta inserire la parola chiave MCLRDIS nella config word per disabilitare la funzione di Master Clear e quindi usare MCLR come un normale I/O.
    Utilizzando MCLR come I/O ovviamente si perde la funzione di reset esterno del picmicro (ma in genere è molto difficile che tale funzione serva a meno che non si stia facendo un sistema di sviluppo).

  38. #39 da linchip il 22 febbraio 2010

    Si, infatti. Ora la situazione si è fatta più chiara e poi tra l’altro ho trovato tutti i possibili settaggi dei fuses proprio nella documentazione del C18, senza andare direttamente nel sito della MICROCHIP. Benchè possa suscitare pareri discordi…ke dire il jdm funziona! Ho in “cantiere” anche un pic16f88 vedrò se funziona anche con quello…ma il C18 purtroppo lì mi abbandona. Ma hitec-c ha dei limiti particolari o è completo come il C18?

  39. #40 da Giovanni Bernardo il 22 febbraio 2010

    Se guardavi nella sezione “Risorse” (http://www.settorezero.com/wordpress/risorse/) avresti trovato il documento con l’elenco dei fuses di configurazione per tutti i pic18. L’ho messo qui perchè in effetti sul sito della Microchip è quasi impossibile riuscire a trovarlo. Penso tu stia usando la versione “student” del C18, non è completa, anche lei ha dei limiti ma adesso non so dirti quali perchè per ora non ci ho ancora messo mano. L’hitec-c (che ormai è pure questo della Microchip) in versione LITE ti limita a 2000H word di programma, ma ti assicuro che non sono poche, io ci riesco a fare tutto e comunque sta sempre alla bravura del programmatore riuscire a fare routine più snelle possibile.

  40. #41 da Luca il 1 marzo 2010

    Ciao, innanzitutto nuovamente complimenti per questo utile e splendido corso. Volevo solo avvisarti che è la seconda volta che provo a registrarmi, prima con “Mad Picker” poi con “Overvolting” come username, ma ancora non riesco a loggarmi, sempre il solito “ERRORE: nome utente non valido.” mi daresti una mano? Grazie mille
    L.

  41. #42 da Giovanni Bernardo il 2 marzo 2010

    Segui attentamente ciò che c’è scritto nel form di registrazione e sull’email e vedi che non avrai problemi. Se ti dico questo è perchè non hai letto ciò che c’è scritto, altrimenti non ti saresti registrato fornendo i dati così come hai fatto.

  42. #43 da Luca il 2 marzo 2010

    Giovanni Bernardo :
    Segui attentamente ciò che c’è scritto nel form di registrazione e sull’email e vedi che non avrai problemi. Se ti dico questo è perchè non hai letto ciò che c’è scritto, altrimenti non ti saresti registrato fornendo i dati così come hai fatto.

    L’ho fatto per tre volte, inserendo credenziali veritiere, accettando i disclaimer, ed aspettando quelle 24h, il tutto per tre volte. In cosa sto sbagliando?

    L.

  43. #44 da Giovanni Bernardo il 2 marzo 2010

    Nel fatto che continui a mettere il nome o il cognome solo con l’iniziale seguita dal punto?

  44. #45 da Luca il 4 marzo 2010

    Ciao,
    allora, grazie per la pazienza, ti devo le mie scuse per quanto riguarda la registrazione. Allora avrei un paio di domande; innanzitutto voglio informarti che programmo con un willem programmer 5.0 i pic16f628a (gli 877a non sembrano dare segni di vita e non so perchè, anche se la programmazione via ICSP sembra funzionare dato che la verifica và a buon fine, ma dopo aver caricato il tuo programma che ho scaricato da questo articolo e impostato il circuito come sopra non sembra funzionare…attento un’illuminazione divina che mi spieghi cosa gli accade!); volevo sapere, quali sono, o almeno dove posso trovare, le parole per configurare i fuses (quelli dopo il __config) per il 628a . Poi avrei un altro problema, sto sviluppando su una breadboard, bella grande, e non capisco perchè spesso e volentieri, sia usando il quarzo interno che quello esterno, nel programma di lampeggio, appena si accenda il led impazzisca e smetta di lampeggiare emettendo una luce molto piu fioca del normale funzionamento; tutto torna alla normalità una volta toccato con un DITO la massa, ma continui cosi per qualche minuto prima di spegnersi completamente…soprannaturale vero? ho disattivati tutti i fuses tranne quello del power uped ho anche aggiunto un condensatore in parallelo all’alimentazione da 100pF ma niente… Qualche idea?
    Grazie infinite della tua pazienza…
    Luca

  45. #46 da Giovanni Bernardo il 4 marzo 2010

    Se programma, e verifica, allora il problema sta nel circuito. Il quarzo funziona? E’ collegato bene? Hai messo la resistenza di pullup sul MCLR? Hai attivato mica l’interrupt su timer0 e lo fai andare in overflow senza resettarlo? I motivi possono essere mille, senza ovviamente escludere il programmatore. La causa principale di malfunzionamento è comunque la dimenticanza della resistenza di pullup su MCLR. Oppure stai usando la word di configurazione settando un tipo di oscillatore diverso da quello che hai realmente collegato.

    I Fuses di configurazione io generalmente li vedo nei files include dell’Hitec-C (C:\Programmi\HI-TECH Software\PICC\PRO\9.65\include) facendo un confronto con il datasheet del pic interessato.

    I nomi mnemonici del 16F628A sono contenuti nel file pic16f62xa.h , le parole chiave per la configurazione si trovano alla fine del file:

    Nota: CONTROLLA BENE IL DATASHEET ALLA VOCE
    “Special Features of The CPU / Configuration Word”

    PROTECT (protegge memoria programma)
    UNPROTECT (non protegge eeprom e memoria programma)
    CPD (protegge eeprom)
    LVPEN (programmazione low voltage abilitata)
    LVPDIS (programmazione low voltage disabilitata)
    BOREN (BrownOut reset abilitato)
    BORDIS (BrownOut reset disabilitato)
    MCLREN (MCLR funziona come normale Master Clear Reset)
    MCLRDIS (MCLR funziona come I/O digitale)
    PWRTEN (PowerUp Timer abilitato)
    PWRTDIS (PowerUp Timer disabilitato)
    WDTEN (Watch Dog Timer abilitato)
    WDTDIS (Watch Dog Timer disabilitato)

    Configurazioni Oscillatore:
    RCCLK (Clock esterno da circuito RC, ingresso segnale su RA7 e uscita clock su RA6)
    RCIO (Clock esterno da circuito RC, ingresso segnale su RA7 e RA6 funziona come normale I/O)
    INTCLK (Clock interno a 4MHz, uscita clock su RA6 e RA7 funziona come normale I/O)
    INTIO (Clock interno a 4MHz, RA6 e RA7 funzionano come normale I/O)
    EC (Clock esterno da apposito circuito oscillatore da inviare a RA7, normale funzione I/O su RA6)
    HS (Quarzo ad alta velocità su RA6 e RA7)
    XT (Quarzo normale su RA6 e RA7)
    LS (Quarzo a bassa potenza su RA6 e RA7)

    per ulteriori informazioni vedi il datasheet.

    Nota importantissima, che in molti trascurano ed è poco documentata: Non possono coesistere il clock interno e mclr come normale I/O. Se abiliti le opzioni per fare questo, il pic si comporterà in maniera assurda.

    O usi MCLR come normale master reset e usi il clock interno O usi MCLR come I/O ma con il clock esterno, questo è specificato nella nota 4 a tergo della configuration word sul datasheet.

    Se usi MCLR come I/O, alcuni programmatori potrebbero trovare problemi nella programmazione e verifica, dal momento che la funzione del pin MCLR viene in qualche modo alterata non consentendo più il normale riconoscimento del pic. Il pickit ha una funzione apposita per ovviare a tale problema, come ho specificato nell’ultimo articolo (http://www.settorezero.com/wordpress/picmicro-che-non-vengono-piu-riconosciuti-dal-pickit-lerrore-no-device-detected/)

    Per quanto riguarda la questione della breadboard, sono sicuro si tratti della breadboard, perchè è capitato anche a me e ad altri. Purtroppo ora sul mercato si trova soltanto roba cinese e spesso capita che tali basette non siano di qualità, per cui i pin di contatto all’interno o non fanno contatto o creano strane capacità parassite che fanno impazzire il circuito. Prova a spostare il circuito in un’altra parte della breaboard, altrimenti fatti tu una schedina di sviluppo usando pure una millefori per stare tranquillo. Il condensatore in parallelo all’alimentazione, poi, andrebbe messo da 100nF (100pF sono pochetti) e il più vicino possibile ai pin dell’alimentazione del pic.

  46. #47 da Luca il 4 marzo 2010

    Allora, il quarzo funziona perchè è lo stesso che utilizzo sul 628a, 20Mhz @ HS, La rete di pullup è ok controllata anche con un tester (quasi5V normale, 0V a tasto premuto), lo stesso vale per il resto del circuito. Il prg ed i fuses sono gli stessi di sopra, caricando l’hex automaticamente il programma del programmatore li imposta automaticamente quindi scarterei l’interrupt.
    Ti ringrazio vivamente per i fuses del 628a, e sono contento (ma abbastanza vergognato) di sapere che è da 2 giorni che violo la nota importantissima :S ! Stasera che torno a casa verifico il tutto, il condensatore è da 100nF ho sbagliato a scrivere; ci avevo pensato anch’io stamane di spostare il circuito su una millefori, la breadbord mi ricorda molto quei condensatori in aria usati nelle vecchie radio,,,
    Ti farò sapere stasera l’esito dei test.
    Grazie mille e buona serata…

  47. #48 da Giovanni Bernardo il 4 marzo 2010

    Non puoi usare gli stessi fuses di configurazione del 628A con l’877A, alcune impostazioni sono differenti. La nota importantissima è una cosa che purtroppo sfugge di vista perchè nemmeno sul datasheet non è che sia tanto “pubblicizzata”

  48. #49 da fredigsm il 6 marzo 2010

    Giovanni complimenti che lavoro splendido sei grande e questo tuto gratis

    grazie mile

(non verrà pubblicata)
  1. Ancora nessun trackback

Fusion theme by digitalnature | Articoli (RSS) e Commenti (RSS) ^