Questa pagina contiene materiale obsoleto
Scrivere il primo programma in C per il PIC16F690 non è difficile ma è necessario avere qualche nozione di base sul C e un'idea di quale è la struttura del microcontrollore. Inoltre è sempre da tenere a portata di mano un qualunque manuale C, l'HI-TECH C® for PIC10/12/16 User’s Guide e il PIC16F631/677/685/687/689/690 Data Sheet.
Sul sito è disponibile anche una pagina molto simile a questa pensata per il PIC18 con il compilatore MPLAB® C18 C
Il programma presentato accenderà sequenzialmente i quattro led presenti sulla scheda dimostrativa del PICkit 2 (effetto supercar: qualcuno si è lamentato della "banalità" dell'esempio proposto per l'integrato FT2232H).
Un progetto è costituito da vari file di configurazione e da una struttura piuttosto articolata. Il modo migliore per partire è utilizzare l'apposito maghetto presente nel menù Project → Project Wizard di MPLAB IDE.
Occorre selezionare il microcontrollore che si vuole utilizzare (PIC16F690 nell'esempio) per permettere la corretta configurazione dei vari strumenti.
Occorre poi scegliere il compilatore o l'assemblatore che si intende utilizzare (HI-TECH C se volete proseguire nella lettura di questa pagina, che deve essere già installato). I nomi delle directory e dei file sono precompilati. Occorre specificare solo il nome del progetto che si intende scrivere e la cartella che lo conterrà.
Il progetto appena creato appare vuoto.
La prima cosa da fare è scrivere il codice sorgente C, creando un nuovo file da aggiungere al progetto. Nel seguito vedremo come andrà compilato (Build) utilizzando l'apposita icona e trasferito sul componente fisico (Program), non prima di aver eliminato tutti i bug presenti. Una volta che il PIC è stato programmato, l'esecuzione del codice è indipendente dal PC e la schedina demo può anche essere staccata dal PICkit2 (previa alimentazione, ovviamente).
Nell'immagine qui sotto sono mostrate alcune delle tante finestre di MPLAD. In particolare si vede:
In genere i comandi sono attivabili o attraverso il menu oppure usando le apposite icone o ancora con i tasti funzione.
Il codice sorgente (File → New) appare come un normale programma C anche se appena le cose si fanno più complesse ci si accorge di alcune limitazioni dovute ad una architettura dove per esempio la memoria non si misura in MB ma in byte...
Più avanti è presente un file adatto al copia e incolla. Di seguito alcuni commenti in aggiunta a quelli già presenti direttamente nel codice.
#include <htc.h>
Questo file contiene la definizione delle costanti tipiche del microcontrollore utilizzato, quali i nomi e gli indirizzi dei registri, e le definizioni di alcune funzioni C standard o di supporto. Il tipo di microcontrollore è determinato da quanto impostato in uno dei passi precedenti e questo permette l'inclusione degli header file appropriati. Provando a leggere il file htc.h (ma non è necessario...) ci si accorge che a sua volta include molti altri file, alcuni specifici del microcontrollore, altri del compilatore.
#define _XTAL_FREQ 8000000 // Used from delay macro
Questa costante, obbligatoriamente con questo nome, serve per gli eventuali loop di ritardo usati dal programma.
__CONFIG(INTIO & // Use
internal clock
WDTDIS & //
Disable watchdog
PWRTEN & //
Delay after power on enabled
MCLRDIS & // Internal External Switch Over Mode Disable
UNPROTECT & // Disable memory
protection
BORDIS & //
Disable reset on low volage
IESODIS & //
Internal External Switch Over Mode Disable
FCMDIS); //
Disable Fail clock monitoring
Questa macro definisce una serie di parametri di funzionamento del processore. Non sono "istruzioni", nel senso che non sono convertite in istruzioni macchina, ma servono al programmatore per impostare una serie di bit (i cosiddetti "Configuration bits") prima dell'esecuzione del programma. Il significato, richiamato nel commento, è descritto nel manuale del PIC ma non è strettamente necessario comprenderne subito il funzionamento. In alternativa è possibile utilizzare la voce di menu Configure → New per impostare gli stessi parametri, come mostrato nell'immagine seguente: si noti il segno di spunta che specifica che tali parametri sono impostati all'interno del codice sorgente. La & presente indica che le varie opzioni sono in AND logico.
Il programma inizia obbligatoriamente con la funzione main():
void main(void)
{ OSCCON=0x70; // x111 0000 - 8 Mhz internal clock
Le prima istruzione imposta la velocità effettiva del clock interno (la descrizione è sul manuale del PIC). Si noti che l'opzione INTIO dei già citati bit di configurazione non imposta la frequenza del clock mentre la costante _XTAL_FREQ semplicemente è un numero usato da una funzione e non un'impostazione dell'hardware.
Spesso i numeri interi sono indicati nel codice in esadecimale (come in questo caso, quando preceduti da 0x) o in binario (quando preceduti da 0b). Invece di 0x70 si poteva scrivere, esattamente con lo stesso significato, 0b0111000 (un po' scomodo da leggere ma è questione di gusti personali) oppure 112 (sicuramente poco efficace quando si lavora con i bit).
Le tre istruzioni seguenti impostano la porta C del PIC come uscita, disattivando gli ingressi analogici affinché sia possibile accendere o spegnere i LED. Anche in questo caso la descrizione è sul manuale del PIC, cercando il significato dei tre registri i cui nomi sono scritti in maiuscolo. Si noti che sulla schedina PICkit2 sono presenti solamente 4 LED, quelli corrispondenti allo zero esadecimale di destra.
TRISC = 0x00; // Set PORTC as Output
ANSEL = 0; // Set as Digital I/O
ANSELH = 0; // Set as Digital I/O
Infine il loop infinito che accende i LED in sequenza. PORTC non è una normale variabile in memoria ma una delle interfacce fisiche del PIC verso il mondo reale: scrivere un 1 significa applicare una tensione alta ad un filo elettrico e quindi, in questo caso, accendere il LED ad esso collegato. Scrivere uno 0 significa ovviamente spegnere il LED.
for(;;)
{ PORTC = 0x01; // xxxx 0001 - Turn On Port RC0
__delay_ms(50); // Delay 50 ms
[...]
}
l'istruzione PORTC = 0x01; scrive contemporaneamente 8 bit (questa è la dimensione fisica dell'interfaccia). Il numero, che corrisponde al binario 0b00000001, provoca l'accensione di un solo LED, quello collegato al pin RC0 cioè il pin fisico numero 16 se usate il PIC16F690 in contenitore DIP20.
La funzione __delay_ms(50), dall'ovvio significato, è tipica del compilatore usato. Il massimo ritardo è pari a 98ms, se impostate un valore superiore il compilatore ritorna un codice di errore.
Per leggere lo stato di un segnale esterno al PIC occorre configurare un pin di una porta come ingresso. Sulla scheda del PICkit2 è presente un interruttore che, quando premuto, fornisce uno zero logico al pin RA3; quando rilasciato, fornisce un uno logico.
Per poterlo usare in un programma occorre configurare la porta PORTA come ingresso:
TRISA = 0xFF; // Set PORTA as input (RA3 is always input if MCLR disabled)
La lettura di tutti gli otto bit associati alla porta viene fatta semplicemente leggendo la variabile PORTA (in realtà solo i sei bit meno significativi sono fisicamente presenti). Se si vuole leggere il solo bit associato al bit 3 della porta, nel nostro caso quello a cui è collegato l'interruttore, è possibile far riferimento a RA3.
while (RA3); // Loop if pin 3 of PORTA is 1 (SW1 not pressed)
Il loop precedente in pratica blocca l'esecuzione del programma principale quando RA3 vale 1, altrimenti prosegue. Il codice lo trovate a fondo pagina, basta togliere i commenti alle due righe appena descritte.
Due informazioni utili per usare RA3 con il PICKit2, un po' nascoste nel manuale:
Per effettuare il debug del codice non ci sono risorse hardware disponibili con la versione base del PICkit2 ed occorre quindi selezionare il simulatore solo software dove sono peraltro disponibili strumenti potenti. le limitazioni sono l'assenza di supporto per l'interazione con l'hardware e l'uso del real-time.
Da tenere sempre sotto'occhio le finestre che mostrano le risorse disponibili sul micro: sono poche, ogni byte è importante!
Lo strumento base per il debug è l'uso dei Breakpoint, cioè di punti del programma in cui l'esecuzione si interrompe. Sono attivabili con un doppio click direttamente sulla riga del codice sorgente alla quale ci si vuole fermare. Il contenuto delle variabili e dei registi può essere osservata nella finestra di View → Watch. Inoltre possibile applicare agli ingressi segnali variabili nel tempo attraverso lo strumento Stimulus.
Nell'immagine è visibile la finestra che mostra il contenuto di due registri (PORTA e PORTC, in rosso quando cambiano) oltre all'impostazione di uno stimolo che simula la pressione dell'interruttore collegato a RA3.
La barra verde in basso indica che la simulazione è in corso. Essendo esclusivamente software è possibile effettuare il debug del programma anche in assenza di un PIC fisico e relativo hardware di programmazione.
La programmazione del PIC è fatta con l'apposita funzione del menù (Programmer → Program), ovviamente dopo aver selezionato come programmatore il PICkit 2. Per l'esecuzione fisica del programma occorre selezionare Programmer → Release_from_Reset. E' comodo impostare la programmazione e l'esecuzione automatica del programma dopo la compilazione.
Una volta che il programma è stato memorizzato sul PIC, la sua esecuzione è possibile anche staccando il PICkit2 e alimentando la scheda con una tensione continua di 3 oppure 5V.
PIC16F690 in C - OBSOLETO - Versione 1 - Ottobre 2014
Copyright 2009-2014, Vincenzo Villa (https://www.vincenzov.net)
Quest'opera stata rilasciata con licenza Creative Commons | Attribuzione-Condividi allo stesso modo 3.0 Unported.