|
|
|
![]() |
Lezione 2
Led & pulsanti
|
|
|
|
|
Moltissimi di voi, con la lezione 1, siete riusciti ad accendere i led con un PIC. Cosa che non siete mai riusciti a fare, neanche leggendo libri sulla programmazione del PIC. Ciò è segno che il metodo e la forma con cui ho esposto la lezione 1 funziona benissimo e lo dimostrano le numerosissime mail di ringraziamenti.
A gran voce avete chiesto un seguito alla cosa. Così ho deciso di sviluppare le mie demoboard modulari per evitare di dover rifare tutte le basette sperimentali da capo e risparmiando parecchi soldini. Oltre a ciò, alla fine, ci ritroveremo con dei moduli sempre riutilizzabili ed un sistema di sviluppo non da poco.
Mi auguro che voi impariate sempre di più da queste pagine e solo le vostre mail me lo potranno confermare.
|
Si parte con la seconda lezione
Dopo aver sviluppato il programma SEMAFORO, non sarà male riprendere da lì per proseguire in questa lezione.In pratica propongo di cominciare a far funzionare i Led, poi aggiungere i pulsanti, sviluppando il programma per gradi, in modo che tutto possa essere chiaro.Questa volta posso spiattellarvi subito la base del programma, se avete seguito la lezione del Semaforo, dovreste già comprenderla.
/****************************\
* led in sequenza *
\****************************/
#include<pic.h>
main(void)
{
PROGRAMMA DA SCRIVERE
}
Questa è la base del programma da cui cominciare a sviluppare il tutto. Dobbiamo ora vedere un attimo cosa abbiamo intenzione di fare e, di conseguenza operare le opportune aggiunte.
Il nostro obiettivo iniziale è far accendere in sequenza gli 8 led, quindi avremo bisogno di settare le porte B del PIC come uscite con il comando TRISB, usare il comando PORTB per accendere i led ed introdurre delle pause tra l'accenzione di un led e l'altro.
Ciò implica che dovremo aggiungere la direttiva che richiama la routine di ritardo delay.c presente nella cartella bin del PICLITE.
Aggiungiamo quanto appena detto e arriviamo a questo:
/****************************\
* led in sequenza *
\****************************/
#include<pic.h> // compila per il PIC generico
#include"delay.c" // richiama la routine di ritardo per poter usare le pause
main(void) //l'inizio del programma
{ // graffa di apertura del programma
TRISB = 0; // setta le porte B del PIC come uscite
} // fine del programma
Fatto questo, dovremo rispolverare la tabella dello stato logico delle porte che avevo esposto nella lezione del semaforo. Ve la ripropongo, così non andate troppo in giro per il sito (che ormai è abbastanza trafficato).
Da questa tabella, potremo ricavare il numero binario da passare a PORTB in modo da poter accendere il relativo led a nostro piacimento. Per esempio PORTB = 0b00000010; accende il secondo led della fila da 8 (RB1).Decido ora che i led dovranno accendersi in sequenza da RB0 a RB7 (ricordate che le porte si leggono come i numeri, da destra verso sinistra).
Otteniamo così il seguente listato:
/****************************\
* led in sequenza *
\****************************/
#include<pic.h> // compila per il PIC generico
#include"delay.c" // richiama la routine di ritardo per poter usare le pause
main(void) //l'inizio del programma
{ // graffa di apertura del programma
TRISB = 0; // setta le porte B del PIC come uscite
PORTB = 0b00000001; //accende il led collegato a RB0
PORTB = 0b00000010; //accende il led collegato a RB1 e spegne RB0
PORTB = 0b00000100; //accende il led collegato a RB2 e spegne RB1
PORTB = 0b00001000; //accende il led collegato a RB3 e spegne RB2
PORTB = 0b00010000; //accende il led collegato a RB4 e spegne RB3
PORTB = 0b00100000; //accende il led collegato a RB5 e spegne RB4
PORTB = 0b01000000; //accende il led collegato a RB6 e spegne RB5
PORTB = 0b10000000; //accende il led collegato a RB7 e spegne RB6
} // fine del programma
Notate sempre i punti e virgola alla fine di ogni istruzione, è facile dimenticarli e dovete prestare attenzione.
Abbiamo steso il listato che serve ad accendere tutte e 8 i led in sequenza ma, non basta per avere una sequenza decente.
In realtà il PIC eseguirebbe il programma troppo velocemente e i nostri occhi non sono abbastanza veloci da vedere la sequenza. (se volete provare a compilare e vedere il risultato fate pure).
Dobbiamo inserire una pausa tra l'accensione di un led e l'altro, in modo che la sequenza sia più o meno veloce e regolabile a nostro piacimento con il minor sforzo possibile nel programmare.
Per fare questo, dobbiamo inserire una pausa con una variabile definita tra un comando di accensione a l'altro.
Per prima cosa aggiungiamo la definizione della variabile e gli assegnamo un valore, poi aggiungeremo il comando Delay nel listato.
/****************************\
* led in sequenza *
\****************************/
#include<pic.h> // compila per il PIC generico
#include"delay.c" // richiama la routine di ritardo per poter usare le pause
#define asp 20 //definisce che asp è uguale a 20
main(void) //l'inizio del programma
{ // graffa di apertura del programma
TRISB = 0; // setta le porte B del PIC come uscite
PORTB = 0b00000001; //accende il led collegato a RB0
DelayMs(asp); // ritardo di valore asp (ora è definito a 20)
PORTB = 0b00000010; //accende il led collegato a RB1 e spegne RB0
DelayMs(asp);
PORTB = 0b00000100; //accende il led collegato a RB2 e spegne RB1
DelayMs(asp);
PORTB = 0b00001000; //accende il led collegato a RB3 e spegne RB2
DelayMs(asp);
PORTB = 0b00010000; //accende il led collegato a RB4 e spegne RB3
DelayMs(asp);
PORTB = 0b00100000; //accende il led collegato a RB5 e spegne RB4
DelayMs(asp);
PORTB = 0b01000000; //accende il led collegato a RB6 e spegne RB5
DelayMs(asp);
PORTB = 0b10000000; //accende il led collegato a RB7 e spegne RB6
DelayMs(asp);
} // fine del programma
Eccoci arrivati al programma completo, però non è finito.
Il PIC eseguirebbe una volta soltanto il programma e ci farebbe vedere la sequenza una volta soltanto.(in questo caso specifico il pic a fine programma ricomincerebbe da capo all'infinito e quello che sto per dire dopo è per introdurre il cliclo while).
Se vogliamo che il PIC ripeta all'infinito il programma, dobbiamo inserire il blocco di istruzioni in un ciclo while e, per fare questo, dobbiamo aggiungere anche le relative parentesi graffe.
Qui sotto riporto il listato completo che serve ad avere una sequenza infinita di accensione dei led, tenete conto che le istruzioni possono essere scritte anche sulla stessa riga, purchè ci sia sempre il punto e virgola.
/****************************\
* led in sequenza *
\****************************/
#include<pic.h> // compila per il PIC generico
#include"delay.c" // richiama la routine di ritardo per poter usare le pause
#define asp 20 //definisce che asp è uguale a 20
main(void) //l'inizio del programma
{ // graffa di apertura del programma
TRISB = 0; // setta le porte B del PIC come uscite
while(1) // istruzione per il ciclo senza fine
{ // parentesi di inizio ciclo
PORTB = 0b00000001; DelayMs(asp); //accende il led collegato a RB0
PORTB = 0b00000010; DelayMs(asp); //accende il led collegato a RB1 e spegne RB0
PORTB = 0b00000100; DelayMs(asp); //accende il led collegato a RB2 e spegne RB1
PORTB = 0b00001000 ;DelayMs(asp); //accende il led collegato a RB3 e spegne RB2
PORTB = 0b00010000; DelayMs(asp); //accende il led collegato a RB4 e spegne RB3
PORTB = 0b00100000; DelayMs(asp); //accende il led collegato a RB5 e spegne RB4
PORTB = 0b01000000; DelayMs(asp); //accende il led collegato a RB6 e spegne RB5
PORTB = 0b10000000; DelayMs(asp); //accende il led collegato a RB7 e spegne RB6
} //parentesi di fine ciclo
} // fine del programma
Ora possiamo andare a compilare e a programmare il nostro PIC.Dobbiamo, però, stare molto attenti al fatto che nel nostro caso tutte le porte RB del PIC sono collegate ai led e due di queste porte servono a programmare il PIC.
Quando programmiamo il PIC, dobbiamo staccare momentaneamente i led, altrimenti la programmazione fallirà a causa dell'interferenza dei led stessi.
Ricordatevi che sia il programmatore che la demoboard devono essere accesi, anche durante la programmazione, e che dopo la programmazione è opportuno staccare il cavo ICP dalla demo. (altrimenti, se spegnete il programmatore, la demoboard non potrà funzionare).
Ricordatevi anche che il tasto RESET della demoboard NON deve mai essere premuto durante la programmazione del PIC,pena la probabile rottura del transistor di MCRL del programmatore (solo durante la programmazione).
Se avete seguito attentamente questa lezione, e quella del semaforo, dovreste essere in grado di invertire l'ordine di accensione dei led e di inventare sequenze vostre, semplicemente cambiando la sequenza dei numeri passati a PORTB.
Potete anche cambiare la velocità della sequenza cambiando il numero passato a asp (tra 1 e 255).Fate le vostre prove, vi porterà pratica ed esperienza e poi andremo avanti.
Dopo aver fatto il programma per la sequenza dei led, possiamo affrontare la gestione dei pulsanti.
Se volete sentire subito il cicalino, basta staccare i led dalla demoboard e inserire il filo positivo del cicalino ad una delle porte B del pic appena programmato con il programma precedente e il filo negativo al negativo dell'alimentatore . Sentirete il cicalino emettere un suono intermittente.Avete appena scoperto come usare un cicalino attivo. Si usa come un led solo che ,invece di emettere luce, emette suono. Rimettiamo a posto il cicalino, rimontiamo il pettine dei led e andiamo avanti con la lezione.
Passiamo ad analizzare cosa vogliamo fare con i pulsanti ed i led.
Direi che sarebbe interessante fare 4 sequenze di accensione diverse per i led, assegnare le sequenze ai 4 pulsanti e, ad ogni pressione dei pulsanti, parta la sequenza corrispondente al tasto premuto.
Per prima cosa dovremmo settare le porte A del pic come entrate e, per fare questo, è sufficiente scrivere TRISA=1 nel programma.
Otterremo di poter stendere un inizio di programma che sarà così:
/****************************\
* led in sequenza *
\****************************/
#include<pic.h> // compila per il PIC generico
#include"delay.c" // richiama la routine di ritardo per poter usare le pause
#define asp 20 //definisce che asp è uguale a 20
main(void) //l'inizio del programma
{ // graffa di apertura del programma
TRISA = 15; // setta le prime 4 porte A del PIC come entrate
TRISB = 0; // setta le porte B del PIC come uscite
Settate le porte A del pic, dovremo trovare un comando che soddisfi le nostre esigenze per gestire i tasti.In pratica vorrei che il PIC aspettasse la pressione di uno dei tasti e poi eseguisse la sequenza associata, fino alla fine della sequenza e poi tornasse ad aspettare la pressione dei tasti.
In rete, trovo due possibilità operative per poter fare la stessa cosa, la prima è usare il costrutto IF- else, cioè porre delle condizioni e fare il salto al verificarsi della condizione. (salto condizionato).
La seconda soluzione è usare il costrutto switch che, a seconda dello stato logico letto sulla porta A del pic, esegue il relativo blocco di programma.
Esso và usato in questo modo: (Attentissimi alla punteggiatura usata, solo da li capite la struttura)
switch (PORTA) //decido quali porte leggere
{ //graffa di apertura di switch
case 1: //se si verifica lo stato 1 esegue il blocco successivo,
// altrimenti salta a case successivo
istruzione1;istruzione2; etc; //blocco che esegue se si avvera il case 1
break; //fine del case 1 e esce dal ciclo switch
case 2: //se si verifica lo stato 2 esegue
istruzione1;istruzione2; etc;
break;
}
Per spiegarla meglio, direi che questo pezzo di programma si comporta così:
Se le porte A del pic presentano il numero binario 0b0001 (decimale 1), viene eseguito il blocco di programma che fa capo a case 1, fino al comando break, e poi esce dal ciclo switch. Altrimenti salta al secondo case che, se legge il valore binario 0b0010 (decimale 2), egegue il suo blocco fino al suo break, e via così fino alla fine.
Il tutto dovrebbe essere inserito in un ciclo while, per fare in modo che il programma venga ripetuto all'infinito.Mettendo insieme il tutto, viene fuori questo:
/****************************\
* led in sequenza *
\****************************/
#include<pic.h> // compila per il PIC generico
#include"delay.c" // richiama la routine di ritardo per poter usare le pause
#define asp 120 //definisce che asp è uguale a 120
main(void) //l'inizio del programma
{ // graffa di apertura del programma
TRISA = 15 // setta le prime 4 porte A del PIC come entrate
TRISB = 0; // setta le porte B del PIC come uscite
while(1) //ripete il ciclo all'infinito
{ //graffa di apertura di while
switch (PORTA) //lettura PORTA
{ //graffa di apertura di switch
case 1: //se PORTA è 1 (0001) esegue la sequenza sotto, altrimenti salta
PORTB = 0b00000001; DelayMs(asp); //sequenza da 0 a 7
PORTB = 0b00000010; DelayMs(asp);
PORTB = 0b00000100; DelayMs(asp);
PORTB = 0b00001000; DelayMs(asp);
PORTB = 0b00010000; DelayMs(asp);
PORTB = 0b00100000; DelayMs(asp);
PORTB = 0b01000000; DelayMs(asp);
PORTB = 0b10000000; DelayMs(asp);
break; //interrompe il programma switch e torna a while
case 2: // se PORTA è 2 (0010) esegue, altrimenti salta
PORTB = 0b10000000; DelayMs(asp); //sequenza da 7 a 0
PORTB = 0b01000000; DelayMs(asp);
PORTB = 0b00100000; DelayMs(asp);
PORTB = 0b00010000; DelayMs(asp);
PORTB = 0b00001000; DelayMs(asp);
PORTB = 0b00000100; DelayMs(asp);
PORTB = 0b00000010; DelayMs(asp);
PORTB = 0b00000001; DelayMs(asp);
break;
case 4: //se PORTA è 4 (0100) esegue, altrimenti salta
PORTB = 0b10000001; DelayMs(asp); //sequenza incrociata
PORTB = 0b01000010; DelayMs(asp);
PORTB = 0b00100100; DelayMs(asp);
PORTB = 0b00011000; DelayMs(asp);
PORTB = 0b00100100; DelayMs(asp);
PORTB = 0b01000010; DelayMs(asp);
PORTB = 0b10000001; DelayMs(asp);
break;
case 8: //se PORTA è 8 (1000) esegue, altrimenti salta
PORTB = 0b10000000; DelayMs(asp); //sequenza a treno
PORTB = 0b01000000; DelayMs(asp);
PORTB = 0b10100000; DelayMs(asp);
PORTB = 0b01010000; DelayMs(asp);
PORTB = 0b10101000; DelayMs(asp);
PORTB = 0b01010100; DelayMs(asp);
PORTB = 0b00101010; DelayMs(asp);
PORTB = 0b00010101; DelayMs(asp);
PORTB = 0b00001010; DelayMs(asp);
PORTB = 0b00000101; DelayMs(asp);
PORTB = 0b00000010; DelayMs(asp);
PORTB = 0b00000001; DelayMs(asp);
break;
} //graffa di chiusura di switch
PORTB=0; //spegne tutti i led
} //graffa di chiusura di while
} //graffa di chiusura main (void)
In questo programma ho preferito introdurre il ciclo switch perché il ciclo for lo abbiamo già trattato nella lezione 1 (quella del semaforo).Se volessimo usare un joystick al posto dei pulsanti, basterà togliere dalla demo il modulo tasti e collegare il modulo joy
E potremo usare lo stesso programma.Quando programmate il PIC, esso deve avere gli stessi settaggi di configurazione usati nel semaforo.
Con questa lezione, e con la prima, dovreste aver imparato bene l'uso dei led con il PIC e la loro gestione.
Avrete notato che l'ultimo programma si è allungato un pochino ma in fondo non è tanto complicato, e già abbiamo fatto una cosa carina.
|