Indirizzi e-mail a cui far pervenire osservazioni, critiche e

Transcript

Indirizzi e-mail a cui far pervenire osservazioni, critiche e
Indirizzi e-mail a cui far pervenire osservazioni, critiche e suggerimenti atti a migliorare la guida.
[email protected]
[email protected]
GUIDA ALL’USO E ALLA PROGRAMMAZIONE DI UN MICROCONTROLLORE “PIC”
- INTRODUZIONE
Un microcontrollore PIC e` un gioiello della tecnologia attuale, questo a differenza dei tipici
microprocessori e` qualcosa di piu` elaborato, infatti è capace di interagire con il mondo
esterno attraverso numerose periferiche che si trovano gia` al suo interno. In realta` un
microcontrollore lo possiamo considerare come un computer completo, racchiuso in un
unico circuito integrato.
La sigla PIC sta per : “Programmable Interface Controller”, ed è una varieta` specifica di
microcontrollori creata dalla “Microchip”. Naturalmente come tutti i microcontrollori, hanno
anche una vasta gamma di linguaggi di programmazione, pertanto ho scelto per questa
guida il linguaggio C; utilizzando nello specifico il compilatore “Mikro C” distribuito da
“Mikroelektronika”; invece per quanto riguarda il microcontrollore ho scelto il “PIC16F84A”.
1. REALIZZAZIONE DI UN PROGRAMMATORE JDM PER PIC
Nel primo punto della nostra guida proponiamo l’autocostruzione di un programmatore per
Pic. Nel nostro caso per iniziare abbiamo scelto un programmatore semplice da costruire,
soprattutto molto più economico dei vari programmatori di Pic esistenti sul mercato.
Inoltre c’è da dire che questo programmatore proprio perché è economico non è molto
affidabile quindi consigliamo di realizzare questo circuito solo per muovere i primi passi nel
mondo dei microcontrollori Pic.
Lo schema e` il seguente :
SCHEMA ELETTRICO:
Come si nota il circuito e` molto semplice, in
quanto non esistono eccessivi componenti
elettronici.
L’intero circuito e` formato infatti da uno
zoccolo a 18 piedini che ospita un
microcontrollore della serie PIC 16XXX,
l’alimentazione e` fornita` dall’USB ed in parte
dalla porta seriale. La porta RB6 del Pic
(piedino 12) e` collegata direttamente al
terminale RTS della seriale (piedino 7) e
trasporta il segnale di clock.
La porta RB7 del Pic (piedino 13) e` collegata
ai terminali DTR e CST della seriale
(rispettivamente il piedino 4 e 8) e trasporta il
segnale dei dati.
Il piedino VSS del Pic (piedino 5) e` collegato
La porta MCLR del Pic (piedino 4 Reset) e` collegata al terminale TxD della seriale
(piedino 3), in piu` sul piedino 4 del Pic vi e` collegato un led che ci indica qualitativamente
se il programmatore e` in funzione. Infine il piedino VDD del pic (piedino 14) e` collegato
alla sorgente di alimentazione attraverso il piedino 1 della USB e tramite la resistenza per
assicurare un potenziale continuo al microcontrollore fornendo un minimo di protezione al
circuito, limitando la corrente.
Pagina 2 di 23
CIRCUITO STAMPATO
N.b = I due circuiti stampati sono in dimensioni reali
La sua realizzazione e` molto semplice e` richiede poco tempo (circa mezz’ora). Puo`
essere realizzato su millefori oppure su circuito stampato con l’uso dei trasferibili, visto che
non vi sono troppe piste e fori.
Una volta preparato lo stampato, si possono saldare i componenti, iniziando dalle
resistenze (perche` hanno un profilo piu` basso), di conseguenza lo zoccolo i led, ed infine
i due connettori per la seriale e per la USB.
2. SOFTWARE PER LA PROGRAMMAZIONE DEL PIC
Esistono vari programmi in rete, compatibili con questo programmatore, ma ritengo che il
piu` completo, freeware e soprattutto in lingua italiana sia Ic-Prog, scaricabile dal sito
http://www.ic-prog.com/; compatibile con la maggior parte dei microcontrollori della
Microchip esistenti sul mercato.
Per iniziare ad usare il software, si consiglia di scaricare la versione 1.05 C dal seguente
link: http://www.ic-prog.com/icprog105C.zip; e di scompattare tutti i file *.zip uno per uno in
una cartella, includendo anche i plug-ins IC-Prog NT/2000 driver e Helpfile in Italian
language scaricandoli dai seguenti link :
(http://www.ic-prog.com/icprog_driver.zip e http://www.ic-prog.com/guida.zip).
Avviare l’eseguibile “icprog.exe” (se usate Windows NT/2000/Xp/Vista/7 e compaiono
messaggi di errore, si prega di consultare la appendice 5 Risoluzione dei problemi/Errore
privileged instruction.
Pagina 3 di 23
In seguito cliccate nel menù Settaggi
/hardware e impostare nel menù a
tendina “programmatore”: “JDM
Programmer”, e spuntare anche
l’impostazione “API di Windows” nel
menù “Interfaccia”.
Per completezza selezionate nel menù
Settaggi/Chip/Microchip PIC/Altro
/PIC16F84A.
Infine per impostare il vostro Ic-Prog in
Italiano impostate “italian” nel menù a
tendina “language” in Settings/Options/
language
Dopo aver settato completamente il software vi troverete davanti un interfaccia grafica di
questo tipo:
Pagina 4 di 23
Dove alcuni pulsanti della barra degli stumenti del programma sono spiegati di seguito:
Serve per selezionare i file da scrivere, all’interno della E2prom (Rom) del Pic.
Come vedremo in seguito, dovremo selezionare in questo menu solo file con
l’estensione “*.hex” cioe` il vero e proprio file in linguaggio macchina che verrà
caricato nella E2prom del Pic.
Serve per leggere il contenuto della E2prom del Pic, inoltre ci potrebbe servire per
verificare il contenuto della E2prom del Pic per dei controlli.
Questo pulsante serve per programmare, fisicamente (scrivere) l’E2prom del nostro
Pic, sempre dopo aver caricato i file dal menu, apri.
Pagina 5 di 23
3. IL COMPILATORE
Anche dal punto di vista dei compilatori, in rete ne esistono di tante tipologie, ma per
questa guida ho scelto un compilatore C distribuito dalla Mikroelektronika cioe` “MicroC”,
scaricabile dal sito http://www.mikroe.com./ .
Per iniziare ad usare il software scaricare questo, dal sito prima indicato, in seguito
munirsi di una licenza valida distribuita dallo stesso sito ed avviare l’installazione.
Dopo aver installato il programma, esso si presenterà` cosi`:
Per iniziare a editare un programma cliccare dal Menù Project/New Project… .
Pagina 6 di 23
In questa finestra vi inseriamo il nome del programma che vogliamo creare (in “Project
Name”), la destinazione dei file che andra` a creare (in “Project Path”; inoltre apriamo
una nuova cartella altrimenti i file potrebbero disperdersi), in seguito vi inseriamo un
commento (facoltativo) in “Description”. Infine specifichiamo il pic (P16F84A) con
l’opportuna frequenza di clock (in “Device) espressa in MHz.
In piu` in “Device Flag” selezioniamo il tipo di oscillatore che stiamo usando (esempio
XT_OSC per un quarzo oppure RC_OSC per un Oscillatore Resistenza_Condensatore).
Dopo aver impostato i valori, in New Project, possiamo scrivere il programma in linguaggio
C++ (consultare l’appendice 6 “Cenni sulla programmazione in c++”), in seguito per
compilare il programma cliccate su Project/Build.
Se tutto è andato a buon fine (quindi non ci sono errori di sintassi all’interno del
programma) nella tabella inferiore vi segnalerà il buon esito, e nella nostra cartella (creata
precedentemente) troveremo salvato il listato in c++ e il programma vero è proprio (con
estensione *.hex) compilato in linguaggio macchina, da programmare nella E2prom del
nostro pic.
Pagina 7 di 23
4.PROGRAMMAZIONE FISICA DEL PIC
Adesso con il programma Ic-Prog Apriamo il file “*.hex” nella cartella che abbiamo creato.
Inseriamo il programmatore nella porta seriale del nostro Pc, e con il Pic gia` montato sullo
zoccolo, premiamo il pulsante “programma tutto”.
. L’interfaccia Grafica si presenterà
cosi:
Il Pic è pronto all’uso, me se dovrebbe verificarsi un errore del tipo “Verifica fallita al code
address 0000h !” consultare la sezione “risoluzione dei problemi/Fallita Programmazione
al Code address 0000h”
5.RISOLUZIONE DEI PROBLEMI
Errore : Privileged instuctuion
Se avviate per la prima volta Ic-Prog su windows NT/2000/Xp/Vista/7, e vi compare questo
messaggio di errore, premete OK per saltarlo, poi nel menu Settings/Options/Misc
spuntare l’opzione “Enable NT/2000/XP driver”. In seguito vi compariranno i seguenti
messaggi di conferma :
confermate tutto premendo YES, Ic-prog si riavvierà da solo, altrimenti riavviatelo
manualmente.
Pagina 8 di 23
Fallita Programmazione al Code address 0000h
Questo messaggio di errore compare frequentemente, quando si programmano i
microcontrollori (PIC). Le cause di questo errore possono dipendere da molti fattori:
•
•
•
•
•
•
•
•
Verificare Il cavo usato per collegare il programmatore al PC: Usare solo
prolunghe a 9 poli Pin-to-Pin, disponibili nei negozi di elettronica;
Verificare se i settaggi sono giusti: IcProg va settato a seconda del programmatore
usato (JDM Programmer). Inoltre, bisognerà indicare la porta in uso (Com1 o
Com2).
Verificare se la seriale del Pc fornisce abbastanza tensione al nostro
programmatore: in questo caso bisognerà modificare il programmatore (saldando
due fili in uscita della porta USB montata sul circuito stampato) in modo da poterlo
alimentarre rigorosamente a 5V.
Verificare se è stato installato il driver per Windows NT/2000/XP: Lo trovate in
allegato, va inserito nella stessa cartella di IcProg e andrà attivato da Settaggi ->
Opzioni -> Misc -> "Abilita il driver NT/2000/XP".
Verificare se è abilitato il Code protect : se il CP è abilitato IcProg non riesce a
verificare il contenuto della memoria programma del PIC, quindi "crede" che la
programmazione non sia andata a buon fine; Controllare quindi, attraverso la
casella di controllo, che il code protect sia disabilitato.
Verificare se il programmatore è alimentato: (LED Power on acceso);
Verificare se il microcontrollore (PIC) è funzionante :o se è stato montato
correttamente sul programmatore.
Per evitare qualsiasi errore: verificate la funzionalità del programmatore nel menù
Settaggi \ Controllo Hardware; verificare se il segnale arriva al dispositivo,
spuntando “Attiva Data Out”, e osservare se “Data In” si spunta autonomamente.
Inoltre spuntando “Attiva MCLR” sul nostro programmatore JDM vediamo
accendersi il led rosso.
Pagina 9 di 23
6.CENNI SULLA PROGRAMMAZIONE IN C ++
-VARIABILI
Tipo
Descrizione
Size*
char
Character or small integer.
1byte
short int
(short)
Short Integer.
2bytes
int
Integer.
4bytes
long int
(long)
Long integer.
4bytes
float
double
long
double
Boolean value. It can take one of two
values: true or false.
Floating point number.
Double precision floating point number.
Long double precision floating point
number.
wchar_t
Wide character.
bool
Range*
signed: -128 to 127
unsigned: 0 to 255
signed: -32768 to 32767
unsigned: 0 to 65535
signed: -2147483648 to
2147483647
unsigned: 0 to 4294967295
signed: -2147483648 to
2147483647
unsigned: 0 to 4294967295
1byte
true or false
4bytes
8bytes
+/- 3.4e +/- 38 (~7 digits)
+/- 1.7e +/- 308 (~15 digits)
8bytes
+/- 1.7e +/- 308 (~15 digits)
2 or 4
bytes
1 wide character
* I valori delle colonne Size e Range dipendono dal sistema dove viene compilato il programma. I valori riportati sono
quelli che si trovano sulla maggior parte dei sistemi a 32-bit.
-DICHIARAZIONE DI VARIABILE
Tale dichiarazione può comprendere anche la sua inizializzazione
tipo identificatore = espressione;
ES : int voto = 3 + 5;
-OPERATORI ARITMETICI
+ (SOMMA)
- (SOTTRAZIONE)
* (MOLTIPLICAZIONE)
/ (DIVISIONE)
% (RESTO DI UNA DIVISIONE)
- OPERATORI DI CONFRONTO O RELAZIONALI
< (MINORE )
<= (MINORE UGUALE)
> (MAGGIORE )
>= (MAGGIORE O UGUALE )
= = (UGUALE)
! = (DIVERSO)
Dove “=” è un operatore di ASSEGNAZIONE DA NON CONFONDERE CON ==
Pagina 10 di 23
<< 1 (shift a sinistra di una posizione)
>>1 (shift a destra di una posizione)
- ESPRESSIONE
L’espressione è composta da operatori e operandi con la priorità alle parentesi, dalle più
interne alle più esterne, e con associatività a sinistra.
- PRECEDENZA
Essa e` definita da una ben precisa tabella, che stabilisce il livello 1 a piu` bassa priorita` e
il livello 17 a piu` alta priorita`.
Nel caso invece di operatori appartenenti allo stesso livello di priorità, la precedenza e`
stabilita` dalla associatività, che e` definita da sinistra.
ES.
Prima la sottrazione che è più a
3-4+2 =
sinistra poi la somma
-1+2 = 1
Come nelle normali espressioni matematiche qualora si voglia cambiare l’ordine di
precedenza degli operatori si ricorre alle parentesi, prima le piu` interne e poi, mano
mano, le più esterne (annidate).
ES.
a +b*c
qui viene eseguita prima la moltiplicazione e poi la somma perche` la “*” e la
“+” si trovano su livelli di priorita` diversi.
Mentre
((a+b)*c)
qui viene eseguita prima la somma e poi la moltiplicazione ( grazie alle
parentesi).
- OPERATORI BOOLEANI
! A (NOT A)
A & B (A AND B)
A | B (A OR B)
A^B (A XOR B)
Bit a Bit cioè sui Bit corrispondenti
Bit a Bit
Bit a Bit
Bit a Bit
A<<1 (scorrimento a sinistra di una posizione)
A>>1 (scorrimento a destra di una posizione)
STRUTTURE DI CONTROLLO O COSTRUTTI
LA SEQUENZA : essa e` una struttura in cui le istruzioni che la compongono vengono
eseguite una dopo l’altra nell’ordine indicato.
Tale sequenza e` vista dal compilatore come un unico blocco logico
racchiuso tra parentesi graffe {}.
ES.
Pagina 11 di 23
{ Istruzione 1
Istruzione 2}
LA SELEZIONE: tale struttura in base alla verita` o meno di un' espressione logica,
esegue la sequenza 1 o la sequenza 2. (esistono anche degli IF
nidificati).
ES.1
V
if ( espressione
logica)
{SEQ. 1}
else
{SEQ. 2}
F
ES. 2
if (I < 100)
if (I > 0)
0< I < 100;
ITERAZIONI
Ciclo con controllo in testa “while ”
F
V
Le istruzioni interne al blocco sequenza verranno
ripetute se “espressione” e` vera ( ≠ 0 ); viceversa
quando l’espressione e` falsa ( = 0 ) il controllo
passerà` alla prima istruzione successiva alla
struttura “while”.
Se l’espressione e` falsa, fin dalla prima volta la
sequenza non viene eseguita nemmeno una volta.
Se l’espressione dovesse essere sempre vera si
entra in un ciclo infinito o loop infinito (vedi EX1).
Si sceglie questa struttura quando non si conosce a
priori il numero delle iterazioni.
Definire la variabile di controllo del ciclo prima di
entrare nel ciclo stesso, altrimenti tale struttura
“while” va in errore
while (espressione)
{sequenza}
Pagina 12 di 23
Ciclo con controllo in coda “do …. while “
Il ciclo termina quando espressione risulta falsa.
La sequenza viene sicuramente eseguita almeno
una volta, in quanto “Espressione” viene eseguita al
termine del ciclo e non all’inizio, come avveniva per
la struttura “while”.
In genere questa struttura viene usata per ripetere di
nuovo un programma gia` andato in esecuzione
almeno una volta.
Anche in questo caso la variabile di controllo del ciclo
deve essere definita prima di entrare nel ciclo stesso
do
{sequenza
}
while (espressione);
Il “Ciclo di for”
Sequenza di eventi del ciclo for:
1) Viene inizialmente valutata “espressione 1”
(espressione di inizializzazione che puo`
contenere anche la dichiarazione della variabile di
controllo del ciclo .
ES: int i = 0;
2) Viene poi valutata “espressione 2” (espressione di
controllo ) se e` diversa da 0, verrà eseguita la
sequenza, mentre se e` falsa cioe` uguale a 0, si
esce dalla struttura for .
3) Alla fine della esecuzione di ogni ciclo prima di
calcolare
espressione
2,
viene
eseguita
espressione 3 (espressione di incremento o
decremento).
for (espressione1;espressione2;espressione3)
{sequenza
}
All’interno delle parentesi tonde del “ciclo for” possono mancare tutte o solo alcune
espressioni ma devono necessariamente essere presenti tutti i punti e virgola.
ES: for (int i = 1; i<=N ; i ++)
{sequenza
}
Tale struttura si usa quando si conosce a priori il numero delle iterazioni.
Pagina 13 di 23
ARRAY – VETTORI E MATRICI
I vettori rappresentano il modo piu` semplice per aggregare i dati tra di loro, ricordiamo,
dati dello stesso tipo. Tale vettore rappresenta una variabile indicizzata dalle seguenti
proprietà:
1. Tutti gli elementi che compongono un vettore devono essere dello stesso tipo (tipo
del vettore);
2. la struttura e` individuata da un unico nome (nome del vettore);
3. il numero degli elementi che compongono la struttura di un vettore e` definito al
momento della dichiarazione del vettore e deve essere rigorosamente intera e
maggiore di zero;
4. l’accesso ad un singolo elemento del vettore si ottiene tramite un indice posizionale
che viene posto tra parentesi quadra, in fase di uso del vettore (vedi ES2 riga 3) ;
5. Tutti gli elementi vengono memorizzati in locazioni contigue e la posizione del primo
elemento corrisponde sempre all’indice 0;
Definizione o dichiarazione del vettore :
tipo_elementare nome_vettore [numero elementi]
ES1.
char led [14] = {0x81,0x42,….};
char n;
for (n=0;n =4;n ++)……
e` una espressione in esadecimale;
N.B. 0x32
0b00110010 e` una espressione in binario.
N.B. Una volta definito il vettore con il tipo, il nome e il numero di elementi costituenti il
vettore, si può anche dare un valore ai singoli elementi del vettore scrivendo tutti
questi valori tra parentesi graffe.
ES2.
Char leds [2] = {0x81,0x42};
for (char n=0 ; n<2 ; n++)
portb = leds [2];
Note : Il PIC possiede due porte di I/O. La prima e` la Port A a 4 bit di I/O e la seconda e`
la B a 8 bit di I/O.
-In fase di programmazione bisogna definire se le porte di cui si vuole fare uso, debbano
essere porte di ingresso o porte di uscita. In termini sintattici la scelta si fa in questo modo:
TRISB=0
TRISB=1
Definisce gli 8 bit della Port B come Output
Definisce gli 8 bit della Port B come Input
Pagina 14 di 23
TECNICHE DI PROGRAMMAZIONE
PROBLEMA 1: Complementare uno o piu` bit di un Byte rimanendo gli altri bit inalterati.
0
BIT
MASCHERA
0
0
1
1
1
0
1
1
1
0
A
Basandoci sulla seguente tabella di verità della X-OR, e
sulle definizione degli operatori logici del C++ ( X-or
^) si
puo` affermare che le X-or di un generico bit con con 1
logico comporta la complementazione del bit stesso,
dunque per risolvere il nostro problema si fa la X-or (^) fra il
byte sul quale operare, con una parola maschera costituita
da tutti 0, tranne che per i bit che si vuole complementare
che vanno posti a 1 nella parola maschera.
A^
0
ES. Sia dato il seguente byte 1A70A61A50A4 1A30A21A10A0 e si voglia complementare il bit
A5 rimanendo gli altri inalterati, occorre fare la seguente operazione.
1
0
1
0
1
0
1
0
0
0
1
0
0
0
0
0
1
0
0
0
1
0
1
0
^
PORTB ^
Es di codifica:
portb=portb^0x20
=
PAROLA
MASCHERA 0x20
N.B.: Osservare in seguito EX1 ed EX2
PROBLEMA 2: Si voglia testare il valore di uno o più bit di un byte, e porre i rimanenti bit
che non interessano a 0.
0
BIT
MASCHERA
0
0
1
0
1
0
0
1
1
1
A
&
0
Basandoci sulle tabelle di verita` della porta AND e
sulla definizione di operatore logico del C++ (AND
&) si fa la AND con la parola maschera costituita da
tanti 1 quanti e quali sono i bit da rilevare o testare, e
tutti gli altri bit che non interessano vanno posti a 0
nella parola maschera.
ES1. Dato il seguente byte 0A71A60A51A4 1A30A21A10A0 e si voglia conoscere se il bit A1 sia
1 o 0, in tal caso si fa la And con la parola maschera:
0000 0010
Parola maschera
Infatti
0
1
0
1
1
0
1
0
0
0
0
0
0
0
1
0 PAROLA
MASCHERA
0
0
0
0
0
0
1
0 ≠0
&
Pagina 15 di 23
Si fa notare che se il bit A1 fosse stato 0 si sarebbe avuto il seguente risultato :
0
1
0
1
1
0
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
0
Questo ci consente di utilizzare questa tecnica per scrivere
le espressioni nelle strutture tipo if e while ecc. (vedi EX
successivi). Giacché il risultato del test è =0 oppure ≠0 a
seconda che il bit in esame sia 0 oppure 1
=0
ES.: portb = portb & 0x01
ES2: Rilevare se uno o più bit (dei primi 4) del seguente byte 01011000 sono 1 o tutti
uguali a zero;
0
1
0
1
1
0
0
0
&
0
0
0
0
1
1
1
1
=
0
0
0
0
1
0
0
0
0
1
0
1
0
0
0
0
0
0
0
0
1
1
1
1
=
0
0
0
0
0
0
0
0
=0
portb = portb & 0x0E;
PAROLA
MASCHERA
≠0
&
PROBLEMA 3: posizionare a 1 il bit di un byte, rimanendo gli altri bit invariati.
Basandoci sulla tabella di verita` delle porte OR (|) del C++ si eseguono le OR con la
parola maschera costituita da tutti 0 tranne il bit che si vuole posizionare a 1 .
ES.: dato il byte 0A71A60A51A4 0A31A20A11A0 si voglia posizionare a 1 il bit A7 e rimanere gli
altri inalterati, tale che:
0
1
0
1
0
1
0
1
+
1
0
0
0
0
0
0
0
=
1
1
0
1
0
1
0
1
portb = portb + 0x80;
PAROLA
MASCHERA
Questa tecnica e` spesso utilizzata quando si vuole accendere il punto decimale in un
display a 7 segmenti collegato al bit a7 di un PIC.
Pagina 16 di 23
ESEMPI DI PROGRAMMI
EX1: Lampeggio di un LED utilizzando la porta RB del PIC (definita come uscita) ed in
particolare il bit RB0.
void main () {
portb = 0;
//Pongo l’uscita di PORTB a 0000 0000
trisb = 0;
//Definisco PORTB come uscita
// loop infinito
while (1) {
portb = portb ^ 0b00000001 ; //Complemento il bit B0
delay_ms (500); //Pausa o memorizzazione per 500 ms
}
}
EX2: Lampeggio di due LED in modo alternato uno su RB e l’altro su RB1.
void main () {
portb = 0b00000010;
trisb = 0;
while (1) {
portb = portb ^ 0b00000011;
//complementa entrambi I bit
delay_ms (500);
}
}
EX3: Provocare la seguente situazione di scorrimento dei LED :
void main () {
char n=0;
char leds [14] = {0x01, 0x02,
0x04, 0x08, 0x10, 0x20,
0x40, 0x80, 0x40, 0x20,
0x10, 0x08, 0x04, 0x02};
// Inizializzazione porta B
trisb = 0;
// loop infinito
while (1) {
Portb=leds [n];
n++;
if (n==14) n=0;
delay_ms (100);
}
}
N°
1
2
3
4
5
6
7
8
9
10
11
12
13
14
BINARIO HEX
00000001 01
00000010 02
00000100 04
00001000 08
00010000 10
00100000 20
01000000 40
10000000 80
01000000 40
00100000 20
00010000 10
00001000 08
00000100 04
00000010 02
Pagina 17 di 23
EX3.1: Con lo stesso programma realizziamo la seguente sequenza: (effetto super car)
void main () {
char n=0;
char leds [14] = {0x81, 0x42,
0x24, 0x18, 0x18, 0x24,
0x42, 0x81, 0x42, 0x24,
0x18, 0x18, 0x24, 0x42};
// Inizializzazione porta B
trisb = 0;
// loop infinito
while (1) {
Portb=leds [n];
n++;
if (n==14) n=0;
delay_ms (100);
}
N°
1
2
3
4
5
6
7
8
9
10
11
12
13
14
BINARIO HEX
10000001 81
01000010 42
00100100 24
00011000 18
00011000 18
00100100 24
01000010 42
10000001 81
01000010 42
00100100 24
00011000 18
00011000 18
00100100 24
01000010 42
Pagina 18 di 23
EX4: Pilotaggio di un display a 7 segmenti a catodo comune (CK) con cifre che vanno da
0 a 9.
void main () {
char n=0;
char segs [16] = {0x3f, 0x06,
0x5b, 0x4f, 0x66, 0x6d,
0x7d, 0x07, 0x7f, 0x6f,
0x77, 0x7c, 0x39, 0x5e,
0x79, 0x71};
// Inizializzazione porta B
trisb = 0;
// loop infinito
while (1) {
Portb=segs [n];
n++;
if (n==10) n=0;
delay_ms (1000);
}
}
EX4.1: visualizzare il numero 1234 su 4 display con l’uso della multiplazione.
5
5
5
2
0
5
ms
ms
Pagina 19 di 23
void main () {
char n,ds;
char segs [16] = {0x3f, 0x06,
0x5b, 0x4f, 0x66, 0x6d,
0x7d, 0x07, 0x7f, 0x6f,
0x77, 0x7c, 0x39, 0x5e,
0x79, 0x71};
char cifra [4] = {1,2,3,4} ;
// Inizializzazione porte
trisa = 0;
trisb = 0;
// loop infinito
while (1) {
ds=1;
for (n=0;n<4;n++) {
portb=segs [cifra [n]];
porta=ds;
delay_ms (20);
ds = ds << 1 ;
}
}
}
MULTIPLEXING – Occorre accendere i
vari display in successione ad una
velocità tale, da non far percepire
all’occhio lo sfarfallio. Per ottenere
questo effetto è sufficiente accendere
ogni cifra ALMENO ogni 20ms. Dal
momento che le cifre sono 4, dovremo
tenere accese singolarmente meno di
5ms. ( vedi diagramma temporale )
• Sulla Porta B dovranno essere inviate
ciclicamente i valori corrispondenti alle
quattro cifre da visualizzare cioè 1234.
• Sulla Porta A dovrà essere portato alto
una sola linea alla volta, cioè quella
corrispondente alla cifra da visualizzare, ciclicamente :
(0b 0000 0001,
0b 0000 0010,
0b 0000 0100,
0b 0000 1000)
P.S.: LA VARIABILE ds che è inizializzata a 1 (0000 0001) serve per lo shift, cioè per
realizzare il multiplexing. SEGS [16] per convertire la cifra da decimale a 7 segmenti.
Pagina 20 di 23
EX5: Utilizzare la porta Rb1 per accendere un led posto sulla porta Rb0 e utilizzare la
porta Rb2 per spegnere il led.
Le resistenze di pull-down (RA-RB)
da 1KΩ posta tra i pulsanti e massa
servono per fissare a livello basso
(0V) i rispettivi piedini di I/O quando
i pulsanti non sono premuti (in caso
contrario , cioè senza le R da 1 KΩ,
le tensioni sui pin Rb1 e Rb2,
potrebbero essere influenzate da
interferenze esterne).
PULSANTE PREMUTO
PULSANTE RILASCIATO
IN = 5 V Ξ 1
IN = 0 V Ξ 0
void main () {
// inizializzazione porta b
trisb = 0x06;
portb = 0;
//loop infinito
while (1) {
if (portb&0X02) portb=1; // se il pulsante su Rb1 è premuto accendi il led
if (portb&0X04) portb=0; // se il pulsante su Rb2 è premuto spegni il led
}
}
NOTA SULL’INIZIALIZZAZIONE DELLA PORTA B
Per leggere lo stato dei due pulsanti i piedini corrispondenti alla porta B sono stati
configurati come ingressi scrivendo il valore nel registro TRIS B 0x06 che in binario è
“0000 0110” in cui gli 1 rappresentano i pin configurati come ingressi cioè RB1 e RB2, e i
bit che valgono 0 cioè RB0 vale come uscita.
NOTA SOFTWARE: Il ciclo infinito mantiene il led sempre acceso o spento a seconda
dello stato dei pulsanti; questo artificio software corrisponde alla funzione di memoria.
Pagina 21 di 23
EX5.1: Fare in modo che alla pressione di uno dei due pulsanti il LED venga acceso ed
alla successiva pressione venga spento.
void main () {
// inizializzazione porta b
trisb = 0x06; // configura rb1 e rb2 come ingressi e rb0 come uscita
portb = 0;
//inizializzazione con azzeramento della porta b
//loop infinito
while (1) {
if (portb&06) portb=portb^01; //inverti il bit su rb0 solo se trova rb1 o rb2 premuti
altrimenti ripete.
//Attesa rilascio
while (portb&0x06) {};
delay_ms (50);
Quando la condizione () è falsa quindi i due pulsanti
sono rilasciati, il programma ritorna automaticamente al
}
“1° While” per l’accensione o lo spegnimento.
}
Meccanismo antirimbalzo.
N.B.:Il motivo della scelta della parola maschera “06dec” è quella che: premendo il pulsante
su RB1, o premendo il pulsante su RB2, la AND con 06 da come risultato un valore ≠0
cioè VERO (Vedi tabella) . In tutti gli altri casi il risultato è = 0 quindi FALSO.
Caso con i pulsanti premuti:
0 0 0
0
&
0
0
0
0
0
1
0
0
0
0
0
0
1
1
0 PAROLA
MASCHERA
0
0
0
0
0
0
0
1
0
0 ≠0
0
0
0
0
0
1
0
0
0
0
1
1
0 PAROLA
MASCHERA
0
0
0
0
1
0 ≠0
&
Caso con i pulsanti non premuti:
0
0
0
0
0
0
0
0
0
0
0
0
0
1
1
0
0
0
0
0
0
0
0
1
0
1
1
0
0
0
0 PAROLA
MASCHERA
0
0
0
0
0
1
1
0 PAROLA
MASCHERA
0 =0
0
0
0
0
0
0
0
0 =0
&
&
Pagina 22 di 23
EX6: Caso di antirimbalzo e contatore guidato da due pulsanti Up e Down con l’uso di un
display a 7 segmenti, ad ogni pressione del tasto S1 e S2.
void main () {
signed char count = 0;
char segs [16] = {0x3f, 0x06,
0x5b, 0x4f, 0x66, 0x6d,
0x7d, 0x07, 0x7f, 0x6f,
0x77, 0x7c, 0x39, 0x5e,
0x79, 0x71};
// controllo pulsanti
if (porta&0x02) count++;
if (porta&0x01) count--;
// correzione contatore
// Inizializzazione porte
trisa = 0x03;
trisb = 0x00;
porta= 0x08; //RA0 e RA1 rilasciati
// loop infinito
while (1) {
portb= segs [count];
if (count > 9 ) count = 0;
if (count < 0 ) count = 9;
//attendere rilascio
while (porta==0x03) {};
}
}
Pagina 23 di 23