Costruire un programma che visualizzi sulla Development Board EasyPic4 con micro PIC16F887 il numero 54 sui primi 2 display a 7 segmenti (DIS0 e DIS1).
Soluzione:
Nella Development Board EasyPic4 la porta A viene utilizzata per selezionare quale display
a 7 segmenti attivare. Ad esempio:
- se pongo a 1 il primo bit (RA0) della porta A (PORTA=0b00000001) verrà
utilizzato il primo display a destra,
- se pongo a 1 il secondo bit (RA1)
della porta A (PORTA=0b00000010)
verrà utilizzato il secondo display e cosi via ...
I segmenti del display
sono collegati alla porta D secondo lo schema sottostante.
Essendo tutti i 4 display collegati alla stessa porta D segue che appena imposto la seconda cifra (il 5 nel nostro problema) la precedente (il 4) viene sovrascritta e perduta. Come posso ovviare ? Potrei sfruttare i fenomeni di persistenza dell'immagine sulla retina e il transitorio di spegnimento dei led del display a 7 segmenti! Un programma che esegue un loop che non fa altro che accendere in sequenza ciascun display con una frequenza molto elevata potrebbe creare i presupposti necessari affinché all'occhio sembri che tutti i display siano sempre accesi (in realtà lo sono solo per un istante molto breve) uno alla volta. Un tempo di attesa adeguato tra l'attivazione di un display e il successivo (capace quindi di sfruttare i fenomeni di persistenza dell'immagine sulla retina e il transitorio di spegnimento dei led sui display) è un millisecondo.
Questa tecnica si chiama Multiplexing. Tale tecnica è concettualmente molto semplice e si basa sul fenomeno della persistenza della visione: si accende un unico display per volta, ad intervalli di tempo talmente brevi da non poter essere percepiti dall’occhio umano: accendiamo prima un display, lo lasciamo acceso per pochi millisecondi, lo spegniamo e accendiamo il successivo e così via.
Se carichiamo sul PIC questo programma vedremo infatti apparire il numero 54 senza alcun sfarfallio.
/* -------------------------------------------------------------- * Nome progetto: 7Seg2_Static (Mostra 54 sul display a 7Segmenti) * Configurazione: MCU: P16F887A Dev.Board: EasyPIC4 Oscillator: HS, 08.0000 MHz SW: mikroC v7.0 -------------------------------------------------------------- */ // array con la codifica per i DISPLAY a 7 segmenti // -------------------------------------------------------------- // // Valore in Segmenti deci- Valore in Segmenti deci- // display .GFEDCBA male display .GFEDCBA male // ---------------------------- ---------------------------- // 0 00111111 63 5 01101101 109 // 1 00000110 6 6 01111101 125 // 2 01011011 91 7 00000111 7 // 3 01001111 79 8 01111111 127 // 4 01100110 102 9 01101111 111 // // -------------------------------------------------------------- void main() { PORTA = 0; // disattivo tutti i display TRISA = 0; // tutti i bit della porta A sono di output PORTD = 0; // spengo tutti i segmenti del display TRISD = 0; // tutti i bit della porta D sono di output while (1) { PORTA = 0b00000001; // accendo il 1° display a destra PORTD = 0x66; // mando la mask per il 4 sulla PORTAD Delay_ms(1); // attesa di un millisecondo PORTA = 0b00000010; // accendo il 2° display a destra PORTD = 0x6D; // mando la mask per il 5 sulla PORTAD Delay_ms(1); // attesa di un millisecondo } } |
Questa soluzione non è proponibile quando il valore visualizzato è frutto di una lunga elaborazione. Infatti l'attesa tra l'ottenimento del risultato e la sua visualizzazione, in un loop infinito, potrebbe comportare un tempo superiore al transitorio di spegnimento dei led sul display a 7 segmenti con conseguente sfarfallio delle cifre.
La soluzione alternativa, che supera questo inconveniente, è quella che sfrutta gli interrupt.
GESTIONE INTERRUPT: Prima di vedere la soluzione con gli interrupt vediamo come questi vengono gestiti nel PIC16F887.
Il PIC16F887 ha 3 timer/contatori completamente indipendenti identificati con le sigle TMR0, TMR1 and TMR2. La figura sottostante illustra il ruolo dei bit di configurazione che controllano i timer. Questi bit sono contenuti nel registro OPTION_REG.
Il TMR0 è un semplice contatore ad 8 bit. Il suo conteggio viene incrementato automaticamente di 1 (essendo ad 8 bit va da 0 a 255) ad ogni ciclo di istruzioni. Il ciclo di istruzioni in un PICMicro è pari alla frequenza di clock divisa per 4: ciò equivale a dire che una singola istruzione assembler viene eseguita in 4 cicli di clock. Indicando con Fosc la frequenza di clock (la frequenza del quarzo o dell’oscillatore in genere), la frequenza di un ciclo di istruzioni è quindi pari a Fosc/4.
Quindi il TMR0 si incrementa di 1 ogni 4 colpi di clock, ovvero con una frequenza di Fosc/4. Se stiamo utilizzando un quarzo da 20Mhz, la frequenza di esecuzione delle istruzioni è pari a 20/4 = 5MHz. Poichè la frequenza è l’inverso del tempo (periodo) segue che ogni istruzione verrà eseguita nel tempo di 1/5 = 0,2 μS (microsecondi).
Quando il TMR0 va in overflow (cioè passa dal valore 255 al valore zero), è possibile fargli generare l'Interrupt su overflow del TMR0 (indicato con TMR0IF) che possiamo intercettare e sfruttare per attivare o disattivare determinate funzioni. Un interrupt è una sorta di “campanello” che ci permette di fermare momentaneamente l’esecuzione del programma principale per eseguire altre funzioni.
Utilizzando un quarzo da 20Mhz, abbiamo che il TMR0 va
in overflow dopo 256*0,2μS = 51,2μS (ho utilizzato il valore 256 e non 255
perché devo conteggiare anche lo zero). Tale tempo, per la stragrande
maggioranza delle applicazioni, è troppo basso. Generalmente abbiamo bisogno di
tempi più “palpabili” per poter lavorare in tranquillità, o per ottenere
temporizzazioni ben definite. Per tale
motivo i PICMicro hanno a bordo un’utile dispositivo chiamato Prescaler.
Il Prescaler altro non è che un divisore di frequenza: ci permette di dividere la frequenza (la velocità) del nostro ciclo di istruzioni (Fosc/4)
in valori più piccoli, facendoci ottenere tempi di esecuzione più alti e quindi
più facilmente gestibili o in ogni caso impostabili sui valori che desideriamo.
Ovviamente il prescaler non influisce sulla velocità di esecuzione delle istruzioni: le istruzioni continueranno ad essere
eseguite ad una velocità di Fosc/4. Esso influisce unicamente sull’incremento
del TMR0.
Il prescaler può essere assegnato o al Timer0 o
al Watchdog Timer.
Supponiamo di voler generare l'interrupt di overflow dopo un tempo ben preciso. Ad esempio un interrupt ogni millisecondo, ovvero ogni 1000μS. In questi casi si ricorre ad un trucchetto estremamente semplice: basta non far partire il TMR0 dal valore 0 ma da un altro valore che indicheremo con la sigla PreloadTMR0. Vediamo come calcolare il valore di partenza di TMR0 più adeguato ai nostri scopi:
La formula che fornisce il tempo trascorso in N° cicli istruzione è il seguente
dove:
Fosc = Frequenza del quarzo
PS=Valore del prescaler (uno dei valori: 2, 4, 8, 16, 32, 64, 128, 256)
(4*PS/FOSC) = tempo necessario affinché il TMR0 si incrementi di un'unità
Supponiamo che il timer si incrementi di una unità ogni 6,4 μS (4*PS/FOSC) ciò
significa che un tempo di 1000 μS lo raggiunge dopo:
1000/6,4 = 156,25 cicli
Teniamo però conto del valore intero: 156 (i cicli sono numeri naturali per cui
non possiamo usare il decimale!). Quindi se dopo 156 cicli
otteniamo un intervallo di un millisecondo ci basta far partire il TMR0
da 100 = 256-156 per ottenere un interrupt dopo 1 mS. Una volta generato l’interrupt reimposteremo
di nuovo il TMR0 a 100 e così ad ogni interrupt. Chiaramente,
avendo tralasciato dei decimali, il tempo non sarà esattamente di 1000 μS.
Il tempo reale è desumibile dalla formula:
dove PreloadTMR0 è il valore iniziale da dare al TMR0 (valore intero: privo dei decimali!). Il preloadTMR0, dopo alcune semplificazioni, può essere così determinato:
dove:
Td = tempo desiderato
SISTEMA INTERRUPT DEL PIC 16F887
Analizziamo ora i registri associati alla gestione degli interrupt. Speciali bit abilitano o disabilitano un determinato interrupt. Tali bit sono riconoscibili poichè il loro nome termina per IE (Interrupt enable). Per ogni bit abbiamo anche un bit che indica se quel particolare interrupt si è verificato o meno. Il loro nome termina con la sigla IF (interrupt flag).
Tutto si basa su un semplice ed efficiente
principio: quando una richiesta di interrupt arriva il bit IF viene posto a 1.
Se il bit IE associato è a zero l'interrupt verrà completamente ignorato
altrimenti no. Se ci sono più interrupt abilitati è necessario che la routine di
interrupt determini quale siano da considerarsi attivi analizzando i bit flag
IF. I bit flag
non vengono automaticamente azzerati ma dovranno essere resettati mediante la
routine di interrupt. Se non resettiamo un interrupt questo si ripeterà
immediatamente quando ritorniamo al main anche se non ci sono ulteriori
richieste in sospeso.
Tutti i riferimenti relativi agli interrupt tipici del PIC16F887 sono qui sotto
mostrati.
Per abilitare un interrupt quando la port B cambia di stato è necessario
abilitare il singolo bit separatamente mediante il registro IOCB che funge da
IE
bit.
Vediamo ora in dettaglio i registri coinvolti:
RBPU - abilita le resistenze di Pull-up per la
porta B
Abilita (0) oppure disabilita (1) le resistenze di pull-up sulla
porta B. Le resistenze di pull-up servono a fare in modo che un pin configurato
come ingresso non rimanga “appeso” ovvero non rimanga senza segnali applicati ad
esso (condizione che può portare a malfunzionamenti). Generalmente sui pin
configurati come ingresso andremo sempre ad inserire una resistenza di pull-up
che mantiene il pin a valore logico alto (up) {vedi note in fondo}. Le porte B
dei PIC hanno questa caratteristica: possiamo quindi evitare di mettere tali
resistenze all’esterno del PIC.
INTEDG - è il bit che definisce il fronte di riferimento (di salita/di
discesa) per l'interrupt sul pin RB0/INT.
E' possibile attivare un interrupt esterno sul pin 0 della porta B RB0/INT (bit INTE
sul registro INTCON). Se questo bit è posto a 1 l’interrupt sul pin 0
della porta B avviene sul fronte di salita del segnale altrimenti su quello di
discesa. Quindi se poniamo questo flag:
- sul valore 1: avremo che l’interrupt sarà generato sul fronte di salita del
segnale applicato ad RB0/INT,
- sul valore a zero: l’interrupt scatterà sul fronte di discesa del segnale.
Tale impostazione non c’entra assolutamente nulla col Timer0, ma fa comunque
parte del registro delle opzioni.
T0CS - è il bit che definisce il clock di riferimento per il TMR0
Possiamo fare in modo che l’incremento del TMR0 sia legato ad una
sorgente di clock esterna (questo può essere utile quando dobbiamo ad esempio
sviluppare un’applicazione di precisione e ottenere quindi un tempo estremamente
preciso). Se
vogliamo che il TMR0 si incrementi tramite una sorgente esterna di clock,
dobbiamo impostare il bit T0CS ad 1 (in questo caso il clock andrà
applicato al pin contrassegnato sul PICMicro con la sigla T0CKI), se
invece vogliamo che il TMR0 si incrementi tramite la circuiteria interna
del PIC (e quindi tramite il quarzo), allora imposteremo tale bit a zero.
- se vale 0 l'impulso nel PIC16F887 arriva tramite il pin RA4 (T0CKI).
- se vale 1 il TMR0 utilizza il ciclo di clock interno (Fosc/4).
T0SE - è il bit che definisce il fronte di
riferimento (di salita/di discesa) per il TMR0.
Il bit T0SE stabilisce come deve avvenire l’incremento del Timer0 ma vale solo
nel caso si sfrutti una sorgente esterna.
- se vale 0 l’incremento si avrà nel momento in cui il segnale effettua il
passaggio da stato logico basso a stato logico alto.
- se vale 1 l’incremento si avrà nel momento in cui il segnale effettua il
passaggio da stato logico alto a stato logico basso.
PSA - Bit di assegnamento del Prescaler
- con 1 il prescaler è assegnato al WDT.
- con 0 il prescaler viene assegnato al TMR0.
PS2, PS1, PS0 - bit divisore di frequenza
I bit PS0 PS1 e PS2 servono per impostare il valore di divisione della
frequenza (il valore del prescaler) come mostrato nella tabella sottostante.
Impostando ad esempio questi 3 bit sul valore 101 otterremo un valore di
divisione della frequenza del ciclo istruzioni pari a 64. In questa tabella vi sono due colonne: quella
sinistra è relativa al valore di divisione che si ottiene quando assegniamo il
prescaler al
TMR0 mentre quella destra rappresenta il valore di divisione che si
ottiene se invece il prescaler è assegnato al Watchdog timer.
PS2 | PS1 | PS0 | TMR0 | WDT |
---|---|---|---|---|
0 |
0 |
0 |
1:2 |
1:1 |
0 |
0 |
1 |
1:4 |
1:2 |
0 |
1 |
0 |
1:8 |
1:4 |
0 |
1 |
1 |
1:16 |
1:8 |
1 |
0 |
0 |
1:32 |
1:16 |
1 |
0 |
1 |
1:64 |
1:32 |
1 |
1 |
0 |
1:128 |
1:64 |
1 |
1 |
1 |
1:256 |
1:128 |
I valori su cui possiamo impostare il prescaler (ovvero il divisore) sono : 2, 4, 8, 16, 32, 64, 128, 256. Come si vede il valore 1 non è presente: in questo caso basta semplicemente non assegnare il prescaler al TMR0.
Il registro INTCON contiene i bit di
abilitazione e segnalazione dei vari interrupt gestiti dal PIC.
Gli interrupt sui PIC16 hanno una sorta di interruttore generale: il bit GIE (Global Interrupt Enable) che consente di mascherare tutte le sorgenti di interrupt, ovvero di non far richiamare l’ISR (Interrupt Service Routine) anche se i bit di abilitazione sono settati. Vi è inoltre un bit di abilitazione per gli interrupt di periferica: PIE (Peripheral Interrupt Enable) che serve per mascherare tutti gli interrupt i cui flag di abilitazione si trovano nei registri PIE.
GIE – Global Interrupt Enable bit:
Questo bit abilita (valore 1) tutti gli interrupt abilitati nei bit PEIE, T0IE,
INTE e RBIE (bit 3 ... 6). Con 0 disabilita tutti gli interrupt
PEIE – Peripheral Interrupt Enable bit:
Funziona come GIE ma controlla solo gli interrupt originati dalle
periferiche (che vanno attivate tramite il registro PIE1). Questo
significa che:
- non ha alcuna influenza su TMR0
- neppure sul cambiamento di
stato della PORTB
- neanche su RB0/INT1.
Con 1 abilita tutti gli
interrupt abilitati in PIE1 e PIE2 ad esclusione dei 3 citati. Vediamo di riassumere la
struttura del registro correlato PIE1:
![]() |
|
ADIE | Abilito (1)/ disabilito (0) l'interrupt del modulo ADC |
RCIE | Abilito (1)/ disabilito (0) l'interrupt di ricezione del modulo EUSART (Enhanced Universal Synchronous Asynchronous Receiver Transmitter - E' nota anche come Serial Communications Interface ). |
TXIE | Abilito (1)/ disabilito (0) l'interrupt di trasmissione del modulo EUSART |
SSPIE | Abilito (1)/ disabilito (0) l'interrupt emesso quando viene completato un trasferimento dati, effettuato in modo sincrono, tramite il modulo di comunicazione seriale MSSP. MSSP (Master Synchronous Serial Port) è il modulo periferico dedicato alle comunicazioni seriali di tipo sincrono, ovvero costituite da una linea dati e da una linea di clock. |
CCP1IE | Abilito (1)/ disabilito (0) l'interrupt generato dal modulo CCP1 utilizzato nel segnale PWM. Il modulo CCP di un picmicro è in grado di generare un treno continuo di impulsi a modulazione di ampiezza del quale, in ogni momento, possiamo cambiare il duty cicle. Dal modulo CCP potra' essere prelevato il segnale pwm. (vedere questo link) |
TMR2IE | Abilito (1)/ disabilito (0) l'interrupt emesso quando i registri PR2 e TMR2 hanno lo stesso valore (vedere questo link) |
TMR1IE | Abilito (1)/ disabilito (0) l'interrupt di overflow di TMR1 |
T0IE – TMR0 Overflow Interrupt
Enable bit
Abilita l’interrupt sull’overflow di TMR0. Con 1 abilita l’interrupt su TMR0
mentre con 0 lo disabilita.
INTE – RB0/INT External Interrupt
Enable bit
Attiva l’interrupt sul cambiamento di stato del pin RB0/INT (interrupt esterno).
Con 1 abilita l’interrupt esterno su RB0/INT altrimenti lo disabilita
RBIE – RB Port Change Interrupt
Enable bit.
Attiva l’interrupt sul cambiamento di stato della portB, sia da alto a
basso che viceversa. Con 1 abilita.
T0IF – TMR0 Overflow Interrupt Flag
bit
Registro l’overflow su TMRO. Se contiene il valore 1 il registro TMR0 è andato in overflow
(il bit deve essere azzerato via software) altrimenti no.
INTF – RB0/INT External Interrupt
Flag bit
Segnala il cambiamento di stato sul pin RB0/INT pin.Se vale 1 l’interrupt
esterno su RB0/INT è avvenuto (il bit deve essere azzerato via software) altrimenti
no
RBIF – RB Port Change Interrupt
Flag bit
Registra il cambiamento di stato della portB. Se vale 1 almeno uno dei pin della
portB ha cambiato stato (il bit deve essere azzerato via software).
Ritorniamo al nostro problema: scrivere 54 sugli ultimi due display a 7
segmenti. Utilizzando l'interrupt di overflow sul TMR0
possiamo richiamare ad istanti regolari la funzione che effettua il refresh
delle cifre sui 2 display. Analizziamo quindi la soluzione con gli
interrupt:
/* -------------------------------------------------------------- * Nome progetto: 7Seg2_Static (Mostra 54 sul display a 7Segmenti) * Configurazione: MCU: P16F887A Dev.Board: EasyPIC4 Oscillator: HS, 08.0000 MHz SW: mikroC v7.0 -------------------------------------------------------------- */ // array con la codifica per i DISPLAY a 7 segmenti // -------------------------------------------------------------- // // Valore in Segmenti deci- Valore in Segmenti deci- // display .GFEDCBA male display .GFEDCBA male // ---------------------------- ---------------------------- // 0 00111111 63 5 01101101 109 // 1 00000110 6 6 01111101 125 // 2 01011011 91 7 00000111 7 // 3 01001111 79 8 01111111 127 // 4 01100110 102 9 01101111 111 // // -------------------------------------------------------------- unsigned short displayattivo; void interrupt() { if (displayattivo==1) { PORTD = 0x66; // imposto la codifica del 4 sulla PORTB PORTA = 0b00000001; // accendo il 1° display e spengo il 2° displayattivo = 2; // imposto il prossimo display da usare } else { PORTD = 0x6D; // imposto la codifica del 5 sulla PORTB PORTA = 0b00000010; // accendo il 2° display e spengo il 1° displayattivo = 1; // imposto il prossimo display da usare } TMR0 = 0; // resetto il timer TMR0 // CONFIGURAZIONE REGISTRO INTCON (Interrupt Config) // bit 7 -> GIE, Gestione Interrupt (1 -> attiva) // bit 6 -> PEIE, Gestione Interrupt di periferica (0 -> disattivato) // bit 5 -> TMR0IE, Gestione Interrupt di overflow sul Timer0 (1 -> attivo) // bit 4 -> INTE, Gestione Interrupt su porta RB0/INT (0 -> disattivato) // bit 3 -> RBIE, Gestione Interrupt su porte B (0 -> disattivato) // bit 2 -> T0IF - Flag interrupt su Timer0 (0 -> reset) // bit 1 -> INTF - Flag interrupt su RB0/INT (0 -> reset) // bit 0 -> RBIF - Flag interrupt su porte B (0 -> reset) INTCON = 0b00100000; // 0x20; - azzero T0IF e setto TMR0IE } void main() { // Impostazione del registro OPTION (pag.55 del datasheet) // bit 7 -> Gestione Resistenze di pull-up su porta B (1 -> disattivate) // bit 6 -> Non importa // bit 5 -> Clock per Timer0 derivato da ciclo di clock interno // bit 4 -> Non importa // bit 3 -> Prescaler assegnato al Timer0 // bit 2 -> Prescaler Rate Select bit 0 (1:32) // bit 1 -> Prescaler Rate Select bit 0 // bit 0 -> Prescaler Rate Select bit 0 OPTION_REG = 0b10000000; // 0x80 - disabilito le resistenze di pull-up sulla porta B PORTA = 0; // disattivo tutti i display TRISA = 0; // tutti i bit della porta A sono di output PORTD = 0; // spengo tutti i segmenti del display TRISD = 0; // tutti i bit della porta D sono di output TMR0 = 0; // azzero il timer TMRO // CONFIGURAZIONE REGISTRO INTCON (Interrupt Config) // bit 7 -> GIE, Gestione Interrupt (1 -> attiva) // bit 6 -> PEIE, Gestione Interrupt di periferica (0 -> disattivato) // bit 5 -> TMR0IE, Gestione Interrupt di overflow sul Timer0 (1 -> attivo) // bit 4 -> INTE, Gestione Interrupt su porta RB0/INT (0 -> disattivato) // bit 3 -> RBIE, Gestione Interrupt su porte B (0 -> disattivato) // bit 2 -> T0IF - Flag interrupt su Timer0 (0 -> reset) // bit 1 -> INTF - Flag interrupt su RB0/INT (0 -> reset) // bit 0 -> RBIF - Flag interrupt su porte B (0 -> reset) INTCON=0b10100000; // 0xA0 displayattivo = 1; // resto in attesa dell'interrupt } |
Nota per me: verificare che funzioni se al posto di OPTION_REG=0x80 metto 0x00 e TRISB=0 (output) - non ho capito perchè devo disabilitare le resistenze di pull-up
Poichè la frequenza di esecuzione che è stata
impostata per l'esecuzione del programma qui sopra è di 8Mhz segue che la
frequenza di esecuzione delle istruzioni assembler (e quindi di incremento del
TMR0) è Fosc/4=8Mhz/4 = 2Mhz. Essendo la frequenza l'inverso della durata
basta calcolare 1/2Mhz = 0,5 μS per ottenere il tempo di esecuzione di un'istruzione
assembler. Il TMR0 va
in overflow ogni 256 cicli di istruzione per cui si verifica un interrupt ogni
256*0,5μS = 128μS. Il prescaler è 1:2 per cui il tempo si raddoppia:
256μS. La funzione Interrupt() oltre a gestire il refresh dei display dovrà:
- azzerare il valore del TMR0
- azzerare il flag che registra l'avvenuto overflow (TMR0IF o T0IF)
- riattivare l'interrupt di overflow ponendo a 1 il bit TMR0IE (o T0IE).
All'avvio il programma dovrà agire sul registro INTCON per avviare
il timer0 ed esattamente:
- attivare tutti gli interrupt ponendo a 1 il bit GIE
- attivare l'interrupt di overflow su TMR0 ponendo a 1 il bit TMR0IE (o
T0IE).
Resistenze di pull up
Gli ingressi del PIC sono ad alta impedenza
ovvero richiedono (assorbono) una corrente minima per cambiarne lo stato.
Questo presenta un inconveniente: essendo così sensibili gli ingressi lasciati
liberi (non collegati) presentano valori casuali causati dai rumori di fondo e
non un valore LOW come potremmo erroneamente pensare. Per questa ragione
dobbiamo far si che il nostro pin sia sempre connesso o a 5V o a 0V. Nello
schema sottostante con il pulsante premuto avremo un valore HIGH sul pin di
ingresso, mentre con circuito aperto avremo valori in ingresso oscillanti.
Per questa ragione dobbiamo far si che il nostro pin sia sempre connesso o a 5V
o a 0V. Potremmo ovviare il problema connettendo il circuito aperto a terra. Ma
in questo caso il problema nasce quando chiudiamo il circuito che causa un bel
cortocircuito con conseguente danneggiamento del nostro PIC.
Per fare questo possiamo utilizzare il
successivo schema. Abbiamo introdotto una resistenza da 10K chiamata
resistenza di pull up.
Fintatochè il pulsante non è premuto il pin rimane stato HIGH; la corrente che
fluisce è bassa per via della resistenza, ma data l'alta impedenza degli
ingressi è sufficiente a mantenere alto lo stato. Quando premiamo il pulsante la
corrente fluisce verso massa e la tensione prossima a 0V porta il pin in stato
LOW. In questo caso non abbiamo corto circuito poichè la resistenza limita la
corrente ( I = V/R=5V/10.000ohm= 5mA). L'obiettivo raggiunto dalla resistenza di
pull up è quello di togliere le fluttuazioni al pin di input; Il compito della
resistenza di pull up è anche quello ridurre la corrente che attraversa il
circuito. Utilizzando una resistenza di pull up avremmo uno stato HIGH con il
circuito aperto (pulsante non premuto) e LOW con circuito chiuso (pulsante
premuto). Questo può inizialmente creare un po' di confusione, ma è solo una
convenzione.
In maniera analoga alle resistenze di pull up possiamo utilizzare resistenze di pull down. In questo caso il circuito aperto porterà il pin in stato LOW e il circuito chiuso in stato HIGH
http://www.vincenzov.net/tutorial/elettronica-di-base/PIC16F690/interrupt.htm
http://mbortolotti.blogspot.it/2012/01/resistenze-di-pull-up.html