Sei sulla pagina 1di 75

Albertini Diego Brizzolara Daniela Evangelista Mario Laveni Pierpaolo

Introduzione Alla Programmazione Dei

PIC16F876
Ringraziamento particolare a
Nicola Guercetti
che con i suoi consigli ha permesso
una più veloce stesura
di questo manuale

Ultima Modifica: 17-2-2002

Tutte le volte che nel Manuale si fa riferimento al datasheet del componente si intende il file DS30292x.PDF (dove x
definisce la versione, che in questo momento risulta essere la B) rintracciabile nel sito www.microchip.com.
Sommario

CAPITOLO 1 IL MANUALE E IL PIC........................................................................................................... 1


1.1. PREMESSA ................................................................................................................................................. 1
1.2. IL PIC16F876............................................................................................................................................ 1
CAPITOLO 2 LA PROGRAMMAZIONE....................................................................................................... 3
2.1. PREMESSA ................................................................................................................................................. 3
2.2. LE DIRETTIVE AL COMPILATORE ................................................................................................................. 3
2.3. LE ISTRUZIONI - P RINCIPI DI PROGRAMMAZIONE ......................................................................................... 7
2.4. GESTIONE DEL PROCESSO CON LOOP E SALTI ............................................................................................... 9
2.4.1. Call e Goto........................................................................................................................................... 9
2.4.2. Ritardo software................................................................................................................................. 10
2.5. DIRETTIVE SPECIALI: BANKSEL & CO. ...................................................................................................... 10
2.6. CONCLUSIONI .......................................................................................................................................... 12
CAPITOLO 3 FREQUENZA DELL’OSCILLATORE E DEL CLOCK DEL SISTEMA ........................... 13
3.1. PREMESSA ............................................................................................................................................... 13
3.2. SCELTA DELL’OSCILLATORE ..................................................................................................................... 13
CAPITOLO 4 INTERRUPT ........................................................................................................................... 15
4.1. PREMESSA ............................................................................................................................................... 15
4.2. PROGRAMMARE UNA ROUTINE DI INTERRUPT ............................................................................................ 15
4.3. REGISTRI DI INTERRUPT ........................................................................................................................... 21
CAPITOLO 5 TIMER E CONTATORI DI EVENTI .................................................................................... 23
5.1. PREMESSA ............................................................................................................................................... 23
5.2. IL TIMER 0............................................................................................................................................... 23
5.3. TIMER 1 .................................................................................................................................................. 25
5.4. TIMER2 ................................................................................................................................................... 25
CAPITOLO 6 LE PORTE DEL PIC .............................................................................................................. 27
6.1. PREMESSA ............................................................................................................................................... 27
6.2. PORTA A ................................................................................................................................................. 27
6.2.1. Stadio di uscita delle linee RA0, RA1, RA2 ,RA3 e RA5 ....................................................................... 27
6.2.2. Funzionamento in ingresso ................................................................................................................. 28
6.2.3. Funzionamento in uscita ..................................................................................................................... 29
6.2.4. Stadio d'uscita della linea RA4/T0CKI ................................................................................................ 29
6.3. PORTA B ................................................................................................................................................. 30
6.3.1. Stadio d'uscita delle linee RB0, RB1, RB2 ed RB3 ............................................................................... 31
6.3.2. Stadio d'uscita delle linee RB4, RB5, RB6 e RB7 ................................................................................. 31
6.4. PORTA C ................................................................................................................................................. 31
CAPITOLO 7 I MODULI CCP ...................................................................................................................... 33
7.1. PREMESSA ............................................................................................................................................... 33
7.2. FUNZIONE CAPTURE ................................................................................................................................ 34
7.3. FUNZIONE COMPARE................................................................................................................................ 35
7.4. FUNZIONE PWM...................................................................................................................................... 35
CAPITOLO 8 CONVERTITORE A/D........................................................................................................... 37

I
8.1. PREMESSA ............................................................................................................................................... 37
8.2. FUNZIONAMENTO DELLA PERIFERICA ADC ............................................................................................... 38
8.3. IL RISULTATO DELLA CONVERSIONE ......................................................................................................... 40
8.4. LA PROGRAMMAZIONE DELLA CONVERSIONE ............................................................................................ 40
CAPITOLO 9 LA MEMORIA EEPROM ...................................................................................................... 41
9.1. PREMESSA ............................................................................................................................................... 41
9.2. REGISTRI SPECIALI PER L'ACCESSO ALLA EEPROM DATI .......................................................................... 41
9.3. SCRITTURA DI UN DATO SU EEPROM....................................................................................................... 41
9.4. LETTURA DI UN DATO DA EEPROM ......................................................................................................... 42
CAPITOLO 10 COMUNICAZIONE SERIALE.............................................................................................. 43
10.1. PREMESSA ............................................................................................................................................... 43
10.2. COMUNICAZIONE USART........................................................................................................................ 43
10.2.1. Trasmissione Asincrona ................................................................................................................. 44
CAPITOLO 11 ALGORITMI E FUNZIONI ................................................................................................... 45
11.1. PREMESSA ............................................................................................................................................... 45
11.2. RITARDO SOFTWARE PROGRAMMABILE..................................................................................................... 45
11.2.1. Funzioni di supporto alla funzione Delay........................................................................................ 46
11.3. USO DEL DISPLAY LED A 7 SEGMENTI ..................................................................................................... 47
11.3.1. Le costanti ..................................................................................................................................... 47
11.3.2. Aggiornare il display...................................................................................................................... 48
11.3.3. Visualizzare una parola sul display ................................................................................................ 48
11.3.4. Convertire numero decimale per visualizzarlo sul display............................................................... 49
11.4. ALGORITMI DI SOMMA ............................................................................................................................. 50
11.4.1. Somma di due registri a 8 bit.......................................................................................................... 51
11.4.2. Somma di due numeri di 3 Byte ...................................................................................................... 51
11.5. ALGORITMI DI PRODOTTO E DI DIVISIONE .................................................................................................. 52
11.5.1. Prodotto di due numeri da 2 Byte ................................................................................................... 52
11.5.2. Divisione di un numero di 2 Byte per dieci...................................................................................... 54
APPENDICE A ...................................................................................................................................................... 56
P16F876.INC ....................................................................................................................................................... 56
APPENDICE B....................................................................................................................................................... 61
OPERATORI LOGICI E MATEMATICI ........................................................................................................................ 61
APPENDICE C ...................................................................................................................................................... 62
CONFIGURATION WORD ........................................................................................................................................ 62
APPENDICE D ...................................................................................................................................................... 63
STRUTTURA DELLA RAM - F ILE REGISTERS ........................................................................................................... 63
REGISTRO DI S TATO – S TATUS REGISTER ............................................................................................................... 64
APPENDICE E....................................................................................................................................................... 65
SET DI ISTRUZIONI PER I PIC .................................................................................................................................. 65
APPENDICE F....................................................................................................................................................... 66
ADCON0 REGISTER ............................................................................................................................................. 66
ADCON1 REGISTER ............................................................................................................................................. 67
APPENDICE G ...................................................................................................................................................... 68
STANDARD RS232................................................................................................................................................. 68
INDICE ANALITICO............................................................................................................................................. 70

II
Introduzione Alla Programmazione Dei PIC16F876

Capitolo 1 Il Manuale e il PIC

1.1. Premessa
Lo scopo che ci prefiggiamo scrivendo questo testo è di insegnare il linguaggio assembly
per la programmazione dei microcontrollori PIC16F876 della Microchip per permettere di sfruttare
tutte le potenzialità di questo integrato.
Il testo è stato scritto considerando che il lettore conosca già la tipologia di programmazione
in assembly, quindi non verranno spiegati i significati di parole come Program Counter, Stack,
Opcode, Direttive al compilatore, Istruzioni, Interrupt…
Al lettore digiuno da questo tipo di linguaggio si consiglia di studiare su un testo specifico
all’insegnamento del linguaggio assembly e solo in un secondo momento di affrontare la lettura di
questo, mentre per tutti quelli a cui serva solo un ripasso veloce dei termini di sopra elencati si
consiglia di leggere sul sito www.tanzilli.com il corso introduttivo alla programmazione del
PIC6F84 dove sono rivisti in sufficiente dettaglio i termini principali dell’assembly riferendoli
subito al mondo dei PIC della Microchip.

1.2. Il PIC16F876
Il microcontrollori PIC (Programmable Interface Controller) con la sigle 16F876 si presenta
come un integrato a 28 piedini1 posto in un contenitore DIP-SOIC.
Questo dispositivo oltre ad essere una CPU “in miniatura” possiede delle periferiche
integrate.
L’architettura utilizzata per il set d’istruzioni è di tipo RISC e ogni istruzione viene
identificata da un parola di 14bit: questa caratteristica impone un set limitato di istruzioni (35) e
quindi risulta che mancano istruzioni come moltiplicazione e divisione. Per quanto riguarda i dati
questi sono memorizzati in parole da 8bit.
Altra considerazione di importanza, per quel che riguarda l’architettura, è la presenza di un
solo registro interno che è quello di accumulazione denominato con la lettera ‘W’ (facendo
rferimento al mondo Intel a 16bit si può dire che esite solo il registro AX e mancano registri come
BX, CX, DX, SI, DI…)
La mancanza di questi espliciti registri però è supplita dalla presenza di memoria RAM
integrata sul CHIP (si hanno a disposizione 512 Bytes di memoria RAM di cui 144 Bytes riservati
1
Ci sono PIC anche con un numero diverso di piedini a seconda del numero di periferiche integrate che
possiedono e del tipo di compito a cui sono destinati. Il PIC16F876 fa perte della famiglia PIC16F87x, dove al posto
della x si anno le sigle 3,4,6 o7. Questi PIC, oltre ad essere diversi internamente possiedono anche un diverso numero di
piedini: 28 per i 16F873/6 e 40 per il 16F874/7.

1
Introduzione Alla Programmazione Dei PIC16F876

per la gestione del dispositivo e 368 Bytes liberi per utilizzo generale!!) che possono essere usati
alla stregua di registri! (quindi si può considerare la presenza di 368 registri a 8bit… calma non
esaltatevi: NON sono VERI registri sono locazioni di RAM usate COME registri, quindi ci saranno
degli accorgimenti per poterli usare.)
Le istruzioni del programma sono memorizzate su una memoria FLASH, avente 8k
(8192) locazioni di memoria da 14bit, e sono indirizzate attraverso un PC (Program Counter) da
13bit. La loro memorizzazione, in genere, viene effettuata mediante un Programmatore di Memorie
Flash oppure può essere fatta attraverso un procedimento di In-Circuit Serial Programming (ICSP)
attraverso due pin dell’integrato.
Si vuole ricordare la presenza di un’ulteriore forma di memorizzazione attraverso una
EEPROM (256 Bytes) che permette la memorizzazione di dati che permangono anche con lo
spegnimento del dispositivo.
Il PIC prevede l’interruzione del programma principale attraverso la gestione di Interrupt.
Bisogna fare attenzione perchè le potenzialità di controllo degli Interrupt sono ridotte da diversi
fattori: la non esistenza di una gerarchia di priorità, la gestione di un interrupt disabilita il
riconoscimento di un ulteriore Interrupt e la routine richiamata quando si verifica un Interrupt è
unica e quindi è compito del programmatore riconoscere l’evento che si è determinato.
Altre caratteristiche sono la possibilità di portare il componente in una modalità di risparmio
energetico (Sleep Mode) e di poter scegliere la frequenza di oscillazione, dove le frequenze
ammissibili vanno da 0 a 20 MHz che portano il PIC a funzionare tra 0 e 5 MHz2.

Per fare un rapido elenco delle periferiche integrate nel PIC si possono ricordare:
• 3 porte di Input/Output selezionabili: due con 8 piedini e una con 6 piedini
• 3 contatori: due a 8bit e uno a 16 bit. Possono sia servire per conteggi di tempo che di eventi e
con la possibilità di variare la frequenza di conteggio attraverso dei “prescaler” (Divisore di
frequenza di conteggio)
• 2 moduli che possono funzionare alternativamente come “Catturatori di eventi”,
“Comparatori”, o “Modulatori PWM”
• 5 ingressi facenti capo, attraverso un multiplexer, a un ConvertitorieAnalogico-Digitale a
10bit
• Interfaccia di Comunicazione seriale sia Sincrona che Asincrona

2
Questo è dovuto al fatto che la frequenza a cui vengono eseguite le istruzioni nella CPU risulta essere ¼ della
frequenza scelta per l’oscillatore.

2
Introduzione Alla Programmazione Dei PIC16F876

Capitolo 2 La Programmazione

2.1. Premessa
Il capitolo, attraverso un semplice esempio di programma, introduce la programmazione in
assembly del PIC.
Le sole periferiche considerate sono le porte di I/O, che , per ora, sono viste sotto l’aspetto
di registri logici e non come periferiche hardware: viene seguito questo primo approccio per
focalizzare l’attenzione sul funzionamento del PIC come microprocessore e non come
microcontrollori.
Gli argomenti di seguito trattati sono: direttive al compilatore, principi di programmazione,
gestione della memoria, gestione del processo, stack e gestione delle porte di I/O.

2.2. Le direttive al compilatore


Scriviamo il primo programma "FILE1.ASM". Il compito di questo Programma è di portare
alternativamente a 0 e a 1 un bit in un registro a 8 bit.
;
; File001.asm
;

PROCESSOR 16F876
RADIX DEC
INCLUDE "P16F876.INC"
ERRORLEVEL -302

;Settaggio dei Flags di configurazione del PIC

;Disable Flash Program Memory Code Protection


;Disable Watchdog Timer
;Disable Brown-out Reset
;Enable Power-up Timer
;HS oscillator => 20 MHz
;Enable Flash Program Memory Write
;Enable Low Voltage In-Circuit Serial Programming

__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _HS_OSC & _WRT_ENABLE_ON & _LVP_OFF

LED EQU 0

ORG 0x20

Count RES 3

3
Introduzione Alla Programmazione Dei PIC16F876

;Reset Vector
;Start point at CPU reset

ORG 0x00

bsf STATUS,RP0

movlw B'00011111'
movwf TRISA

movlw B'11111110'
movwf TRISB

movlw B'00111100'
movwf TRISC

bcf STATUS,RP0

bsf PORTB,LED

MainLoop

call Delay

btfsc PORTB,LED
goto SetToZero

bsf PORTB,LED
goto MainLoop

SetToZero

bcf PORTB,LED
goto MainLoop

;Subroutines

;Software delay

Delay
clrf Count
clrf Count+1
clrf Count+2

DelayLoop

decfsz Count,1
goto DelayLoop

decfsz Count+1,1
goto DelayLoop

decfsz Count+2,1
goto DelayLoop

return

END

F IL E 1 . A S M – P R IM O P R O G R A M M A

Per prima cosa vediamo la direttiva PROCESSOR che seleziona il tipo di microprocessore
utilizzato, quindi si trova radix che setta la notazione numerica di default alla quale il compilatore
associa tutti i numeri che nel programma sono indicati senza una notazione esplicita. Le alternative
sono hex, dec o oct.
Durante la programmazione i numeri possono essere immessi con notazioni differenti da
quella scelta per default; le notazioni accettate sono:

4
Introduzione Alla Programmazione Dei PIC16F876

F IG . 2 .2 -1 – N O TAZ IO N I N U M ER IC H E D E L C O M P IL ATO R E

(Oss: per l’esade cimale è accettata anche le forme 09FH e 0x9F)


La direttiva include “P16F876.INC” permette di definire delle costanti mnemoniche predefinite
dalla Microchip che facilitano della programmazione. Si rimanda all’Appendice A la visione del file
P16F876.INC.
La direttiva errorlevel serve per eliminare, in sede di compilazione, tre messaggi:
Message[302] FILE001.ASM 39 : Register in operand not in bank 0. Ensure that bank bits are correct.
Message[302] FILE001.ASM 42 : Register in operand not in bank 0. Ensure that bank bits are correct.
Message[302] FILE001.ASM 45 : Register in operand not in bank 0. Ensure that bank bits are correct.
Relativi alle istruzioni:
movwf TRISA
movwf TRISB
movwf TRISC
Non abbiamo idea a cosa possono essere dovuti, però non recano nessun problema: fidatevi!
(Oss: nei file di esempio trovati su www.tanzilli.com l’errore viene risolto dando come
istruzione:
movwf TRISA & H’7F’
che a rigor di logica non dovrebbe riportare nessuna differenza!3
Infatti, dal file P16F876.INC, si può vedere che:
TRISA = H'0085'
quindi:
H'0085'& H’7F’ = H'0085' !!!!!
)

Ritornando alla spiegazione del nostro file, la direttiva che si incontra in questo momento,
__CONFIG, è forse una delle più importanti in quanto il buon funzionamento del circuito dipende dal
giusto settaggio delle ‘Caratteristiche speciali della CPU’. Per i nostri scopi la configurazione, così
come è settata va più che bene. Per maggiori chiarimenti fare riferimento all’Appendice C (in cui è
riportata la Configuration Word) oppure al datasheet del componente a pag. 121.
Come per l’assembly usato per i processori Intel, la direttiva che ora i ncontriamo
LED EQU 0
serve per definire una costante, in questo caso di nome LED e avente il valore, in decimale,
pari a 0.

3
La spiegazione degli operatori &, != ecc. si può trovare nell’Appendice B.

5
Introduzione Alla Programmazione Dei PIC16F876

F IG . 2 .2 -2 – S TR U TTU R A D E L L A P R O G R AM M E M O R Y E S TAC K

La direttiva ORG serve al compilatore per capire in quale indirizzo di memoria porre il codice
che la segue. Nel nostro caso ci interessa prima definire la posizione della memoria RAM in cui
vogliamo allocare (o riservare) delle celle di memoria e poi definire la posizione di inizio del nostro
programma sulla FLASH. Si vuole far notare che la direttiva ORG usata per riservare memoria sulla
RAM e per scrivere il programma sulla flash è identica: è quindi compito del compilatore capire a
quale memoria si sta facendo riferimento.
Al programma è riservata l’indirizzo 0x00 (vedi figura 2.2 -2) mentre, come vedremo più in
dettaglio, alla routine di interrupt è riservato l’indirizzo 0x04.

Come si può vedere nell’Appendice D la memoria libera , cioè non riservata a speciali
funzioni del PIC, risulta essere indicata con la dicitura ‘General Purpose Register’ ed è
complessivamente pari a 368 Bytes. Ogni cella di memoria è di 8bit e gli indirizzi di partenza dai
quali si può allocare memoria sono: 0x20, 0xA0, 0x110 e 0x190.

F IG . 2 .2 -3 – I N D IR IZZ AM E N TO D E L L E M E M O R IE F L ASH E R AM

Per un problema di impossibilità di indirizzamento, tramite un indirizzamento diretto a 7 bit


(vedi figura 2.2-3), della memoria RAM di 512 Bytes, non si può vedere tutta la memoria
direttamente. Per poterla vedere tutta si dovrebbe avere la disponibilità di 9 bit d’indirizzamento: la
soluzione adottata è quella di suddividere la memoria in 4 banchi che vengono indirizzati da due bit

6
Introduzione Alla Programmazione Dei PIC16F876

dedicati (chiamati RP1 e RP0) che si trovano nel registro STATUS (Appendice D). Si osservi, nella
struttura del File Register (Appendice D), che questo registro è presente in ogni banco di memoria a
causa della sua importanza. Nel registro STATUS, infatti, sono elencati i seguenti bit di stato:
• RP1 e RP0 che servono per indirizzare i 4 banchi di memoria
Per selezionare i banchi si devono rispettare queste combinazioni:

RP1:RP0 Bank
00 0
01 1
10 2
11 3

• IRP è un bit che viene abilitato quando si esegue un indirizzamento indiretto della
memoria
• TO e PO utilizzati da istruzioni quali SLEEP oppure dal Watchdog
• Z che viene settato a uno se il risultato di un' operazione logica o aritmetica è nullo
• DC il bit dove viene registrato il riporto dovuto al quarto bit
• C è il bit dove viene registrato il riporto

Ritornando al programma …
L' istruzioneORG 0x20 risulta essere la direttiva che comunica al compilatore che ciò che
segue è codice che si trova nella memoria RAM! Nel nostro caso la linea seguente del programma
permette di allocare 3 Byte di memoria indicandola attraverso una etichetta mnemonica COUNT.
Dopo aver riservato 3 Byte di memoria la nuava direttiva org 0x00 comunica al compilatore
che da questo punto incomincia il programma principale.

2.3. Le istruzioni - Principi di programmazione


A questo punto abbiamo finito di preparare le costanti e le locazioni di memoria per cui
possiamo iniziare il programma vero e proprio!
Le istruzioni4, che scriveremo ora, saranno memorizzate nella memoria FLASH.
Prima di affrontare la descrizione esaustiva del programma si vuole fare una semplice
introduzione alle interfacce I/O del PIC. Innanzitutto le considereremo per comodià come semplici
porte logiche in cui i valori a cui si possono portare sono 0 e 1 logici.5
Le porte presenti nell' integrato sono tre, di cui una avente 6 piedini, e due con 8 piedini.
Sono indicate con la sigla PORTx dove al posto di x si si intende alternativamente A, B o C.

4
Fate riferimento all' Appendice E per avere una visione ompleta
c delle istruzioni o al datasheet del
componente a pag.139 per avere la spiegazione di ogni singola istruzione.
5
In realtà il valore logico 1 è relativo alla tensione +5V mentre lo 0 ai 0V. Sapendo questo si può pensare di
collegare opportunatamente ai piedini di output un led che si accenderà quando ai piedini arriva un 1 logico, oppure un
interruttore ai piedini di input che comunicheranno un 0 logico quando si chiuderà il contatto.

7
Introduzione Alla Programmazione Dei PIC16F876

F IG . 2 .3 -1 – P O S IZ IO N E D E L L E P O R TE N EL L ’ IN TE G R ATO A 2 8 P IN

Ogni porta è provvista/assistita da due registri a 8 bit: uno che serve per tenere le
informazioni sullo stato di utilizzo della porta, cioè se i singoli piedini sono usati come Input
(indicati nel registro attraverso un 1) o come Output (indicati con uno 0), e denominato con TRISx,
mentre l' altro mantiene traccia del dato presente nella porta (stato logico 1 o 0) e denominato con
PORTx (Attenzione stesso nome duplice significato!).

Registro definizione Registro contenete


Porta Numero piedini della direzione del il dato presente sulla
dato (I/O) porta
PORTA 6 TRISA PORTA
PORTB 8 TRISB PORTB
PORTC 8 TRISC PORTC

Ad ogni bit dei registri PORTx e TRISx corrisponde un piedino I/O del PIC.
Esempio.
- se il dato presente nel registro TRISB risulta essere B' 00001111' avremo che i piedini
della porta B saranno settati metà come Output (0) e metà come Input (1): nel caso in
esame i piedini RB4, RB5, RB6, RB7 saranno output mentre RB0, RB1, RB2, RB3
saranno Input.
- Considerando la stessa porta si può vedere che se il dato presente nel registro PORTB
fosse B' 00001111' avremo che il PIC sta ricevendo, dai piedini d' ingres
so, degli 1 e sta
trasmettendo degli 0.

…riprendiamo il FILE1.ASM
L' istruzione
BSF STATUS, RPO
Serve per settare la coppia di bit RP1:RP0=01 in modo da abilitare il BANK1 di memoria
RAM.
BSF, letteralmente ' Bit Set File register' , permette di settare a 1 il bit nella posizione RPO
contenuto nella locazione di RAM indirizzata da STATUS6.
Una vola abilitato il BANK1 si può aggiornare il funzionamento I/O delle porte7 A , B e C
andando ad impostare il valore dei registri TRISA, TRISB e TRISC.
6
STATUS, come RP0, W ecc.. sono costanti, che si riferiscono a registri o a bit, che sono definite all’interno
del file P16F876.INC, per questo motivo devono essere scritte in maiuscolo. Queste costanti permettono una più
semplice programmazione in assembly liberando il programmatore dall’onere della conoscenza dell’ind irizzo numerico
di ogni singolo registro o posizione dei bit all’interno dei registri.(vedere Appendice A)

8
Introduzione Alla Programmazione Dei PIC16F876

L' aggiornamento viene fatto con le seguenti istruzioni:


movlw B'00011111'
movwf TRISA

movlw B'11111110'
movwf TRISB

movlw B'00111100'
movwf TRISC
dove MOVLW permette di portare la costante B' 000111111' (in gergo detta LITERAL, e da
questo nome deriva la L presente in MOVLW) nell' accumulatore W (da qui la W in MOVLW). In
un secondo momento MOVWF permette di spostare il dato dall' accumulatore allaRAM (che in
gergo viene chiamata File Register, e da qui la F in MOVWF) nella posizione indirizzata dalla
costante TRISA.
Una volta aggiornati i Registri TRISx si deve riselezionare il BANK0 per poter abilitare
l' utilizzo del registri PORTx. Per far quest
o è usata l' istruzione BCF(Bit Clear File register) che
permette di ripristinare nel registro STATUS RP1:RP0=00.

Il programma ora porta a 1 il piedino 0 della porta B, che precedentemente si era abilitato
come output, attraverso:
bsf PORTB,LED
E' significativo notare come una istruzione del genere possa permettere l’accensione di un
led se questo fosse connesso al pin 0 della porta B: la costante LED=0 assume il significato di
indicatore del piedino a cui è connesso il led.

2.4. Gestione del processo con loop e salti


Il PIC viene avviato, in generale, con lo scopo di funzionare indefinitamente, quindi,durante
la programmazione, si deve fare in modo che il processo si chiuda in un loop infinito.
E' in questo loop che si svolge il vero programmadel PIC tutto ciò che precede il loop sono
solo preparativi e settagli per la configurazione del microcontrollore. Si deve però permettere al PIC
di uscire momentaneamente da questo loop ogni qualvolta sia necessario per poter eseguire una
certa funzione.
Il loop considerato è indicato in gergo con MainLoop (e non è detto che un programma
debba avere un unico MainLoop!).

Nel nostro programma, all' interno del MainLoop, troviamo una chiamata alla subroutin
Delay tramite l’istruz ione call. Delay è una subroutine che esegue un ritardo software.

Le istruzioni usate in questa subroutine, oltre alle istruzioni goto e return, sono:
- CLRF che permette di azzerare il registro indirizzato
- DECFSZ che decrementa un registro in memoria e nel momento in cui questo venga
azzerato, il programma esce dal DelayLoop saltando l’operazione GOTO.

2.4.1. Call e Goto


Si sa che vi è una grande differenza tra le due istruzioni: CALL e GOTO. La prima permette di
interrompere momentaneamente il programma per eseguire una routin ben definita, la seconda
permette di controllare il flusso del programma saltando a piacere nel codice. Nella gestione dei PIC

7
L' aggiornamento dello stato delle porte è una delle operazioni che per prime devono essere fatte durante la
programmazione. Durante questo aggiornamento si deve tener in considerazione le tipologia di circuito dove il PIC sarà
inserito.

9
Introduzione Alla Programmazione Dei PIC16F876

ci sono due problemi da non sottovalutare per queste istruzioni: la dimensione massima dello Stack
e la paginazione della Flash.
Come si può vedere dalla figura 2.2-2 la paginazione suddivide la FLASH in quattro parti.
Questa suddivisione comporta un problema sia per l' istruzione CALL che per la GOTO (che per la
RETURN). C' è da dire, innanzitutto che per programmi di piccole dimensioni la memoria occupata
dal codice rimane confinata nella pagina 0, solo per grandi programmi si deve considerare la
gestione delle pagine.(Nel caso si debbano scrivere programmi di grandi dimensioni si consiglia di
vedere pag. 26 del datasheet del componente)
Il problema dello Stack riguarda, invece, la sola istruzione CALL. Lo Stack ha una
dimensione massima di 8 livelli che permettono un' annidamento di 8 chiamate. Caratteristica dello
Stack è di essere un buffer circolare (se lo stack è stato riempito per 8 volte la nona volta viene
riscritto il valore che era stato accantonato per primo!) senza nessun controllo sulle condizioni di
Overflow e Underflow, e senza la possibilità di utilizzare istruzioni dirette, come potrebbero essere
PUSH e POP, per la gestione dello Stack in quanto sono assenti. MORALE: ATTENZIONE
durante la programmazione a non superare le 8 chiamate!!
L' uni
ca volta in cui potrebbe essere utile o ininfluente la caratteristica ciclica dello Stack
rigurda quei programmi aventi più MainLoop e che quindi possono spostarsi da uno ' stato stabile' ad
un altro anche eseguendo durante questi spostamenti più di 8 chiamate annidiate!(vedi figura)

2.4.2. Ritardo software


Sapendo che il PIC ha un' architettura RISC e che impiega un solo ciclo di CPU (che risulta
essere un quarto della frequenza del clock esterno) per eseguire un' operazione (questo nel caso che
l' operazione non comporti un salto), il loop di Delay decrementando il registro Count fino al suo
azzeramento (registro a 8bit che comporta 256 iterazioni per il suo azzeramento) iterando in modo
sequenziale l' azzeramento dei registri Count +1 e Count+2, genera un ritardo superiore a 16 milioni
di cicli di CPU. Questo vuol dire, considerando un Clock esterno a 20MHz, che internamente
diventa Clock di CPU a 5MHz, che il ritardo software, presente nel file di esempio, dura più di 3
secondi(~16Milioni/5MHz)!!

2.5. Direttive speciali: Banksel & co.


La Microchip ha introdotto delle direttive per il compilatore che permettono una più
semplice stesura del programma in assembly. L’elenco delle varie direttive può essere trovato sul
MPASM USER’S GUIDE (DS33014F.pdf) a pag. 23 e seguenti.
Quella che può essere più interessante conoscere è la banksel.
Con questa direttiva è possibile demandare al compilatore in fase di assemblaggio il compito
di selezionare il banco di memoria giusto in cui si trova una certa variabile.
Se ad esempio si deve considerare di leggere il registro EECON1 che si trova nel Bank3 e
poi di leggere il registro PCON del Bank2 queste operazioni con questa direttiva si scrivono
semplicemente in questo modo:
banksel EECON1
movf EECON1, W
......
banksel PCON
movf PCON,W

10
Introduzione Alla Programmazione Dei PIC16F876

......

Mentre il compilatore le interpreta come se avessimo scritto:


bsf STATUS,RP1
bsf STATUS,RP0
movf EECON1, W
......
bsf STATUS,RP1
bcf STATUS,RP0
movf PCON, W
......

Si possono fare due osservazioni: la prima è che con questo tipo di programmazione non ci
interessa sapere a priori la posizione dei registro in memoria, quindi si semplifica molto la
programmazione, la seconda è che questo metodo provoca un maggior dispendio di memoria per la
programmazione in quanto alcune istruzioni sono superflue.
Un esempio di questo tipo di programmazione si trova nel “file2.asm” dove si è riscritto il
“file1.asm” con le nuove direttive8.
;
; File002.asm
;

PROCESSOR 16F876
RADIX DEC
INCLUDE "P16F876.INC"

;Settaggio dei Flags di configurazione del PIC

;Disable Flash Program Memory Code Protection


;Disable Watchdog Timer
;Disable Brown-out Reset
;Enable Power-up Timer
;HS oscillator => 20 MHz
;Enable Flash Program Memory Write
;Enable Low Voltage In-Circuit Serial Programming

__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _HS_OSC & _WRT_ENABLE_ON & _LVP_OFF

LED EQU 0

ORG 0x20

Count RES 3

;Reset Vector
;Start point at CPU reset

ORG 0x00

banksel TRISA

movlw B'00011111'
movwf TRISA & 7FH

movlw B'11111110'
movwf TRISB & 7FH

movlw B'00111100'
movwf TRISC & 7FH

Banksel PORTB

bsf PORTB,LED

MainLoop

call Delay

8
Si ricorda che durante la compilazione il software della Microchip darà sempre il messaggio di “errore” per
tutti i registri che si trovano sul bank1. Questo messaggio , come prima detto, non deve essere considerato, oppure si
può risolvere con la direttiva errorlevel o aggiungendovi al nome del registro & 7FH.

11
Introduzione Alla Programmazione Dei PIC16F876

btfsc PORTB,LED
goto SetToZero

bsf PORTB,LED
goto MainLoop

SetToZero

bcf PORTB,LED
goto MainLoop

;Subroutines

;Software delay

Delay
clrf Count
clrf Count+1
clrf Count+2

DelayLoop

decfsz Count,1
goto DelayLoop

decfsz Count+1,1
goto DelayLoop

decfsz Count+2,1
goto DelayLoop

return

END

F IL E 2 . A S M – P R IM O P R O G R A M M A C O N B A N K S E L

2.6. Conclusioni
Il programma FILE1.ASM non si limita, quindi, a variare lo stato logico dei bit di un
registro , ma permette di portare ad 1, con una certa frequenza determinata della routine di ritardo
software,un pin di uscita de PIC; inoltre se pensassimo di connettere a questo piedino un led, un
programma del genere farebbe in modo che il led possa lampeggiare aritmicamente.

12
Introduzione Alla Programmazione Dei PIC16F876

Capitolo 3 Frequenza dell’oscillatore e del Clock del sistema

3.1. Premessa
Nel capitolo precedente si era accennato ad un oscillatore a 20 MHz, in questo si imparerà
ad ottenerne uno facendo uso di un solo quarzo e due capacità sfruttando le caratteristiche circuitali
dell’integrato. Il PIC, come detto nell’introduzione, può funzionare con diverse frequenze, quindi si
parlerà pure di come ottenere diversi valori di frequenze o come utilizzare un generatore di clock
esterno.
Importante è però capire che vi è una differenza tra la frequenza dell’oscillatore esterno e la
frequenza del clock interno con cui vengono eseguite le istruzioni del PIC, questo a causa del fatto
che la frequenza del clock interno risulta da una divisione per 4 della frequenza dell’oscillatore
esterno.

3.2. Scelta dell’oscillatore


Il PIC può essere settato in modo tale che possa lavorare con quattro configurazioni diverse
di oscillatori.
Le modalità possibili sono:
LP – Quarzo a bassa frequenza
XT – Quarzo o Risonatori Ceramici
HS – Quarzo o Risonatori Ceramici ad alta frequenza
RC – Resistenze e Capacità

13
Introduzione Alla Programmazione Dei PIC16F876

F IG . 3 .2 -1

Le modalità vengono scelte per mezzo della direttiva al compilatore __CONFIG (vedi
capitolo 2)
Se si vuole si può, inoltre, collegare il PIC ad una sorgente esterna di clock, ad esempio
quando si devono pilotare più microcontrollori che lavorino in modo sincronizzato, in questo caso
le configurazioni da usare sono LP, XT e HS.

14
Introduzione Alla Programmazione Dei PIC16F876

Capitolo 4 Interrupt

4.1. Premessa
Il PIC 16F876 possiede vari tipi di Interrupt. Si parla di 14 differenti sorgenti di interrupt,
ma molto facilmente nella programmazione se ne terranno in considerazione ben pochi: due o, più
frequentemente, uno. Questo vuol dire, da una parte, che durante la programmazione ci si dovrà
preoccupare di selezionare i tipi di interrupt di nostro interesse e dall' altra che si dovrà programmare
le routine ad hoc che ci permettano di gestire gli interrupt. Per fare questo si devono conoscere tre
aspetti: il primo è che per ogni interrupt che si verifica la chiamata a sottoprogramma che il PIC
esegue è unica per tutti gli interrupt e avviene all' indirizzo0x04 della memoria Flash (vedi figura
2.2-2),il secondo è che ci sono ben 5 registri dedicati alla gestione degli interrupt e il terzo è che sta
al programmatore verificare il tipo di interrupt che si è verificato andando a testare i registri
dedicati.

4.2. Programmare una routine di Interrupt


All' inizio del programma si deve quindi comunicare al compilatore la giusta sequenza di
istruzioni differenziando la routine del programma principale dalla routine della gestione degli
interrupt. La posizione di origine del programma si trova all’indirizzo 00H, mentre quella di
interrupt si trova all’indirizzo 04H: per comunicare la giusta posizione al compilatore si devono
usare le direttive ORG come di seguito mostrato:
ORG 00H ;Origine del programma
goto Start ;Salto incondizionato al Corpo del Programma

ORG 04H ;Origine della routine di interrupt


...
...

...
...
retfie ;Ritorna al programma principale nella
;posizione in cui si è generato l'interrupt

Start ... ;Corpo del programma


...

15
Introduzione Alla Programmazione Dei PIC16F876

Dall’esempio si nota che subito dopo aver dato origine al programma si deve fare un salto
incondizionato in modo tale che il compilatore riservi il posto alla routine di interrupt nella
memoria FLASH. Per riservare il posto alla routine di interrupt basta dichiarare la sua posizione con
la direttiva ORG 04H e quindi scrivere il suo codice.

Per poter programmare bene una routine di gestione degli interrupt è bene conoscere in che
modo le interruzioni vengono gestite.
Quando si verifica un' interrupt il PIC esegue alcune operazioni: disabilita il bit GIE del
registro INTCON in modo tale che non vengano gestiti altri interrupt contemporaneamente9, viene
abilitato il bit relativo all' interrupt che si è verificato, detto FLAG BIT, viene registrato nello stack
il PC e chiamata la locazione di memoria 0x04.
Quindi, sapendo questo, durante la programmazione di questa routine si deve:
- Fare attenzione alla posizione dove si colloca la sequenza iniziale della routine che deve
essere la 0x04 in modo che possa essere chiamata. (Questo viene fatto, come da
esempio, dalla direttiva ORG 04H)
- Salvare i dati10 del registro di stato STATUS e il registro accumulatore W (e altri
registri che si pensa possano essere modificati durante l' interruzione). Questa è una delle
classiche operazioni fatte nella gestione degli interrupt, essendo queste chiamate in
momenti sconosciuti dell’esecuzione del programma.
- Identificare l' interrupt testando i bit di interesse dei registri: INTCON, PIR1,PIR2
- Chiamare la subroutine di gestione appropriata
- Cancellare il bit che identifica l' interrupt
- Ripristinare gli eventuali registri precedentemente salvati
- Uscire dalla subroutine attraverso l' istruzioneretfie che oltre a ricaricare dallo stack il
PC riporta a 1 il bit GIE per poter rilevare altri eventuali interrupt

Un esempio di routine di gestione interrupt è:


ORG 0x20
....
....
status_temp RES 1
w_temp RES 1
....
....

ORG 0x04 ; Inizio routine di Interrupt


Banksel status_temp ;
movwf w_temp ; Salvo lo stato dei registri
movf STATUS,W ; W e STATUS.
movwf status_temp ;

corpo_routine_interrupt_inizio
....
....
....
corpo_routine_interrupt_fine

banksel status_temp ;
movf status_temp,W ;
movwf STATUS ;
swapf w_temp,F ; Recupero i registri
swapf w_temp,W ; W e STATUS salvati.
retfie ; Fine routine di Interrupt

9
Attenzione: questo potrebbe essere un problema! Nel PIC, infatti, non esiste una gerarchia di interrupt, quindi
l' interrupt che viene gestito è quello che si verifica per primo: è questo il perché è consigliabile implementare pochi
interrupt nel programma, in modo da evitare che se ne verifichi uno mentre ne viene gestito un altro perdendo così la
possibilità di osservarlo!
10
Non è necessario se questi non vengono modificati, mentre è di grande importanza se si ha la possibilità che
invece lo siano.

16
Introduzione Alla Programmazione Dei PIC16F876

....
....

NOTA: È molto probabile che una routine di questo tipo possa dare dei problemi durante il
salvataggio del registro STATUS. Infatti nella seconda riga si può vedere che la direttiva Banksel
prende il posto di una istruzione tipo BSF STATUS,RP0 che presuppone una variazione del registro
STATUS prima ancora che si sia fatta una sua copia. Da notare che però anche se tecnicamente non
corretta, una routine di questo tipo da problemi solo se viene chiamata, da un interrupt, in un punto
del programma dove il banco di memoria selezionato risulta essere diverso da quello in cui si trova
STATUS_TEMP, mentre non provoca nessun problema se ad esempio viene richiamata all' interno
di un loop infinito in cui si era già preselezionato il banco di memoria di STATUS_TEMP. Nello
stesso tempo, però una routine di questo tipo permette una gestione più veloce dell' interrupt rispetto
ad una routine che invece non presenta questo tipo di errore. Morale: state attenti quando usate una
routine di questo tipo e valutate se il risparmio di tempo è essenziale o se è meglio evitare possibili
problemi durante la chiamata di interrupt.
Una possibile gestione alternativa dell' interrupt che ene
ti conto del banco di memoria può
essere:
ORG 0x20
....
....
status_temp RES 1
w_temp RES 1
....
....

ORG 0x04 ; Inizio routine di Interrupt


btsfsc STATUS, RP1
goto banco_2o3

banco_0o1
btsfsc STATUS, RP0
goto banco_1

banco_0 ; RP1:RP0= 00
banksel status_temp ;
movwf w_temp ; Salvo lo stato dei registri
movf STATUS,W ; W e STATUS.
movwf status_temp ;
bcf status_temp, RP1
bcf status_temp, RP0
goto corpo_routine_interrupt_inizio

banco_1 ; RP1:RP0= 01
banksel status_temp ;
movwf w_temp ; Salvo lo stato dei registri
movf STATUS,W ; W e STATUS.
movwf status_temp ;
bcf status_temp, RP1
bsf status_temp, RP0
goto corpo_routine_interrupt_inizio

banco_2o3
btsfsc STATUS, RP0
goto banco_3

banco_2 ; RP1:RP0= 10
banksel status_temp ;
movwf w_temp ; Salvo lo stato dei registri
movf STATUS,W ; W e STATUS.
movwf status_temp ;
bsf status_temp, RP1
bcf status_temp, RP0
goto corpo_routine_interrupt_inizio

banco_3 ; RP1:RP0= 11
banksel status_temp ;

17
Introduzione Alla Programmazione Dei PIC16F876

movwf w_temp ; Salvo lo stato dei registri


movf STATUS,W ; W e STATUS.
movwf status_temp ;
bsf status_temp, RP1
bsf status_temp, RP0
goto corpo_routine_interrupt_inizio

corpo_routine_interrupt_inizio
....
....
....
corpo_routine_interrupt_fine

banksel status_temp ;
movf status_temp,W ;
movwf STATUS ;
swapf w_temp,F ; Recupero i registri
swapf w_temp,W ; W e STATUS salvati.
retfie0x04 ; Fine routine di Interrupt

....
....

Una semplice osservazione che si vuole fare è che il salvataggio di W e STATUS non è
sempre essenziale. Per suffragare questa affermazione si consideri questo semplice esempio
(file3.asm) in cui non è presente alcun accorgimento per il salvataggio dei dati del registro STATUS
e W.
;
; file0003.asm
;
; Programma che fa lampeggiare il led sull'uscita 0 della porta B
; Viene abilitato un'interrupt che segnala il cambiamento di stato delle linee RB4, RB5,RB6,RB7
; della porta B facendo accendere il led dell'uscita 1 della porta B
; Il led che si è acceso con l'interrupt si spegnerà dopo tre lampeggi del diodo intermittente

PROCESSOR 16F876
RADIX DEC
INCLUDE "P16F876.INC"

;Settaggio dei Flags di configurazione del PIC

;Disable Flash Program Memory Code Protection


;Disable Watchdog Timer
;Disable Brown-out Reset
;Enable Power-up Timer
;HS oscillator => 20 MHz
;Enable Flash Program Memory Write
;Enable Low Voltage In-Circuit Serial Programming

__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _HS_OSC & _WRT_ENABLE_ON & _LVP_OFF

LED1 EQU 0
LED2 EQU 1
LED3 EQU 2
LED4 EQU 3

ORG 0x20

Count RES 3
nTick RES 1 ;Registro utilizzato per contare il numero di
;lampeggi del LED 1

;Reset Vector
;Punto di inizio del programma al reset della CPU

ORG 00H

;Salta al corpo principale del programma. Questo jump Š necessario


;per evitare tutta la parte di codice per la gestione degli

18
Introduzione Alla Programmazione Dei PIC16F876

;interrupt.

goto Start

;Interrupt vector
;Punto di inizio per tutte le subroutine di gestione degli interrupt

ORG 04H

;**********************************************************************
; Interrupt handler
;**********************************************************************

;Accende il led 2 per segnalare che c'e' stato un interrupt


bsf PORTB,LED2

;Inizializza il contatore di lampeggi del LED1


movlw 3
movwf nTick

;Azzera nuovamente il flag RBIF per consentire all'interrupt di


;ripetersi
bcf INTCON,RBIF

;Ritorna al programma principale


retfie

;**********************************************************************
; Corpo del programma
;**********************************************************************
Start:
;Commuta sul secondo banco dei registri per accedere ai registri TRISA e TRISB

banksel TRISA

;Definizione delle linee di I/O (0=Uscita, 1=Ingresso)


;Definizione della porta A

movlw 00011111B
movwf TRISA & 7FH

;Definizione della porta B


;Le linee da RB0 a RB3 vengono programmate in uscita per essere collegate ai quattro led
;Le linee da RB4 a RB7 vengono programmate in ingresso per essere collegate ai quattro
pulsanti

movlw 11110000B
movwf TRISB & 7FH

;Commuta sul primo banco dei registri

banksel LED1

;Spegne tutti i led collegati sulla porta B


bcf PORTB,LED1
bcf PORTB,LED2
bcf PORTB,LED3
bcf PORTB,LED4

;Abilita l'interrupt sul cambiamento di stato delle linee RB4,5,6,7


banksel INTCON
movlw 10001000B
movwf INTCON

;**********************************************************************
; Loop principale
;**********************************************************************

MainLoop

call Delay ;Ritardo software

btfss PORTB,LED1 ;Led acceso ?


goto TurnOnLed1 ;No, lo accende
goto TurnOffLed1 ;Si, lo spegne

;Accensione led e decremento del contatore di lampeggi

19
Introduzione Alla Programmazione Dei PIC16F876

TurnOnLed1
bsf PORTB,LED1

;Controlla se LED 2 di segnalazione dell'interrupt e' gia acceso.


;Se e' acceso decrementa il contatore nTick ad ogni lampeggio di
;LED1. Quando nTick vale 0 spegne LED 2

btfss PORTB,LED2 ;LED2 acceso ?


goto MainLoop ;No, continua a lampeggiare

decf nTick,1 ;Si, decrementa nTick


btfss STATUS,Z ;nTick = 0 ?
goto MainLoop ;No, continua a lampeggiare

bcf PORTB,LED2 ;Si, spegne LED2

goto MainLoop ;Continua a lampeggiare

;Spegnimento led

TurnOffLed1

bcf PORTB,LED1 ;Spegne LED 1


goto MainLoop ;Continua a lampeggiare

;**********************************************************************
; Subroutine
;**********************************************************************

;Subroutine di ritardo software

Delay
clrf Count
clrf Count+1
clrf Count+2

DelayLoop

decfsz Count,1
goto DelayLoop

decfsz Count+1,1
goto DelayLoop

decfsz Count+2,1
goto DelayLoop

return

END

F IL E 3 . A S M – G E S T IO N E I N T E R R U P T

Una volta conclusa la programmazione della routine di interrupt si deve continuare il


percorso del programma principale. Per fare questo si pone l’etichetta usata dal salto incondizionato
GOTO e si programma il cosiddetto Corpo del Programma.
Nella programmazione del corpo del programma, oltre alle funzioni che il PIC dovrà
eseguire per il compito che gli è stato assegnato, si deve:
1. Abilitare il tipo di interrupt che si vuole osservare andando a settare a 1 i bit appropriati
nei registri: INTCON, PIE1, PIE2
2. Abilitare la segnalazione generale degli interrupt attraverso il settaggio a 1 del bit GIE
che si trova nel registro INTCON
3. Tener conto che la chiamata ad un interrupt porta ad un salvataggio nello stack
dell' indirizzo contenuto nel PC e che quindi si potrebbe verificare un overflow dello
stack!!

20
Introduzione Alla Programmazione Dei PIC16F876

4.3. Registri di Interrupt


Si è in precedenza accennato alla presenza di 5 registri per la gestione degli interrupt. Questi
registri sono: INTCON, PIE1, PIE2, PIR1,PIR211

F IG . 4 .3 -1

Ogni bit di questi registri ha una sua funzione particolare ed esclusiva nella gestione degli
interrupt. Si può però fare una distinzione dei bit in 3 classi:
1. Il bit GIE e PEIE di INTCON
2. I bit, esclusi GIE e PEIE, il cui no,e finisce con E, cioè i bit TOIE, INTE, RBIE di
INTCON e tutti i bit di PIE1 e PIE2.
3. I bit il cui nome finisce con F, cioè i bit TOIF, INTF, RBIF di INCON e tutti i bit di
PIR1 e PIR2.

Nella prima classe si è posto il bit GIE che è il bit di abilitazione di tutti gli interrupt che
possono essere segnalati. Come si può osservare dalla figura 4.3-2 la segnalazione degli interrupt è
fatta attraverso una rete logica e la comunicazione alla CPU dell’interrupt è vincolata dal settag gio a
uno di GIE.

F IG . 4 .3 -2

11
Si veda il datasheet del PIC per maggiori dettagli: pag 20 e seguenti

21
Introduzione Alla Programmazione Dei PIC16F876

Allo stesso modo il bit PEIE possiede una grande importanza in quanto blocca la
comunicazione di un interrupt da tutta una serie di sorgenti. Questo tipo di interruzioni vengono
chiamate Interruzioni di periferica (Peripheral Interrupt).
Senza addentrarci nella gestione di ogni singola sorgente di interruzione, possiamo dire che
il registro INTCON permette la gestione degli INTERRUPT provenienti dal TIMER0, dal pin
RB0/INT della porta B, e dai piedini RB4:RB7 sempre della porta B, mentre tutte gli altri interrupt
sono generati dalle periferiche e quindi sono trattati in modo a se stante attraverso i registri PIEx e
PIRx.
La seconda classe si compone dei bit, detti ENABLE BIT, che permettono l’abilitazione o la
disabilitazione della segnalazione del singolo interrupt.
Nell’ultima classe si hanno i cosiddetti FLAG BIT che segnalano l’avvenuto interrupt.
Molto importante è sapere che anche quando una sorgente di interrupt non viene abilitata per mezzo
del suo ENABLE BIT, se si verifica un interrupt questo viene segnalato sul FLAG BIT, e la
comunicazione alla CPU dell’interruzione è ostacolata dall’AND logico con l’ENABLE BIT.
Si vuole far presente che all’uscita della routine di getione dell’interrupt è compito del
programma il ritorno a zero del FLAG BIT che ha generato l’interrupt, pena la nuova richiamata
della stessa interruzione.

22
Introduzione Alla Programmazione Dei PIC16F876

Capitolo 5 Timer e Contatori di eventi

5.1. Premessa
In questo capitolo si parla delle periferiche del PIC usate come contatori ti tempo e di eventi.

5.2. Il Timer 0
Questo modulo è un contatore di tempo, o di eventi, a 8 bit. Il registro usato per il conteggio
è detto TMR0.
In questa periferica si possono vedere 4 sezioni distinte:
1. l' ingresso del clock del contatore
2. il prescaler a 8 bit
3. il modulo del watchdog
4. il registro a 8 bit TMR0

F IG . 5 .2 -1 - T IM E R 0

23
Introduzione Alla Programmazione Dei PIC16F876

Questo dispositivo è assistito dai bit 0:5 del registro OPTION_REG12

F IG . 5 .2 -2

Partendo dalla sezione d' ingresso del clock possiamo vedere che il bit T0CS quando è a 0
seleziona come clock del timer il clock di sistema, mentre se è a 1 abilita il clock esterno presente
sul piedino 6 (denominato RA4/T0CKI)13. Il bit T0SE permette di selezionare il fronte di salita, del
clock esterno, con cui fare procedere il conteggio. Osserviamo che questo dispositivo si presta sia
per un conteggio di tempo (sia quando si abilita il clock interno, sia quando si abilita un clock
esterno), sia per un conteggio di eventi, quando al piedino 6 fa capo un segnale che commuta per
segnalare un evento.
Il prescaler è invece un dispositivo che permette di "dividere" la frequenza di clock
(attraverso la scelta opportuna dei bit PS2:PS0, vedi figura 4.2-3) e quindi permette di incremetare
il contatore come se avessimo a disposizione frequenze di clock differenti. Questo modulo è
comune sia al TIMER0 che al Watchdog, quindi la selezione, attraverso il bit PSA, dell' utilizzo per
uno ne esclude l' uso da parte dell' altro. (vedi figura 4.2
-1)

F IG . 5 .2 -3

Il watchdog è una periferica a se stante rispetto al TIMER0 che ha in comune con esso
l' utilizzo del solo Prescaler. Il Watch Dog Timer è un oscillatore interno al PIC, ma completamente
indipendente dal resto della circuiteria, il cui scopo è quello di rilevare eventuali blocchi del flusso
normale del programma e attraverso un reset del microcontrollori di ripristinare la normale
esecuzione. (Per maggiori chiarimenti sul watchdog fare riferimento al datasheet)
Infine è nel registro TMR0 che è contenuto il dato del conteggio. Questo registro è
accessibile sia in scrittura che in lettura, questo comporta sia la possibilità di fare partire il
conteggio da un valore desiderato, sia la possibilità di osservare lo stato del conteggio. Essendo a 8

12
Si veda pag. 48 del datasheet per maggiori informazioni
13
Ricordiamo che il piedino 6 si trova sulla porta A e quindi per abilitare il suo uso come clock esterno si deve
abilitare il piedino come ingresso segnalandolo nel registro TRISA. Bisogna poi provvedere ad un' adeguata elettronica
esterna.

24
Introduzione Alla Programmazione Dei PIC16F876

bit, una volta raggiunto il valore 255 all’incremento successivo il contatore si azzera andando in
overflow. L’overflow del timer 0 genera un interrupt segnalato dal bit T0IF del registro INTCON.

5.3. Timer 1
Questo modulo è un contatore di tempo o di eventi a 16 bit. Il registro a 16bit è detto TMR1
ed è formato da due registri a 8 bit (TMR1H:TMR1L) che possono essere letti o scritti. Dopo
l’accensione del PIC il valore presente in questi registri è sconosciuto e quindi si deve pensare di
aggiornarli se si intende usare il timer1. Questo modulo permette la generazione di un interrupt
quando si verifica l’overflow del registro TMR1 con la segnalazione nel flag TMR1IF nel registro
PIR1.

F IG . 5 .3 .2 -5 .3 -1 – T IM E R 1

Il timer1 è assistito dal registro T1CON (vedi pag 51 del datasheet) che permette: la scelta
della divisione del prescaler, l’abilitazione o la disabilitazione dell’incremento del registro TMR1 e
la scelta del tipo di clock da usare. Caratteristica peculiare di questo timer è la possibilità di
collegare un circuito oscillatore dedicato e permettere, quindi, un conteggio sia sincrono che
asincrono, alla frequenza desiderata.
Questa periferica può essere usata da sola oppure insieme alle funzioni Capture e Compare
delle periferiche CCP. (Si faccia riferimento al capitolo dedicato)

5.4. Timer2
Questo modulo è un contatore a 8 bit esclusivamente alimentato dal clock di sistema: può
essere quindi solo un contatore di tempo. Il registro dove viene memorizzato il conteggio è il
TMR2.

25
Introduzione Alla Programmazione Dei PIC16F876

F IG . 5 .4 .3 -5 .4 -1 – T IM E R 2

Il Timer2 ha diverse particolarità:


- Possiede un prescaler per la divisione del clock che permette le sole configurazioni 1:1,
1:4, 1:16.
- Possiede un registro di supporto a 8bit, detto PR2, accessibile sia n lettura che in
scrittura, che viene costantemente confrontato con il registro TMR2. Quando i due
registri sono uguali viene generata una segnalazione che origina tre eventi: azzeramento
del registro TMR2, generazione di un segnale “TMR2 Output” (usato da modulo SSP –
Syncronous Serial Port- vedi pag.63 del datasheet) e generazione di un segnale di
interrupt.
- Possiede, infine, un postscaler che gestisce il segnale di interrupt generato dal
comparatore. Le divisioni possibili sono tutte quelle nell’interballo da 1:1 a 1:16,
permettendo quindi di segnalare l’avvento dell’interrupt al bit TMR 2IF di PIR1 solo
dopo che sono avvenute un numero prefissato di uguaglianze tra TMR2 e PR2.

Il registro che assiste il Timer 2 è il T2CON.


Anche questa periferica può essere usata da sola o per mezzo della funzione PWM del
modulo CCP. (Si faccia riferimento al capitolo dedicato)

26
Introduzione Alla Programmazione Dei PIC16F876

Capitolo 6 Le Porte del PIC

6.1. Premessa
Tutti funzioni eseguite dal PIC devono poter comunicare con la circuiteria elettronica
esterna. Questa comunicazione viene fatta attraverso le 3 porte del PIC.
Nel capitolo 2 si è parlato di queste porte a livello logico: da allora si è appreso che per la
configurazione in ingresso o in uscita i singoli piedini di una porta si deve configurare i registro
TRIx a lei relativo, mentre per leggere o scrivere si usa il registro PORTX.
Nella realtà le porte del PIC risultano essere dispositivi hardware abbastanza complessi,
dove ogni singolo piedino può avere caratteristiche a se stanti e che quindi merita esso stesso la
definizione di dispositivo.
In questo capitolo saranno discusse nel dettaglio le caratteristiche di queste periferiche.

6.2. Porta A
Questa porta è contraddistinta da 6 piedini di I/O che, sull' integrato DIP
-SOIC a 28 piedini,
si posizionano dal numero 2 al numero 7. I nomi e le funzioni di queste linee sono:
- RA0/AN0 : piedino I/O – ingresso analogico
- RA1/AN1 : piedino I/O – ingresso analogico
- RA2/AN2/VREF- : piedino I/O – ingresso analogico
- RA3/AN3/VREF+ : piedino I/O – ingresso analogico
- RA4/TOCKI : piedino I/O – ingresso clock esterno per Timer0
- RA5/AN4/SS : piedino I/O – ingresso analogico – ingresso per trasmissioni seriali

Il funzionamento di queste linee, come si può vedere dal nome che portano, può essere
diverso, tuttavia si può osservare come la configurazione dello stadio di uscita sia lo stesso (ad
esclusione della porta RA0/TOCKI)

6.2.1. Stadio di uscita delle linee RA0, RA1, RA2 ,RA3 e RA5
Iniziamo dal gruppo di linee RA0, RA1, RA2 ,RA3 e RA5 per le quali è riportato lo schema
di uscita nella figura 5.2-1.
Prendiamo come esempio la linea RA0 ed analizziamo il funzionamento dello stadio d' uscita
sia quando la linea funziona in ingresso, che quando funziona in uscita.

27
Introduzione Alla Programmazione Dei PIC16F876

6.2.2. Funzionamento in ingresso


Per configurare la linea RA0 in ingresso, dobbiamo mettere a 1 il bit 0 del registro TRISA
con l' istruzione:
bsf TRISA,0
Questo determina una commutazione ad 1 dell’uscita Q del flip -flop di tipo D-latch indicato
nel blocco con il nome TRIS latch. Per ogni linea di I/O delle porta A, B, e C esiste uno di questi
flip-flop e lo stato logico in cui si trova dipende strettamente dallo stato logico del relativo bit nel
registro TRIS (anzi per meglio dire ogni bit del registro TRISx è fisicamente implementato con un
TRIS latch).
L' uscita Q del TRIS latch è collegata all' gresso
in di una porta logica di tipo OR. Questo
significa che, nel nostro caso, indipendentemente dal valore presente all' altro ingresso, l' uscita della
porta OR varrà sempre 1 in quanto uno dei suoi ingressi vale 1. In questa condizione il transistor P
non conduce e mantiene la linea RA0 scollegata dal positivo d' alimentazione.

F IG . 6 .2 -1

Allo stesso modo l' uscita negata del TRIS latch è collegata all' ingresso di una porta AND
quindi l' uscita di questa varràsempre 0 in quanto uno dei suoi ingressi vale 0. In questa condizione
anche il transistor N non conduce mantenendo la linea RA0 scollegata anche dalla massa. Lo stato
logico della linea RA0 dipenderà esclusivamente dalla circuiteria esterna a cui la collegheremo.
Applicando 0 o 5 volt al pin RA0, sarà possibile leggerne lo stato sfruttando la circuiteria
d' ingresso del blocco rappresentata dal TTL input buffer e dal latch d' ingresso.
Questi cinque ingressi possono essere utilizzati come ingressi analogici da inviare al
convertitore D/A. Per questo motivo vi è un ulteriore registro ADCON1 (vedi il capitolo dedicato)
che permette di selezionare l’entrata come analogica e disabilitare quindi l’ingresso digitale.

28
Introduzione Alla Programmazione Dei PIC16F876

6.2.3. Funzionamento in uscita


Per configurare la linea RA0 in uscita, dobbiamo mettere a 0 il bit 0 del registro TRISA con
l' istruzione:
bcf TRISA,0
Questo determina la commutazione a 0 dell' uscita Q del TRIS latch. In questo stato il valore
in uscita dalle porte OR e AND dipende esclusivamente dallo stato dell' uscita Q negata del Data
Latch. Come per il TRIS latch, anche il Data Latch dipende dallo stato di un bit in un registro, in
particolare del registro PORTA. La sua uscita negata viene inviata all' ingresso delle due porte
logiche OR e AND e quindi direttamente sulla base dei transistor P ed N.
Se mettiamo a 0 il bit 0 del registro PORTA con l' istruzionebcf PORTA,0 otterremo la
conduzione del transistor N con conseguente messa a 0 della linea RA0.
Se invece mettiamo a 1 il bit 0 con l' istruzione:bsf PORTA,0 otterremo la conduzione del
transistor P con conseguenza messa a +5 volt della linea RA0.
Nel funzionamento di uscita è sempre possibile rileggere il valore inviato sulla linea tramite
la circuiteria d' ingresso.

6.2.4. Stadio d'uscita della linea RA4/T0CKI


Analizziamo ora il funzionamento dello stadio d' uscita della linea RA4 (figura 5.2-2) che si
differenzia da tutte le altre linee di I/O della porta in quanto è multiplexata con il modulo Timer0
per essere utilizzata come ingresso del clock esterno.

F IG . 6 .2 -2

La logica di commutazione è sostanzialmente identica al gruppo di linee RA0-3 ad


eccezione dell' assenza della porta OR e del transistor P,ovvero di tutta la catena che consente di
29
Introduzione Alla Programmazione Dei PIC16F876

collegare al positivo la linea RA4. Questo significa, in termini pratici, che quando la linea RA4
viene programmata in uscita e messa a 1 in realtà non viene connessa al positivo ma rimane
scollegata. Tale tipo di circuiteria d' uscita viene denominata a "collettore aperto”.
Se vogliamo che la linea RA4 vada a 1 dovremo collegare esternamente una resistenza di
pull-up, ovvero una resistenza collegata al positivo di alimentazione.
Le caratteristiche salienti di questo pin risultano essere la presenza di un trigger di Smith in
ingresso e l’uscita a collettore (o drain) aperto.

6.3. Porta B
Questa porta è contraddistinta da 8 piedini di I/O che, sull' integrato DIP (o SOIC), si
posizionano dal numero 21 al numero 28. I nomi e le funzioni di queste linee sono:
- RB0/INT : piedino I/O – ingresso interrupt esterno
- RB1 : piedino I/O
- RB2 : piedino I/O
- RB3/PGM : piedino I/O – Piedino usato per la programmazione del CHIP
- RB4 : piedino I/O con generazione di interrupt alla sua variazione di stato
- RB5 : piedino I/O con generazione di interrupt alla sua variazione di stato
- RB6/PGC : piedino I/O con generazione di interrupt alla sua variazione di stato – Piedino
usato per la programmazione del CHIP
- RB7/PGD : piedino I/O con generazione di interrupt alla sua variazione di stato – Piedino
usato per la programmazione del CHIP

F IG . 6 .3 -1

30
Introduzione Alla Programmazione Dei PIC16F876

6.3.1. Stadio d'uscita delle linee RB0, RB1, RB2 ed RB3


Anche per questo gruppo di linee rimane sostanzialmente invariata la logica di
commutazione: l’unica differenza è nello schema a blocchi dove i transistor N e P, visti sulla porta
A, vengono rappresentati da un buffer.
Queste linee dispongono in aggiunta di una circuiteria di weak pull-up attivabile quando le
linee sono programmate in ingresso. In ingresso infatti, come spiegato precedentemente, le linee
vengono completamente scollegate dal PIC in quanto sia il transitor P che il transistor N sono
aperti. Lo stato delle linee dipende quindi esclusivamente dalla circuiteria esterna. Se tale circuiteria
è di tipo a collettore aperto o più semplicemente è costituita da un semplice pulsante che, quando
premuto, collega a massa la linea di I/O, è necessario inserire una resistenza di pull-up verso il
positivo per essere sicuri che quando il pulsante è rilasciato ci sia una condizione logica a 1 stabile
sulla linea d' ingresso. La circuiteria di weak pull
-up consente di evitare l' uso di resistenzedi pull-up
e può essere attivata o disattivata agendo sul bit RBPU del registro OPTION_REG.
La sola linea RB0/INT inoltre, presenta una caratteristica molto particolare. Essa, quando
viene configurata come linea di ingresso, può generare un interrupt. L’i nterruzione è generata o sul
fronte di salita o di discesa del segnale a seconda di come il bit INTDG del registro OPTION_REG
è settato, ed è segnalato dal bit RBIE del registro INTCON.

6.3.2. Stadio d'uscita delle linee RB4, RB5, RB6 e RB7


La circuiteria di commutazione di questo gruppo di linee è identica al gruppo RB0-3 e anche
queste linee dispongono della circuiteria di weak pull-up.
La peculiarità di queste linee è dovuta alla presenza di uno stadio in grado di rilevare
variazioni di stato su una quansiasi linea e di generare un interrupt quando è settato il bit RBIE di
INTCON.
L’interrupt, che può essere generato dalle sole linee configurate in ingresso, è in comune tra
tutte le linee in quanto è segnalato dal solo bit RBIF di INTCON: è compito del programmatore
accertarsi quale linea è responsabile dell’interrupt.
L’osservazione dell’avvenuta variazione di stato è ottenuta confrontando il valore di
ingresso “vecchio” riportato sul “latch old” con quello contenuto nel “latch new”.
Proprio per questa particolarità, cioè che l’interrupt viene generato dal “mismatch” del dato
contenuto nei due latch, si deve fare attenzione durante la gestione dell’interrupt. Il solo modo,
infatti, per cancellare il flag RBIF di INTCON è quello di risolvere per primo il mismatch tra i due
latch, e solo in seguito di cancellare il flag RBIF. Per risolvere il mismatch basta una qualsiasi
operazione di lettura o scrittura della porta B che permette di aggiornare in automatico il “latch
old”.
Vogliamo inoltre ricordare che le porte RB3/PGM, RB6/PGC, RB7/PGD sono multiplexate
con la funzione di Programmazione a Bassa Tensione. Si veda il datasheet per maggiori
informazioni.

6.4. Porta C
Questa porta è contraddistinta da 8 piedini di I/O che, sull' integrato DIP -SOIC a 28 pin, si
posizionano dal numero 11 al numero 18. I nomi e le funzioni di queste linee sono:
- RC0/T1OSO/T1CKI : piedino I/O – Uscita oscillatore Timer1 – Ingresso clock Timer1
- RC1/T1OSI/CCP2 : piedino I/O – Ingresso oscillatore Timer1 – Ingresso Capture2 o Uscita
Compare2 o Uscita PWM2
- RC2/CCP1 : piedino I/O – Ingresso Capture1 o Uscita Compare1 o Uscita PWM1
- RC3/SCK/SCL : piedino I/O – piedino usato per trasmissioni seriali sincrone
- RC4/SDI/SDA : piedino I/O – piedino usato per trasmissioni seriali sincrone
31
Introduzione Alla Programmazione Dei PIC16F876

- RC5/SDO : piedino I/O – piedino usato per trasmissioni seriali sincrone


- RC6/TX/CK : piedino I/O – piedino usato per trasmissioni seriali sincrone o come
trasmettitore per quelle asincrone
- RC7/RX/DT : piedino I/O – piedino usato per trasmissioni seriali sincrone o come
ricevitore per quelle asincrone

Questa porta ha la caratteristica di essere usata come un ingresso o uscita da alcune


periferiche quali: trasmissione seriale sincrona che asincrona e dal Timer 1 quando si configura
l’oscillatore esterno.
Quando una di queste periferiche è abilitata i piedini della porta C vengono usati come
ingressi o uscite indipendentemente dalla impostazione fatta sul registro TRISC. Questo è ottenuto
attraverso una circuiteria particolare che scavalca i Tris e Data latch.
Si rimanda al datasheet per maggiori informazioni sull’uso che le periferiche fanno della
porta C.

F IG . 6 .4 -1

32
Introduzione Alla Programmazione Dei PIC16F876

Capitolo 7 I moduli CCP

7.1. Premessa
Il PIC possiede 3 funzioni particolari che permettono di catturare il tempo presente nel
Timer 1 quando si verifica un evento esterno (funzione CAPTURE), di generare un evento quando
il conteggio del Timer1 è uguale ad un valore prefissato (funzione COMPARE) e ancora una
funzione per la generazione di una modulazione a larghezza d’impulsi (funzioni PWM – pulse wide
modulation).
Le funzioni di CAPTURE, COMPARE e PWM sono integrate in due moduli detti CCP1 e
CCP2. Quando si decide una funzione per un modulo se ne disabilita l’utilizzo delle altre due.
I due moduli sono indipendenti, e questo ci permette di scegliere per entrambi la funzione
che vogliamo. Le funzioni si appoggiano ai timer 1 e 2 in questo modo: la funzione Capture e la
funzione Compare usano il timer1, mentre la PWM il timer 2. Questo sfruttamento dei timer
comporta delle interazioni tra le funzioni che bisogna tener presente. Nella configurazione:
- PWM/Capture o Pwm/Compare: non ci sono problemi
- Capture/Capture: il Timer 1 è usato per entrambe le funzioni
- Capture/Compare: la funzione Capture può triggerare su un determinato evento
cancellando il registro TMR1
- Compare/Compare: ci sono due funzioni che portano a zero il registro TMR1
- PWM/PWM: entrambe, basandosi sul Timer 2, operano alla stessa
frequenza.

Ogni modulo CCP possiede un registro a 16 bit che assume un significato diverso a seconda
della funzione selezionata, e hanno le seguenti caratteristiche:
CCP1 Module possiede:
- Un registro CCPR1 a 16 bit formato da due registri a 8 bit: CCPR1L (byte meno significativo) e
CCPR1H (byte più significativo)
- Un registro per il controllo del modulo detto CCP1CON
- La generazione di un evento durante la comparazione che resetta il Timer1

CCP2 Module possiede:


- Un registro CCPR2 a 16 bit formato da due registri a 8 bit: CCPR2L (byte meno significativo) e
CCPR2H (byte più significativo)
- Un registro per il controllo del modulo detto CCP2CON
- La generazione di un evento durante la comparazione che resetta il Timer1 e fa partire la
conversione A/D

33
Introduzione Alla Programmazione Dei PIC16F876

I registri di configurazione dei moduli CCP (CCP1CON e CCP2CON) sono così fatti:

F IG . 7 .1 -1 – R E G IS TR I C C P 1 C O N E C C P 2 C O N

OSS: I moduli CCP si affacciano sulla porta C, ma non sfruttano la caratteristica di


scavalcare i settagli del registro TRISC, quindi si dovranno settare i suoi bit in modo che le linee
siano ingressi nel caso della funzione Capture, mentre siano uscite per la Compare e la PWM.

7.2. Funzione Capture


Questa funzione permette di catturare nel registro a 16 bit CCPR1 (o analogamente CCPR2)
il valore presente nel registro TMR1 del timer1 al verificarsi di un evento sul pin RC2/CCP1 (o
RC1/CCP2). Come si vede dalla figura l’evento può essere “filtrato” da un prescaler e da un
selettore di fronti in modo tale che i soli eventi accettati siano: un fronte di salita, un fronte di
discesa, 4 fronti di salita o 16 fronti di salita.

F IG . 7 .2 .1 - F U N Z IO N E C APTU R E

Oss: quando si cambiano le impostazioni della funzione Capture viene generato un falso
interrupt di Capture, per evitare questo si deve disabilitare l’acquisizione dell’interrupt di cattura
(bit CCPxIE del registro PIE1) e, una volta modificata la funzione, cancellare il flag d’interrupt
CCPxIF dal registro PIR1 e riabilitare l’acquisizione in PIE1.

34
Introduzione Alla Programmazione Dei PIC16F876

7.3. Funzione Compare


Attraverso questa funzione si può monitorare costantemente il registro TMR1 e generare un
evento quando il contenuto di TMR1 eguaglia il contenuto del registro CCPRx. Gli eventi possibili
sono 4:
- Portare alta l’uscita RC1/CPP2 (RC2/CCP1) e generazione dei un interrupt
- Portare bassa l’uscita RC1/CPP2 (RC2/CCP1) e generazione dei un interrupt
- Generare del solo interrupt
- Generare un evento detto “Trigger special event”, che per il modulo CCP1 consiste nel solo
azzeramento del TMR1, mentre per il modulo CCP2 consiste nell’azzeramento del TMR1 e
nell’avvio della conversione A/D, e generazione dei un interrupt

F IG . 7 .3 .2 – F U N Z IO N E C O M P AR E

7.4. Funzione PWM


Per generare una modulazione PWM serve definire il periodo della forma d’onda e il suo
duty cicle. Per far questo si devono impostare dei valori in appositi registri:
- La durata del periodo viene messa nel registro PR2 (che si trova nel secondo banco di
memoria RAM). Il valore da impostare è dedotto dalla seguente relazione:
Periodo PWM = [(PR2 ) + 1]⋅ 4 ⋅ Tosc ⋅ (Valore del prescaler TMR2)
oppure più semplicemente da:
PR2 =
(Periodo PWM ) −1
4 ⋅ Tosc ⋅ (Valore del prescaler TMR2)

- La durata del “duty cycle” 14 è definito da un registro a 10bit ottenuto utilizzando


contemporaneamente il registro a 8 bit CCPRxL, per i bit meno significativi, e due bit, il
4 e il 5, del registro CCPxCON, per i bit meno significativi. Il valore si ottiene attraverso
la relazione:
Duty Cycle PWM = (CCPRxL : CCPxCON < 5 : 4 > )⋅ Tosc ⋅ (Valore del prescaler TMR2)
oppure più semplicemente da:
(CCPRxL : CCPxCON < 5 : 4 > ) = (Duty Cycle PWM )
Tosc ⋅ (Valore del prescaler TMR2 )

14
In questo caso il trmine Duty Cycle è usato erroneamente e si deve intendere come la durata in cui il segnale
rimane alto.

35
Introduzione Alla Programmazione Dei PIC16F876

F IG . 7 .4 .3 - F U N Z IO N E P W M

Le operazioni che la funzione PWM compie si possono così riassumere: quando il registro
TMR2 è uguale al registro PR2 la funzione identifica la fine di un periodo e annullando il registro
TMR2 dà origine al nuovo periodo. Nel nuovo periodo il pin CCPx è settato al livello alto per tutta
la durata del “duty cycle”. La durata del “duty cycle” è ottenuta comparando il registro CCPRxH
più due bit “accessori” con il timer2, quando si ha l’uguaglianza viene posto il pin al valore basso.
Ogni volta che si arriva alla fine del periodo viene ricaricato il registro CCPRxH più due bit
“accessori” dal registro CCPRxL:CCPxCON<5:4>. Si può quindi aggiornare il duty cycle in ogni
momento andando a cambiare il suo valore nel registro CCPRxL:CCPxCON<5:4>, però il suo
aggiornamento sarà visto nella forma d’onda di uscita solo al nuovo periodo. Durante la modalità
PWM il registro CCPRxH risulta essere di sola lettura.

Per inizializzare la modalità PWM si devono seguire queste operazioni:


- Settare il periodo della PWM nel registro PR2
- Settare il duty cycle della PWM nel registro CCPRxL:CCPxCON<5:4>.
- Settare il bit 1 o 2 di TRISC come uscita
- Scegliere il prescaler adeguato per il Timer2
- Configurare il modulo CCPx per eseguire la funzione PWM modificando i bit 0:3 del
registro CCPxCON

36
Introduzione Alla Programmazione Dei PIC16F876

Capitolo 8 Convertitore A/D

8.1. Premessa
Il PIC16F876 è internamente dotato di un convertitore A/D, che è classificato come una
periferica del PIC stesso. Qui abbiamo uno schema a blocchi del convertitore:

F IG . 8 .1 -1 – C O N V ER ITO R E A /D

Come possiamo notare il convertitore è unico mentre a monte di esso è presente un MUX
analogico necessario per settare gli ingressi analogici opportuni ( 5 ingressi per il PIC a 28 pin 8
ingressi per il PIC a 44 pin). Di default le tensioni di riferimento sono quelle di alimentazione (0-

37
Introduzione Alla Programmazione Dei PIC16F876

5V), ma con la possibilità di operare anche con riferimenti esterni Vref+ e Vref-15. I registri dove
viene letto il risultato della conversione sono ADRESH e ADRESL, mentre i registri che
permettono la configurazione del convertitore sono ADCON0, che controlla le operazioni del
modulo, e ADCON1, che permette la configurazioni delle porte in ingresso.

I registri associati al convertitore A/D sono riportati nella figura seguente::

F IG . 8 .1 -2

8.2. Funzionamento della periferica ADC


Il convertitore A/D è composto, internamente, da un sample&hold con in cascata un
convertitore ad approssimazioni successive, la cui risoluzione ottimale è di 10 bit. La capacità del
circuito sample&hold è di 120pF.(Nella figura seguente abbiamo lo schema di acquisizione)

F IG . 8 .2 -1

15
Che comunque devono essere sempre compresi tra 0 e 5 V.

38
Introduzione Alla Programmazione Dei PIC16F876

Affinché la conversione sia fatta correttamente bisogna attendere che la capacità venga
caricata fino al valore di tensione in ingresso. Questo tempo che si aggira intorno ai 20 µsec,
dipende sia dalla resistenza Rss del carico (meglio se <10K), sia dalla resistenza interna dello
switch elettronico (funzione della temperatura).
Una volta memorizzata analogicamente il valore di tensione può iniziare la conversione vera
e propria che richiede un tempo di circa Tad = 1.6 µsec per ogni bit di conversione (ossia 12Tad per
i 10 bit complessivi), questo tempo può assumere solo quattro valori: 2Tosc, 8Tosc, 32Tosc e
tempo dell’oscillatore RC interno (2 -6 µsec). Ne segue che Tosc, e quindi la massima frequenza del
clock del PIC, sia vincolato a valori precisi. Ecco qui visualizzato un ciclo di conversione:

F IG . 8 .2 -2

La conversione avviene settando il bit GO/DONE (si deve porlo ad 1, altrimenti se posto a 0
viene interrotta la conversione) dopodiché bisogna aspettare un tempo pari a 2Tad necessario per
l’acquisizione del valore analogico in ingresso all’ ADC.
I cinque ingressi analogici possono essere disponibili contemporaneamente o secondo
particolari combinazioni a seconda dei settagli del registro ADCON1.(Si veda l’Appendice F)
OSS: gli ingressi usati come analogici vanno settati come ingressi nel registro TRISA.

Come ulteriore chiarimento è disponibile uno schema a blocchi di principio di un


convertitore per approssimazioni successive:

F IG . 8 .2 -3

39
Introduzione Alla Programmazione Dei PIC16F876

8.3. Il risultato della conversione


I registri nei quali viene memorizzato il risultato, della conversione dei segnali analogici,
sono ADRESH e ADRESL: questi due registri sono in grado di memorizzare fino a 16 bit16, però il
dato al loro ingresso è di 10 bit. Per selezionare qual’è il registro da riempire e quale da lasciare
parzialmente riempito si deve settare il bit ADFM del registro ADCON1 che a secondo del valore
mi determinerà la modalità di scrittura nei due registri. L’operazione è esaurientemente riassunta
nella figura 8.3-1.

F IG . 8 .3 -1

Quando viene resettato il PIC il contenuto dei due registri del convertitore A/D ADRESL
ADRSH viene cancellato ed lo stesso convertitore viene forzato ad abortire la conversione.

8.4. La programmazione della conversione


Per ottenere la conversione A/D si devono seguire questi passi:
- Configurare il modulo A/D scegliendo i piedini da utilizzare come ingressi analogici, la
linea da convertire in quel momento, la frequenza di conversione e quindi accendere il
modulo di conversione (bit ADON di ADCON1)
- Configurare l’interrupt che segnala la fine della conversione, se serve
- Aspettare il tempo necessario per eseguire l’acquisizione del dato
- Iniziare la conversione ponendo a 1 il bit GO/DONE del registro ADCON0
- Aspettare che la conversione sia finita facendo un polling per aspettare che il bit
GO/DONE sia tornato 0 oppure aspettando l’interrupt
- Leggere il dato nel registro ADRESH:ADRESL
- Per una nuova conversione ripetere la sequenza e aspettare almeno 2TAD (che risulta
essere il tempo di conversione A/D per bit) prima di eseguire la nuova conversione

16
In realtà questi registri sono entrambi da 8 bit, però sono interpretati dal ADC come un unico registro da 16

40
Introduzione Alla Programmazione Dei PIC16F876

Capitolo 9 La memoria EEPROM

9.1. Premessa
La EEPROM DATI è una particolare area di memoria da 256 byte nella quale possiamo
scrivere i valori numerici che vogliamo che non vengano persi in caso di mancanza di tensione di
alimentazione.
La memoria EEPROM è scrivibile e leggibile in condizioni di normale alimentazione e
senza dover ricorrere ad alcun programmatore esterno. Le modalità di accesso sono notevolmente
diverse dalla memoria RAM dei REGISTER FILE e devono seguire una serie di procedure
particolari atte ad evitare eventuali perdite di dati in condizioni di funzionamento anomale.
Nota: Si può leggere e scrivere anche nella memoria FLASH in modo simile a come si fa
con la EEPROM. Per questo tipo di operazione si rimanda al datasheet a pag 41 e seguenti.

9.2. Registri speciali per l' accesso alla EEPROM dati


Per accedere alla EEPROM DATI vengono utilizzati i seguenti registri speciali:
EEADR (EEPROM Address) è il registro utilizzato per indirizzare una delle 256 locazioni
di memoria EEPROM in cui si desidera effettuare una lettura o scrittura di un dato.
EEDATA è il registro che viene usato per inviare un byte alla EEPROM in scrittura oppure
per ricevere un byte dalla EEPROM in lettura.
EECON1 ed EECON2 sono due registri ci controllo utilizzati nelle operazioni di lettura e
scrittura come descritto di seguito.

9.3. Scrittura di un dato su EEPROM


Vediamo ora come si può scrivere un dato su una locazione EEPROM. Ipotizziamo di voler
scrivere il valore decimale 10 nella locazione 0 della EEPROM dati.
La prima operazione da compiere è scrivere nel registro EEADR l' indirizzo della locazione
di memoria che intendiamo scrivere.
Dato che il registro EEADR e EEDATA sono nel banco 3 mentre EECON1 e EECON2 nel
banco 4, dovremo indirizzare portarci nel giusto banco prima di accedere al registri.
Possiamo usare per far questo le seguenti istruzioni:
banksel EEADR
movlw 0
movwf EEADR

41
Introduzione Alla Programmazione Dei PIC16F876

Nel registro EEDATA dobbiamo ora scrivere il valore che intendiamo inviare alla locazione
EEPROM indirizzata con il registro EEADR:
banksel EEDATA
movlw 10
movwf EEDATA
A questo punto dobbiamo settare il flag WREN (WRite ENable) contenuto nel registro di
controllo EECON1 per poter abilitare l' accesso alle successive operazioni di scrittura.
banksel EECON1
bsf EECON1,WREN ;Enable Write
Ora dobbiamo eseguire una sequenza di scritture sul registro EECON2 per comunicare al
PIC che abbiamo intenzione di scrivere sulla EEPROM. Questa sequenza rappresenta una specie di
codice di accesso alla EEPROM e serve ad evitare scritture accidentali in caso di funzionamento
anomalo del PIC dovuto a sbalzi di tensione, errori si programmazione. In pratica dobbiamo
scrivere i due valori esadecimali 55h e AAh in sequenza nel registro EECON2:
banksel EECON2
movlw 55h ;Write 55h to EECON2
movwf EECON2
movlw AAh ;Write AAh to EECON2
movwf EECON2
Arrivati a questo punto abbiamo effettuato tutte le operazioni preliminari per scrivere sulla
EEPROM e ci rimane solo di avviare la scrittura settando il flag WR (WRite) del registro EECON1
con l' istruzione:
bsf EECON1,WR ;Begin write
L' hardwaredel PIC impiega un certo tempo a partire da questo momento per programmare
la cella EEPROM con il valore da noi inviato. Quando l' operazione ha avuto termine, l' hardware del
PIC ci avverte azzerando nuovamente il flag WR del registri EECON1.
Se nel nostro programma decidiamo di aspettare che la cella sia stata programmata prima di
proseguire dovremo inserire il seguente loop di attesa:
WriteDoneLoop
btfsc EECON1,WR ;Writing done ?
goto WriteDoneLoop ;No, wait
... ;Yes, continue ..
Per evitare questa attesa è possibile richiedere all' hardware del PIC di generare un interrupt
di avvenuta programmazione.
Per scrivere un nuovo valore nella stessa cella EEPROM non è necessario effettuare
operazioni di cancellazioni della cella ma semplicemente ripetere le stesse operazioni di scrittura..

9.4. Lettura di un dato da EEPROM


Vediamo ora come si rilegge quello che abbiamo appena scritto sulla locazione di memoria
EEPROM.
Assicuriamoci anzitutto di essere tornati sul banco registri opportuno.
banksel EEADR
Quindi scriviamo in EEADR l' indirizzo di memoria che vogliamo leggere:
movlw 0
movwf EEADR
Comunichiamo all' hardware del PIC che intendiamo leggere la locazione di memoria
indirizzata da EEADR settando il flag RD (ReaD) del registro di controllo EECON1. Ricordiamoci,
però, di passare prima al banco registri dove si trova appunto il registro EECON1:
banksel EECON1
bsf EECON1,RD
A questo punto possiamo immediatamente leggere dal registro EEDATA il valore contenuto
nella locazione di memoria richiesta. Anche in questo caso dobbiamo però prima di tutto ricordarci
di passare al banco registri giusto:
banksel EEDATA
movf EEDATA,W
Nel registro accumulatore W, ora c' e' il dato letto dalla EEPROM.

42
Introduzione Alla Programmazione Dei PIC16F876

Capitolo 10 Comunicazione Seriale

10.1. Premessa
Gli standard di comunicazione seriale che possono essere usati col PIC 16F876 sono17:
• USART o SCI: Universal Synchronous Asynchronous Receiver Trasmitter
anche conosciuto col termine Serial Communications
Interface
• SSP: Synchronous Serial Port

In questo testo si considererà la sola comunicazione USART e in particolare la sola


trasmissione asincrona.
OSS: Se si vuole connettere il PIC ad una interfaccia RS23218 si deve usare l’integrato
MAX232 che si occupa di convertire i segnali RS232, di ±12V, ai segnali TTL, di 0÷5V, gestibili
direttamente dal PIC.

10.2. Comunicazione USART


I registri usati per la comunicazione USART sono il TXSTA e il RCSTA.
Quando la comunicazione seriale viene abilitata (bit SPEN di RCSTA) automaticamente
viene bypassato il registro TRISC per permettere ai pin RC6 e RC7 di essere usati rispettivamente
come Trasmettitore e Ricevitore.
Un ulteriore registro detto SPBRG è usato per decidere la velocità di comunicazione. In esso
viene posto un valore numerico relativo alla BAUD Rate della comunicazione: sul datasheet, pagg.
97 e 98 si trovano le relazioni necessarie per il calcolo del valore da inserire. A titolo di esempio
riportiamo che per una velocità di 9,6 kBAUD, disponendo di un oscillatore esterno a 20MHz, si
deve porre il valore decimale 129 nel registro SPBRG e si deve settare a 1 il bit BRGH del registro
TXSTA.

17
Si veda i capitoli 9 e 10 del datasheet del PIC
18
Interfaccia seriale standard usata dai PC. Si veda l’Appendice G dove sono riportate alcune informazioni
relative a questo standard.

43
Introduzione Alla Programmazione Dei PIC16F876

10.2.1. Trasmissione Asincrona


Il diagramma a blocchi che segue si riferisce alla struttura interna del trasmettitore USART.

F IG . 1 0 .2 -1

Si può vedere come il cuore del trasmettitore sia il registro a scorrimento TSR: questo
registro non è mappato in memoria e per poterlo alimentare si deve usare il registro TXREG.
Il funzionamento del registro TSR è regolato dal bit TXEN di TXSTA, infatti se questo bit
viene posto a uno si ha lo scorrimento del dato in TSR, mentre se viene posto a zero la trasmissione
s’interrompe e TSR viene cancellato.
Lo stato di TSR, cioè l’indicazione se il registro è pieno o è vuoto, è descritto nel bit TRMT
di TXSTA.

Se la trasmissione è abilitata e TSR è vuoto, il caricamento di un dato nel registro TXREG


provoca la ricopiatura dello stesso in TSR e, quindi, la sua immediata trasmissione.
Una volta ricopiato il dato in TSR, il registro TXREG risulta vuoto e questo evento viene
segnalato nel flag bit TXIF di PR1. Questa tipo di segnalazione permette, nell’eventualità, la
possibilità di generazione di un interrupt. Non appena si è accertato lo svuotamento di TXREG si
può provvedere al caricamento di un nuovo dato che sarà inviato appena il vecchio uscirà da TSR; il
caricamento del dato in TXREG riporta a zero automaticamente il bit TXIF.

44
Introduzione Alla Programmazione Dei PIC16F876

Capitolo 11 Algoritmi e Funzioni

11.1. Premessa
Questo capitolo vuole essere una raccolta di algoritmi e funzioni per sveltire e agevolare la
programmazione del PIC.

11.2. Ritardo software programmabile


Con la funzione sotto riportata si può generare un ritardo software programmabile agendo su
tre valori presenti in altrettanti registri. Questa funziona basa su sei registri:
VALUE_DELAY_0 DELAY_TEMPORANEO_0
VALUE_DELAY_1 DELAY_TEMPORANEO_1
VALUE_DELAY_2 DELAY_TEMPORANEO_2
;****************************************************************
; Routine di Delay
;
; Routine di ritardo programmabile agendo sui registri
; VALUE_DELAY_0
; VALUE_DELAY_1
; VALUE_DELAY_2
;
;****************************************************************
DELAY
banksel REGISTRO_TEST
btfsc REGISTRO_TEST, 0
return

movf VALUE_DELAY_0, W
movwf DELAY_TEMPORANEO_0

REDO0
movf VALUE_DELAY_1, W
movwf DELAY_TEMPORANEO_1

REDO1
movf VALUE_DELAY_2, W
movwf DELAY_TEMPORANEO_2

REDO2
NOP
decfsz DELAY_TEMPORANEO_2, F
goto REDO2
FINE_REDO2

decfsz DELAY_TEMPORANEO_1, F

45
Introduzione Alla Programmazione Dei PIC16F876

goto REDO1
FINE_REDO1

decfsz DELAY_TEMPORANEO_0, F
goto REDO0
FINE_REDO0

return

Per poter calcolare la giusta temporizzazione in secondi si deve usare la seguente formula:
VALUE _ DELAY _ 0 ⋅VALUE _ DELAY _ 1 ⋅VALUE _ DELAY _ 2
delay =
fosc / 20 − VALUE _ DELAY _ 0 ⋅VALUE _ DELAY _ 1 − VALUE _ DELAY _ 0 − 1

Nel caso in cui si usi un oscillatore alla frequenza di 20MHz si possono usare i seguenti
valori per i registri:
Tempo [sec] Frequenza [Hz] VALUE_DELAY_0 VALUE_DELAY_1 VALUE_DELAY_2
2 0,5 63 127 248
1 1 104 209 45
0,5 2,0 62 125 64
0,1 10,0 14 28 255
0,01 100,0 10 20 50
0,000104 9600,0 2 4 13

11.2.1. Funzioni di supporto alla funzione Delay

;****************************************************************
; DELAY_1sec
; Funzione di ritardo di supporto
;****************************************************************
DELAY_1sec
movlw 104
movwf VALUE_DELAY_0

movlw 209
movwf VALUE_DELAY_1

movlw 45
movwf VALUE_DELAY_2

goto DELAY

;****************************************************************
; DELAY_500msec
; Funzione di ritardo di supporto
;****************************************************************
DELAY_500msec
movlw 62
movwf VALUE_DELAY_0

movlw 125
movwf VALUE_DELAY_1

movlw 64
movwf VALUE_DELAY_2

goto DELAY

;****************************************************************
; DELAY_100msec
; Funzione di ritardo di supporto
;****************************************************************
DELAY_100msec
movlw 14
movwf VALUE_DELAY_0

movlw 28
movwf VALUE_DELAY_1

46
Introduzione Alla Programmazione Dei PIC16F876

movlw 255
movwf VALUE_DELAY_2

goto DELAY

;****************************************************************
; DELAY_10msec
; Funzione di ritardo di supporto
;****************************************************************
DELAY_10msec
movlw 10
movwf VALUE_DELAY_0

movlw 20
movwf VALUE_DELAY_1

movlw 50
movwf VALUE_DELAY_2

goto DELAY

11.3. Uso del Display LED a 7 segmenti


Nel caso si voglia connettere un display LED a 7 segmenti sono riportate delle costanti e
delle funzioni che possono aiutare la sua gestione. Nel seguito si fa riferimento ad un display ad
anodo comune (logica invertita) e si considera che i bit delle costanti siano messi in modo che il led
a sia individuato dal bit meno significativo e il led p (il punto) da quello più significativo.

F IG . 1 1 .3 -1 – D IS PL AY L E D A 7 S EG M E TI AD AN O D O C O M U N E

11.3.1. Le costanti

;Segmenti del display

_DISPLAY_SPENTO EQU B'11111111'

_DISPLAY_SEGMENTO_a EQU B'11111110'


_DISPLAY_SEGMENTO_b EQU B'11111101'
_DISPLAY_SEGMENTO_c EQU B'11111011'
_DISPLAY_SEGMENTO_d EQU B'11110111'
_DISPLAY_SEGMENTO_e EQU B'11101111'
_DISPLAY_SEGMENTO_f EQU B'11011111'
_DISPLAY_SEGMENTO_g EQU B'10111111'

47
Introduzione Alla Programmazione Dei PIC16F876

_DISPLAY_SEGMENTO_punto EQU B'01111111'

;Numeri per Display led a 7 segmenti

_DISPLAY_LED_NUM_0 EQU B'11000000'


_DISPLAY_LED_NUM_1 EQU B'11111001'
_DISPLAY_LED_NUM_2 EQU B'10100100'
_DISPLAY_LED_NUM_3 EQU B'10110000'
_DISPLAY_LED_NUM_4 EQU B'10011001'
_DISPLAY_LED_NUM_5 EQU B'10010010'
_DISPLAY_LED_NUM_6 EQU B'10000010'
_DISPLAY_LED_NUM_7 EQU B'11111000'
_DISPLAY_LED_NUM_8 EQU B'10000000'
_DISPLAY_LED_NUM_9 EQU B'10010000'

;Caratteri per Display a 7 segmenti

_DISPLAY_LED_CHAR_A EQU B'10001000'


_DISPLAY_LED_CHAR_C EQU B'11000110'
_DISPLAY_LED_CHAR_E EQU B'10000110'
_DISPLAY_LED_CHAR_I EQU B'11001111'
_DISPLAY_LED_CHAR_O EQU B'11000000'
_DISPLAY_LED_CHAR_S EQU B'10010010'
_DISPLAY_LED_CHAR_t EQU B'11001110'

11.3.2. Aggiornare il display


Se si connettesse il display direttamente alla Porta B, si potrebbe usare la funzione seguente,
che però può essere facilmente convertita per qualsiasi altra configurazione. Per questa funzione è
necessario definire una locazione di memoria detta CHAR_TO_DISPLAY.

;*****************************************************************************
; Funzione che aggiorna il display col carattere contenuto in CHAR_TO_DISPLAY
;
;*****************************************************************************

AGGIORNA_DISPLAY

movf CHAR_TO_DISPLAY, W
movwf PORTB

return

11.3.3. Visualizzare una parola sul display

;**********************************************************************
; Funzione che visualizza la parola CIAO
;**********************************************************************

FUNZIONE_CIAO

movlw _DISPLAY_SPENTO
movwf CHAR_TO_DISPLAY
call AGGIORNA_DISPLAY

call DELAY_500msec

movlw _DISPLAY_LED_CHAR_C
movwf CHAR_TO_DISPLAY
call AGGIORNA_DISPLAY

call DELAY_500msec

movlw _DISPLAY_LED_CHAR_I

48
Introduzione Alla Programmazione Dei PIC16F876

movwf CHAR_TO_DISPLAY
call AGGIORNA_DISPLAY

call DELAY_500msec

movlw _DISPLAY_LED_CHAR_A
movwf CHAR_TO_DISPLAY
call AGGIORNA_DISPLAY

call DELAY_500msec

movlw _DISPLAY_LED_CHAR_O
movwf CHAR_TO_DISPLAY
call AGGIORNA_DISPLAY

call DELAY_500msec

movlw _DISPLAY_SPENTO
movwf CHAR_TO_DISPLAY
call AGGIORNA_DISPLAY

return

11.3.4. Convertire numero decimale per visualizzarlo sul display

;**************************************************************************
; Converti Numero decimale binario in un numero decimale per display
;**************************************************************************

CONVERTI_NUM_CHAR_DISPLAY

bcf STATUS, Z

movf CHAR_TO_DISPLAY, W
sublw 0
btfsc STATUS, Z
goto CHAR_DISPLAY_0

movf CHAR_TO_DISPLAY, W
sublw 1
btfsc STATUS, Z
goto CHAR_DISPLAY_1

movf CHAR_TO_DISPLAY, W
sublw 2
btfsc STATUS, Z
goto CHAR_DISPLAY_2

movf CHAR_TO_DISPLAY, W
sublw 3
btfsc STATUS, Z
goto CHAR_DISPLAY_3

movf CHAR_TO_DISPLAY, W
sublw 4
btfsc STATUS, Z
goto CHAR_DISPLAY_4

movf CHAR_TO_DISPLAY, W
sublw 5
btfsc STATUS, Z
goto CHAR_DISPLAY_5

movf CHAR_TO_DISPLAY, W
sublw 6
btfsc STATUS, Z
goto CHAR_DISPLAY_6

movf CHAR_TO_DISPLAY, W
sublw 7
btfsc STATUS, Z
goto CHAR_DISPLAY_7

49
Introduzione Alla Programmazione Dei PIC16F876

movf CHAR_TO_DISPLAY, W
sublw 8
btfsc STATUS, Z
goto CHAR_DISPLAY_8

movf CHAR_TO_DISPLAY, W
sublw 9
btfsc STATUS, Z
goto CHAR_DISPLAY_9

;Se non è un numero decimale accende il led g


movlw _DISPLAY_SEGMENTO_g
movwf CHAR_TO_DISPLAY
return

CHAR_DISPLAY_9
movlw _DISPLAY_LED_NUM_9
movwf CHAR_TO_DISPLAY
return

CHAR_DISPLAY_8
movlw _DISPLAY_LED_NUM_8
movwf CHAR_TO_DISPLAY
return

CHAR_DISPLAY_7
movlw _DISPLAY_LED_NUM_7
movwf CHAR_TO_DISPLAY
return

CHAR_DISPLAY_6
movlw _DISPLAY_LED_NUM_6
movwf CHAR_TO_DISPLAY
return

CHAR_DISPLAY_5
movlw _DISPLAY_LED_NUM_5
movwf CHAR_TO_DISPLAY
return

CHAR_DISPLAY_4
movlw _DISPLAY_LED_NUM_4
movwf CHAR_TO_DISPLAY
return

CHAR_DISPLAY_3
movlw _DISPLAY_LED_NUM_3
movwf CHAR_TO_DISPLAY
return

CHAR_DISPLAY_2
movlw _DISPLAY_LED_NUM_2
movwf CHAR_TO_DISPLAY
return

CHAR_DISPLAY_1
movlw _DISPLAY_LED_NUM_1
movwf CHAR_TO_DISPLAY
return

CHAR_DISPLAY_0
movlw _DISPLAY_LED_NUM_0
movwf CHAR_TO_DISPLAY
return

11.4. Algoritmi di somma


Per questi algoritmi si considera il formato numerico binario senza segno.

50
Introduzione Alla Programmazione Dei PIC16F876

11.4.1. Somma di due registri a 8 bit


Questa funzione tiene conto del riporto. I registri usati sono:
PRIMO_ADDENDO RIPORTO
SECONDO_ADDENDO
;****************************************************************
; Somma 8 bit
;
;
; PRIMO_ADDENDO OOOO
; SECONDO_ADDENDO OOOO
; ----
; RISULTATO_SOMMA OOOO
;
; RIPORTO OOOO
;
;****************************************************************
SOMMA_8bit

banksel RIPORTO
movf RIPORTO, W
bcf RIPORTO, 0
bcf STATUS, C
addwf PRIMO_ADDENDO, W

btfss STATUS, C
goto SOMMA_SENZA_RIPORTO
bsf RIPORTO, 0 ;C'è il riporto
;quindi sicuramente non c'è ora!

addwf SECONDO_ADDENDO, W
movwf RISULTATO_SOMMA

return

SOMMA_SENZA_RIPORTO
addwf SECONDO_ADDENDO, W
btfsc STATUS, C
bsf RIPORTO, 0 ;ora c'è il riporto!

movwf RISULTATO_SOMMA

return

11.4.2. Somma di due numeri di 3 Byte


Questa funzione tiene conto del riporto. I registri usati sono:
ADDENDO1_3B_T ADDENDO1_3B_S ADDENDO1_3B_F
ADDENDO2_3B_T ADDENDO2_3B_S ADDENDO2_3B_F
RISULTATO_3B_T RISULTATO _3B_S RISULTATO _3B_F

RIPORTO

;****************************************************************
; Somma 3 Byte
;
; T S F
; ADDENDO1_3B OOOO OOOO OOOO
; ADDENDO2_3B OOOO OOOO OOOO
; --------------
; RISULTATO_3B OOOO OOOO OOOO
;

51
Introduzione Alla Programmazione Dei PIC16F876

; RIPORTO OOOO
;
;****************************************************************
SOMMA_3BYTE

movf ADDENDO1_3B_F, W
movwf PRIMO_ADDENDO
movf ADDENDO2_3B_F, W
movwf SECONDO_ADDENDO
call SOMMA_8bit
movf RISULTATO_SOMMA, W
movwf RISULTATO_3B_F

movf ADDENDO1_3B_S, W
movwf PRIMO_ADDENDO
movf ADDENDO2_3B_S, W
movwf SECONDO_ADDENDO
call SOMMA_8bit
movf RISULTATO_SOMMA, W
movwf RISULTATO_3B_S

movf ADDENDO1_3B_T, W
movwf PRIMO_ADDENDO
movf ADDENDO2_3B_T, W
movwf SECONDO_ADDENDO
call SOMMA_8bit
movf RISULTATO_SOMMA, W
movwf RISULTATO_3B_T

return

11.5. Algoritmi di prodotto e di divisione


Per questi algoritmi si considera il formato numerico binario senza segno.

11.5.1. Prodotto di due numeri da 2 Byte


I registri usati sono:
NUMERO1_H NUMERO2_L
NUMERO2_H NUMERO2_L

RISULT_MOLT_3 RISULT_MOLT_2 RISULT_MOLT_1 RISULT_MOLT_0


TEMP_REG_4B_3 TEMP_REG_4B_2 TEMP_REG_4B_1 TEMP_REG_4B_0

ITERAZIONI

;****************************************************************
; Moltiplica due numeri da 2 BYTE
;
;
; H L
; NUMERO1 0000 0000
; NUMER02 0000 0000
;
; 3 2 1 0
; RISULT_MOLT 0000 0000 0000 0000
;
; TEMP_REG_4B 0000 0000 0000 0000
;
;****************************************************************
MOLTIPLICA_2B_2B
clrf RISULT_MOLT_0
clrf RISULT_MOLT_1
clrf RISULT_MOLT_2
clrf RISULT_MOLT_3

52
Introduzione Alla Programmazione Dei PIC16F876

clrf TEMP_REG_4B_0
clrf TEMP_REG_4B_1
clrf TEMP_REG_4B_2
clrf TEMP_REG_4B_3

movf NUMERO1_L, W
movwf TEMP_REG_4B_0
movf NUMERO1_H, W
movwf TEMP_REG_4B_1

movlw 16
movwf ITERAZIONI

LOOP_ITERAZIONI
bcf STATUS, C
rrf NUMERO2_H, F
rrf NUMERO2_L, F

btfss STATUS, C ;Salta se c'è un uno


goto TROVATO_ZERO

; Somma RISULT_MOLT + TEMP_REG_4B =RISULT_MOLT


;
clrf RIPORTO
movf RISULT_MOLT_0, W
movwf PRIMO_ADDENDO
movf TEMP_REG_4B_0, W
movwf SECONDO_ADDENDO

call SOMMA_8bit
movf RISULTATO_SOMMA, W
movwf RISULT_MOLT_0

movf RISULT_MOLT_1, W
movwf PRIMO_ADDENDO
movf TEMP_REG_4B_1, W
movwf SECONDO_ADDENDO

call SOMMA_8bit
movf RISULTATO_SOMMA, W
movwf RISULT_MOLT_1

movf RISULT_MOLT_2, W
movwf PRIMO_ADDENDO
movf TEMP_REG_4B_2, W
movwf SECONDO_ADDENDO

call SOMMA_8bit
movf RISULTATO_SOMMA, W
movwf RISULT_MOLT_2

movf RISULT_MOLT_3, W
movwf PRIMO_ADDENDO
movf TEMP_REG_4B_3, W
movwf SECONDO_ADDENDO

call SOMMA_8bit
movf RISULTATO_SOMMA, W
movwf RISULT_MOLT_3

TROVATO_ZERO
nop

bcf STATUS, C
rlf TEMP_REG_4B_0, F
rlf TEMP_REG_4B_1, F
rlf TEMP_REG_4B_2, F
rlf TEMP_REG_4B_3, F

decfsz ITERAZIONI, F
goto LOOP_ITERAZIONI

return

53
Introduzione Alla Programmazione Dei PIC16F876

11.5.2. Divisione di un numero di 2 Byte per dieci


Funzione molto utile nel caso si voglia rendere decimale un numero binario (per esempio
per poterlo visualizzare sul display!!).
La funzione può essere semplicemente convertita in una divisione per qualsiasi numero
andando a variare la costante che viene inserita in SOTTRATTORE e in ITERAZIONI. I registri
usati sono:
DIVIDENDO_H DIVIDENDO_L
SOTTRATTORE_H SOTTRATTORE_L
RESTO_H RESTO_L
RISULTATO_DIV_H RISULTATO_DIV_L

ITERAZIONI

;****************************************************************
; Dividi per Dieci
;
; |
; DIVIDENDO | 10
; ---------------------
; SOTTRATTORE | RISULTATO_DIV
; |
; RESTO |
;
; H L
; DIVIDENDO 0000 0000
; SOTTRATTORE 0000 0000
; RESTO 0000 0000
; RISULTATO_DIV 0000 0000
;
;
;****************************************************************
DIVIDI_PER_DIECI

banksel SOTTRATTORE_H

clrf SOTTRATTORE_H
clrf SOTTRATTORE_L
clrf RISULTATO_DIV_H
clrf RISULTATO_DIV_L

movlw B'10100000'
movwf SOTTRATTORE_H

movlw 13
movwf ITERAZIONI

LOOP_DIVIDI
clrf RESTO_H
clrf RESTO_L

bcf STATUS, C
movf SOTTRATTORE_L, W
subwF DIVIDENDO_L, W
movwf RESTO_L
btfsc STATUS, C ; Se c'è riporto salta
goto NON_C_E_RIPORTO
; C'è riporto
movf DIVIDENDO_H, F
btfsc STATUS, Z ; Se il sottrattore è zero allora il numero è minore
goto ZERO_TO_RISULTATO ;DIVIDENDO < SOTTRATTORE
decf DIVIDENDO_H, F ;C'è il riporto

NON_C_E_RIPORTO
movf SOTTRATTORE_H, W
subwF DIVIDENDO_H, W
movwf RESTO_H

btfss STATUS, C ; Se non c'è riporto salta l'istruzione successiva


goto ZERO_TO_RISULTATO ;DIVIDENDO < SOTTRATTORE

54
Introduzione Alla Programmazione Dei PIC16F876

goto UNO_TO_RISULTATO ;DIVIDENDO >= SOTTRATTORE - NON C'è RIPORTO!!!

ZERO_TO_RISULTATO ; C'è riporto


bcf STATUS, C
rlf RISULTATO_DIV_L, F
rlf RISULTATO_DIV_H, F
goto FINE_DIVIDI

UNO_TO_RISULTATO ; Non c'è riporto


movf RESTO_H, W
movwf DIVIDENDO_H
movf RESTO_L, W
movwf DIVIDENDO_L

bsf STATUS, C
rlf RISULTATO_DIV_L, F
rlf RISULTATO_DIV_H, F
goto FINE_DIVIDI

FINE_DIVIDI
bcf STATUS, C
rrf SOTTRATTORE_H, F
rrf SOTTRATTORE_L, F

decfsz ITERAZIONI, F
goto LOOP_DIVIDI

movf DIVIDENDO_L, W ; Il resto che si è generato è in DIVIDENDO_L


movwf RESTO_L ; ora è in RESTO_L

return

55
Appendice A

Appendice A

P 1 6 F 8 7 6 .IN C
LIST
; P16F876.INC Standard Header File, Version 1.00 Microchip Technology, Inc.
NOLIST

; This header file defines configurations, registers, and other useful bits of
; information for the PIC16F876 microcontroller. These names are taken to match
; the data sheets as closely as possible.

; Note that the processor must be selected before this file is


; included. The processor may be selected the following ways:

; 1. Command line switch:


; C:\ MPASM MYFILE.ASM /PIC16F876
; 2. LIST directive in the source file
; LIST P=PIC16F876
; 3. Processor Type entry in the MPASM full-screen interface

;==========================================================================
;
; Revision History
;
;==========================================================================

;Rev: Date: Reason:

;1.12 01/12/00 Changed some bit names, a register name, configuration bits
; to match datasheet (DS30292B)
;1.00 08/07/98 Initial Release

;==========================================================================
;
; Verify Processor
;
;==========================================================================

IFNDEF __16F876
MESSG "Processor-header file mismatch. Verify selected processor."
ENDIF

;==========================================================================
;
; Register Definitions
;
;==========================================================================

W EQU H'0000'
F EQU H'0001'

;----- Register Files------------------------------------------------------

INDF EQU H'0000'


TMR0 EQU H'0001'
PCL EQU H'0002'
STATUS EQU H'0003'
FSR EQU H'0004'
PORTA EQU H'0005'
PORTB EQU H'0006'
PORTC EQU H'0007'

PCLATH EQU H'000A'


INTCON EQU H'000B'
PIR1 EQU H'000C'
PIR2 EQU H'000D'
TMR1L EQU H'000E'
TMR1H EQU H'000F'
T1CON EQU H'0010'
TMR2 EQU H'0011'
T2CON EQU H'0012'
SSPBUF EQU H'0013'
SSPCON EQU H'0014'
CCPR1L EQU H'0015'
CCPR1H EQU H'0016'

56
Appendice A

CCP1CON EQU H'0017'


RCSTA EQU H'0018'
TXREG EQU H'0019'
RCREG EQU H'001A'
CCPR2L EQU H'001B'
CCPR2H EQU H'001C'
CCP2CON EQU H'001D'
ADRESH EQU H'001E'
ADCON0 EQU H'001F'

OPTION_REG EQU H'0081'


TRISA EQU H'0085'
TRISB EQU H'0086'
TRISC EQU H'0087'
PIE1 EQU H'008C'
PIE2 EQU H'008D'
PCON EQU H'008E'
SSPCON2 EQU H'0091'
PR2 EQU H'0092'
SSPADD EQU H'0093'
SSPSTAT EQU H'0094'
TXSTA EQU H'0098'
SPBRG EQU H'0099'
ADRESL EQU H'009E'
ADCON1 EQU H'009F'

EEDATA EQU H'010C'


EEADR EQU H'010D'
EEDATH EQU H'010E'
EEADRH EQU H'010F'

EECON1 EQU H'018C'


EECON2 EQU H'018D'

;----- STATUS Bits --------------------------------------------------------

IRP EQU H'0007'


RP1 EQU H'0006'
RP0 EQU H'0005'
NOT_TO EQU H'0004'
NOT_PD EQU H'0003'
Z EQU H'0002'
DC EQU H'0001'
C EQU H'0000'

;----- INTCON Bits --------------------------------------------------------

GIE EQU H'0007'


PEIE EQU H'0006'
T0IE EQU H'0005'
INTE EQU H'0004'
RBIE EQU H'0003'
T0IF EQU H'0002'
INTF EQU H'0001'
RBIF EQU H'0000'

;----- PIR1 Bits ----------------------------------------------------------

ADIF EQU H'0006'


RCIF EQU H'0005'
TXIF EQU H'0004'
SSPIF EQU H'0003'
CCP1IF EQU H'0002'
TMR2IF EQU H'0001'
TMR1IF EQU H'0000'

;----- PIR2 Bits ----------------------------------------------------------

EEIF EQU H'0004'


BCLIF EQU H'0003'
CCP2IF EQU H'0000'

;----- T1CON Bits ---------------------------------------------------------

T1CKPS1 EQU H'0005'


T1CKPS0 EQU H'0004'
T1OSCEN EQU H'0003'
NOT_T1SYNC EQU H'0002'

57
Appendice A

T1INSYNC EQU H'0002' ; Backward compatibility only


T1SYNC EQU H'0002'
TMR1CS EQU H'0001'
TMR1ON EQU H'0000'

;----- T2CON Bits ---------------------------------------------------------

TOUTPS3 EQU H'0006'


TOUTPS2 EQU H'0005'
TOUTPS1 EQU H'0004'
TOUTPS0 EQU H'0003'
TMR2ON EQU H'0002'
T2CKPS1 EQU H'0001'
T2CKPS0 EQU H'0000'

;----- SSPCON Bits --------------------------------------------------------

WCOL EQU H'0007'


SSPOV EQU H'0006'
SSPEN EQU H'0005'
CKP EQU H'0004'
SSPM3 EQU H'0003'
SSPM2 EQU H'0002'
SSPM1 EQU H'0001'
SSPM0 EQU H'0000'

;----- CCP1CON Bits -------------------------------------------------------

CCP1X EQU H'0005'


CCP1Y EQU H'0004'
CCP1M3 EQU H'0003'
CCP1M2 EQU H'0002'
CCP1M1 EQU H'0001'
CCP1M0 EQU H'0000'

;----- RCSTA Bits ---------------------------------------------------------

SPEN EQU H'0007'


RX9 EQU H'0006'
RC9 EQU H'0006' ; Backward compatibility only
NOT_RC8 EQU H'0006' ; Backward compatibility only
RC8_9 EQU H'0006' ; Backward compatibility only
SREN EQU H'0005'
CREN EQU H'0004'
ADDEN EQU H'0003'
FERR EQU H'0002'
OERR EQU H'0001'
RX9D EQU H'0000'
RCD8 EQU H'0000' ; Backward compatibility only

;----- CCP2CON Bits -------------------------------------------------------

CCP2X EQU H'0005'


CCP2Y EQU H'0004'
CCP2M3 EQU H'0003'
CCP2M2 EQU H'0002'
CCP2M1 EQU H'0001'
CCP2M0 EQU H'0000'

;----- ADCON0 Bits --------------------------------------------------------

ADCS1 EQU H'0007'


ADCS0 EQU H'0006'
CHS2 EQU H'0005'
CHS1 EQU H'0004'
CHS0 EQU H'0003'
GO EQU H'0002'
NOT_DONE EQU H'0002'
GO_DONE EQU H'0002'
ADON EQU H'0000'

;----- OPTION_REG Bits ----------------------------------------------------

NOT_RBPU EQU H'0007'


INTEDG EQU H'0006'
T0CS EQU H'0005'
T0SE EQU H'0004'
PSA EQU H'0003'

58
Appendice A

PS2 EQU H'0002'


PS1 EQU H'0001'
PS0 EQU H'0000'

;----- PIE1 Bits ----------------------------------------------------------

ADIE EQU H'0006'


RCIE EQU H'0005'
TXIE EQU H'0004'
SSPIE EQU H'0003'
CCP1IE EQU H'0002'
TMR2IE EQU H'0001'
TMR1IE EQU H'0000'

;----- PIE2 Bits ----------------------------------------------------------

EEIE EQU H'0004'


BCLIE EQU H'0003'
CCP2IE EQU H'0000'

;----- PCON Bits ----------------------------------------------------------

NOT_POR EQU H'0001'


NOT_BO EQU H'0000'
NOT_BOR EQU H'0000'

;----- SSPCON2 Bits --------------------------------------------------------

GCEN EQU H'0007'


ACKSTAT EQU H'0006'
ACKDT EQU H'0005'
ACKEN EQU H'0004'
RCEN EQU H'0003'
PEN EQU H'0002'
RSEN EQU H'0001'
SEN EQU H'0000'

;----- SSPSTAT Bits -------------------------------------------------------

SMP EQU H'0007'


CKE EQU H'0006'
D EQU H'0005'
I2C_DATA EQU H'0005'
NOT_A EQU H'0005'
NOT_ADDRESS EQU H'0005'
D_A EQU H'0005'
DATA_ADDRESS EQU H'0005'
P EQU H'0004'
I2C_STOP EQU H'0004'
S EQU H'0003'
I2C_START EQU H'0003'
R EQU H'0002'
I2C_READ EQU H'0002'
NOT_W EQU H'0002'
NOT_WRITE EQU H'0002'
R_W EQU H'0002'
READ_WRITE EQU H'0002'
UA EQU H'0001'
BF EQU H'0000'

;----- TXSTA Bits ---------------------------------------------------------

CSRC EQU H'0007'


TX9 EQU H'0006'
NOT_TX8 EQU H'0006' ; Backward compatibility only
TX8_9 EQU H'0006' ; Backward compatibility only
TXEN EQU H'0005'
SYNC EQU H'0004'
BRGH EQU H'0002'
TRMT EQU H'0001'
TX9D EQU H'0000'
TXD8 EQU H'0000' ; Backward compatibility only

;----- ADCON1 Bits --------------------------------------------------------

ADFM EQU H'0007'


PCFG3 EQU H'0003'
PCFG2 EQU H'0002'

59
Appendice A

PCFG1 EQU H'0001'


PCFG0 EQU H'0000'

;----- EECON1 Bits --------------------------------------------------------

EEPGD EQU H'0007'


WRERR EQU H'0003'
WREN EQU H'0002'
WR EQU H'0001'
RD EQU H'0000'

;==========================================================================
;
; RAM Definition
;
;==========================================================================

__MAXRAM H'1FF'
__BADRAM H'08'-H'09'
__BADRAM H'88'-H'89', H'8F'-H'90', H'95'-H'97', H'9A'-H'9D'
__BADRAM H'105', H'107'-H'109'
__BADRAM H'185', H'187'-H'189', H'18E'-H'18F'

;==========================================================================
;
; Configuration Bits
;
;==========================================================================

_CP_ALL EQU H'0FCF'


_CP_HALF EQU H'1FDF'
_CP_UPPER_256 EQU H'2FEF'
_CP_OFF EQU H'3FFF'
_DEBUG_ON EQU H'37FF'
_DEBUG_OFF EQU H'3FFF'
_WRT_ENABLE_ON EQU H'3FFF'
_WRT_ENABLE_OFF EQU H'3DFF'
_CPD_ON EQU H'3EFF'
_CPD_OFF EQU H'3FFF'
_LVP_ON EQU H'3FFF'
_LVP_OFF EQU H'3F7F'
_BODEN_ON EQU H'3FFF'
_BODEN_OFF EQU H'3FBF'
_PWRTE_OFF EQU H'3FFF'
_PWRTE_ON EQU H'3FF7'
_WDT_ON EQU H'3FFF'
_WDT_OFF EQU H'3FFB'
_LP_OSC EQU H'3FFC'
_XT_OSC EQU H'3FFD'
_HS_OSC EQU H'3FFE'
_RC_OSC EQU H'3FFF'

LIST

60
Appendice B

Appendice B

O P E R A T O R I L O G IC I E M A T E M A T IC I

61
Appendice C

Appendice C

C O N F IG U R A T IO N W O R D

62
Appendice D

Appendice D

S T R U T T U R A D E L L A R A M - F IL E R E G IS T E R S

63
Appendice D

R E G IS T R O D I S T A TO – S T A TU S R E G IS T E R

64
Appendice E

Appendice E

S E T D I I S T R U Z IO N I P E R I P IC

OSS: La descrizione approfondita delle singole istruzioni a pag. 139 del datasheet del PIC16F87x

65
Appendice F

Appendice F

A D C O N 0 R E G IS T E R

66
Appendice F

A D C O N 1 R E G IS T E R

67
Appendice G

Appendice G

S TA N D A R D R S 2 3 2

Cos' é e a cosa serve l' RS232


Lo standard RS232 definisce una serie di specifiche per la trasmissione seriale di dati tra due dispositivi
denominati DTE (Data Terminal Equipment) e DCE (Data Communication Equipment). Come si può vagamente intuire
dal nome, il Data Communication Equipment è un dispositivo che si occupa di gestire una comunicazione dati mentre il
Data Terminal Equipment è un dispositivo che si occupa di generare o ricevere dati.
In pratica l' RS232 è stata creata per connettere tra loro un terminale dati (nel nostro caso un computer) con un
modem per la trasmissione a distanza dei dati generati.
Per avere una connessione tra due computer è quindi necessario disporre di quattro dispositivi come visibile in
figura: un computer (DTE) collegato al suo modem (DCE) ed un altro modem (DCE) collegato al suo computer (DTE).
In questo modo qualsiasi dato generato dal primo computer e trasmesso tramite RS232 al relativo modem verrà
trasmesso da questo al modem remoto che a sua volta provvederà ad inviarlo al suo computer tramite RS232. Lo stesso
vale per il percorso a ritroso.

Per usare la RS232 per collegare tra loro due computer vicini senza interporre tra loro alcun modem dobbiamo
simulare in qualche modo le connessioni intermedie realizzando un cavo NULL MODEM o cavo invertente, ovvero un
cavo in grado di far scambiare direttamente tra loro i segnali dai due DTE come se tra loro ci fossero effettivamente i
DCE.

La comunicazione seriale asincrona


Per consentire la trasmissione di dati tra il PC ed il modem, lo standard RS232 definisce una serie di specifiche
elettriche e meccaniche. Una di queste riguarda il tipo di comunicazione seriale che si vuole implementare che può
essere sincrona o asincrona.
Nel nostro caso analizzeremo solo la comunicazione seriale asincrona ignorando completamente quella
sincrona in quanto più complessa e non disponibile sui normali PC.
Una comunicazione seriale consiste in genere nella trasmissione e ricezione di dati da un punto ad un altro
usando una sola linea elettrica. In pratica se desideriamo trasmettere un intero byte dobbiamo prendere ogni singolo bit
in esso contenuto ed inviarlo in sequenza sulla stessa linea elettrica.
Facciamo subito un esempio pratico e vediamo come fa un PC a trasmettere, ad esempio, il carattere A usando
la RS232.
Se prendiamo una coppia di fili e colleghiamo tra loro le porte seriali di due PC (che denomineremo PC
trasmittente e PC ricevente) secondo lo schema riportato in figura otterremo la più semplice delle connessioni in RS232.

La linea Transmit Data (TXD) presente sul pin 3 del connettore DB9 maschio di cui il vostro PC è dotato è
connessa alla linea Receive Data (RXD) presente sul pin 2 del secondo PC. Le masse (GND) presenti sul pin 5 di
entrambe i PC sono connesse tra loro.
Per osservare i segnali generati dal PC trasmittente durante la trasmissione seriale colleghiamo tra la linea
TXD e la linea GND un oscilloscopio e lanciamo in esecuzione su entrambe i PC un programma di emulazione
terminale (tipo Hyperterminal o simili).

68
Appendice G

Configuriamo le porte seriali di entrambe i PC a 9600 baud, 8 data bit, 1 stop bit, no parity e disabilitiamo il
controllo di flusso (handshake) sia hardware che xon/xoff. In questo stato qualsiasi cosa digiteremo sul PC trasmittente
verrà inviata immediatamente sulla porta seriale. Assicuriamoci inoltre che il programma di emulazione terminale scelto
sia opportunamente configurato per usare la porta seriale su cui siamo connessi (COM1 o COM2).
Proviamo a digitare la lettera A maiuscola e verifichiamo se è stata correttamente ricevuta sul PC ricevente.
Fatto questo controllo andiamo a vedere sull' oscilloscopio che tipo di segnali sono stati generati per effettuare la
trasmissione.
Quando non c' é nessuna trasmissione in corso la tensione sulla linea TXD è di -12 volt corrispondente alla
condizione logica 1.Per indicare al PC ricevente che la trasmissione ha inizio, il PC trasmittente porta a +12 volt la linea
TXD per un tempo pari all' inverso della frequenza di trasmissione ovvero al tempo di trasmissione di un singolo bit.
Nel nostro caso, avendo scelto di trasmettere a 9600 bit per secondo, la tensione di alimentazione rimarà a +12
volt per: 1/9600=0.104 mS.
Questo segnale viene denominato START BIT ed è sempre presente all' inizio di trasmissione di ogni singolo
byte. Dopo lo start bit vengono trasmessi in sequenza gli otto bit componenti il codice ASCII del carattere trasmesso
partendo dal bit meno significativo. Nel nostro caso la lettera A maiuscola corrisponde al valore binario 01000001 per
cui la sequenza di trasmissione sarà la seguente:

Una volta trasmesso l' ottavo bit (bit 7), il PC aggiunge automaticamente un ultimo bit a 1 denominato STOP
BIT ad indicare l' avvenuta trasmissione dell' intero byte. La stessa sequenza viene ripetuta per ogni byte trasmesso sulla
linea.
Aggiungendo al nostro cavo seriale una connessione tra il pin TXD (pin 3) del PC ricevente con il pin RXD
(pin 2) del PC trasmittente, potremo effettuare una trasmissione RS232 bidirezionale. Il cavo che abbiamo ottenuto è il
più semplice cavo NULL MODEM in grado di mettere in collegamento tra loro due DTE.

Funzionamento del MAX232


Il driver MAX232 è un integrato in grado di convertire i segnali a ± 12 volt tipici della RS232 in segnali a 0÷5
volt gestibili dalle porte del PIC. Nel caso in cui si trasmetta il valore binario 01000001 si avrà ai capi dell’integrato:

69
Indice Analitico

Indice Analitico

A F
ADC........................... Vedi Convertitore A/D File Registers..............................................61
assembly, linguaggio ....................................1 FILE1.ASM..................................................3
file2.asm.....................................................11
B file3.asm.....................................................18
banchi di memoria ........................................6 FLAG BIT..................................................20
Banchi di memoria, Abilitare i......................8 frequenza del clock interno .........................13
banksel .......................................................10 frequenza dell’oscillatore e sterno................13
BCF..............................................................9 frequenza di oscillazione ..............................2
BSF ..............................................................8
G
C General Purpose Register..............................6
goto ...............................................................9
C bit.............................................................7
GOTO ...............................................................9
call ...............................................................9
CALL ...............................................................9
Capture.......................................................20 H
CCP............................................................20 HS ..............................................................13
clock, sorgente esterna................................14
Compare.....................................................20 I
Comunicazione Seriale ...............................20 include ..........................................................5
CONFIG......................................................5; 14
INTCON ....................................................20
Configuration Word................................5; 60 interrupt......................................................15
contatori ti tempo e di eventi.......................20 Interrupt .......................................................2
convertitore A/D.........................................20 Interrupt, gestione degli ..............................16
convertitore per approssimazioni successive istruzioni ......................................................7
...............................................................20
L
D
loop ..............................................................9
datasheet .........................................................b LP ..............................................................13
direttive al compilatore .................................3
Display LED a 7 segmenti ..........................20 M
divisione, Algoritmi di................................48
DS30292x.PDF ................................................b
MainLoop.....................................................9
DS33014F.pdf ............................................10 MAX232 ..............................................20; 67
memoria EEPROM ..............................2; 20
E memoria FLASH ........................................2
memoria FLASH, paginazione....................10
ENABLE BIT.............................................20 memoria libera .............................................6
EQU.............................................................5 memoria RAM............................................1
errorlevel .....................................................5
messaggi di errore ........................................5
microchip ........................................................b
MOVLW......................................................9

70
Indice Analitico

MPASM USER’S GUIDE ..........................10 routine di Interrupt......................................15


RP0, RP1.....................................................7
N RS232 ..................................................20; 66
Notazioni Numeriche del Compilatore..........5
S
O sample&hold ..............................................20
Operatori Logici e Matematici ....................59 SCI.............................................................20
OPTION_REG ...........................................20 Serial Communications Interface ..... Vedi SCI
ORG ................................................................6
set di istruzioni............................................1
oscillatore, scelta del ..................................13 Set di Istruzioni ..........................................63
Sleep Mode ........... Vedi Risparmio energetico
P somma, Algoritmi di...................................20
SSP ............................................................20
P16F876.INC .............................................50 Stack ......................................................6; 10
periferiche integrate......................................2 STATUS ......................................................7
Peripheral Interrupt.....................................20 Status Register............................................62
PIE1 ...........................................................20 Struttura della RAM ...................................61
PIE2 ...........................................................20 Synchronous Serial Port .................. Vedi SSP
PIR1...........................................................20
PIR2...........................................................20 T
Porta A.......................................................20
Porta B .......................................................20 tanzilli ..........................................................1
Porta C .......................................................20 Timer 0.......................................................20
PORTA, PORTB, PORTC............................8 Timer 1.......................................................20
porte I/O.............................................3; 7; 20 Timer2........................................................20
Porte I/O, Stadio di uscita ...........................20 TMR0.........................................................20
Porte, posizione nell' integrato.......................8 TMR1.........................................................20
posizione programma in memoria .................6 TMR2.........................................................20
Posizione routine interrupt in memoria .......15 Trasmissione Asincrona..............................20
posizione variabili in memoria......................6 TRISA, TRISB, TRISC ................................8
PROCESSOR .......................................................4
prodotto, Algoritmi di.................................20 U
Program Memory .........................................6 Universal Synchronous Asynchronous
programmazione in assembly........................3 Receiver Trasmitter ............... Vedi USART
pull-up, interno ...........................................20 USART ......................................................20
PWM..........................................................20
W
R watchdog....................................................20
radix .............................................................4
RC..............................................................13 X
Registri di Interrupt ....................................20 XT..............................................................13
Registro di Stato .........................................62
retfie..........................................................16 Z
return............................................................9
risparmio energetico .....................................2 Z bit.............................................................7
Ritardo software .........................................20

71

Potrebbero piacerti anche