Piedini (link al datasheet)
VSS - Massa
VDD - AlimentazioneMCLR - ResetI piedini che seguono sono quelli della PORTA - si programmano con il registro TRISA (banco 1 della RAM)RA0 - Ingresso/uscita digitale programmabileRA1 - Ingresso/uscita digitale programmabile RA2 - Ingresso/uscita digitale programmabile RA3 - Ingresso/uscita digitale programmabile RA4/T0CKl - Ingresso/uscita digitale programmabile - l'ingresso è dotato di un trigger di schmitt, può fare da ingresso del clock esterno per il modulo Timer0, come uscita è un Open Drain
I piedini che seguono sono quelli della PORTB - si programmano con il registro TRISB (banco 1 della RAM)
RB7 - Ingresso/uscita digitale programmabile - l'ingresso è dotato di resistenze programmabili di pull-up - l'ingresso può abilitare un interrupt ad ogni cambio di stato
RB6 - Ingresso/uscita digitale programmabile - l'ingresso è dotato di resistenze programma
bili di pull-up - l'ingresso può abilitare un interrupt ad ogni cambio di statoRB5 - Ingresso/uscita digitale programmabile - l'ingresso è dotato di resistenze programmabili di pull-up - l'ingresso può abilitare un interrupt ad ogni cambio di statoRB4 - Ingresso/uscita digitale programmabile - l'ingresso è dotato di resistenze programmabili di pull-up - l'ingresso può abilitare un interrupt ad ogni cambio di statoRB3 - Ingresso/uscita digitale programmabile - l'ingresso è dotato di resistenze programmabili di pull-upRB2 - Ingresso/uscita digitale programmabile - l'ingresso è dotato di resistenze programmabili di pull-upRB1 - Ingresso/uscita digitale programmabile - l'ingresso è dotato di resistenze programmabili di pull-upRB0/INT - Ingresso/uscita digitale programmabile - l'ingresso è dotato di resistenze di pull-up - l'ingresso può abilitare un interrupt su un fronte di salita o di discesa (per programmare il fronte si deve cambiare il bit INTEDG nel registro OPTION)OSC1/CLKIN - ingresso clock esterno - collegamento 1 del quarzo esternoOSC2/CLKOUT - uscita clock - collegamento 2 del quarzo esternoRegistri (link al datasheet)
Status (registro di stato)
bit 5: RP0 (Register Bank Select bits)
Selettore banco memoria RAM: 1 = Bank 1 (indirizzo 0x80 - 0xFF), 0 = Bank 0 (0x00 - 0x7F)
bit 4: TO (Time-out bit)
Flag di fine conteggio: 1 = dopo l'accensione, dopo istruzione CLRWDT, dopo istruzione SLEEP, 0 = fine conteggio WDT
bit 3: PD (Power-down bit)
Flag di accensione: 1 = dopo l'accensione, dopo istruzione CLRWDT, 0 = dopo istruzione SLEEP
bit 2: Z (Zero bit)
Flag di zero: 1 = il risultato di un'operazione aritmetica o logica è zero, 0 = il risultato è diverso da zero
bit 1: DC (Digit carry/borrow bit)
Flag di riporto di cifra: 1 = c'e' riporto dopo il quarto bit meno significativo del risultato, 0 = non c'e' riporto
(istruzioni ADDWF, ADDLW,SUBLW,SUBWF) (per il riporto la logica è invertirta)
bit 0: C (Carry/borrow bit)
Flag di riporto: 1 = c'e' riporto dopo il bit più significativo (MSB = Most Significant bit) del risultato, 0 = non c'e' riporto
(istruzioni ADDWF, ADDLW,SUBLW,SUBWF) (per il riporto la logica è invertirta)
Option (registro delle opzioni)
bit 7: RBPU (PORTB Pull-up Enable bit)
Abilitazione resistenze di pull-up sulle porte RB0-7: 1 = resistenze disabilitate, 0 = abilitate
bit 6: INTEDG (Interrupt Edge Select bit)
Selezione fronte in salita o in discesa per generare l'interrupt dal pin RB0/INT: 1 = fronte in salita, 0 = fronte in discesa
bit 5: T0CS (TMR0 Clock Source Select bit)
Selezione clock per il modulo Timer0: 1 = Clock dal pin RA4/T0CKI, 0 = Clock interno (CLKOUT) del ciclo delle istruzioni
bit 4: T0SE (TMR0 Source Edge Select bit)
Selezione fronte in salita o in discesa per il clock su RA4/T0CKI: 1 = fronte in discesa, 0 = fronte in salita
bit 3: PSA (Prescaler Assignment bit)
Assegnazione divisore di frequenza (Prescaler): 1 = Prescaler assegnato al WDT, 0 = Prescaler assegnato al Timer0
bit 2-0: PS2:PS0 (Prescaler Rate Select bits)
Attenzione: se il Prescaler è assegnato al WDT il modulo Timer0 non ha divisione di frequenza (1:1).
Schema della logica collegata ai piedini di I/O
PORTA - RA0-3
PORTA - RA4
PORTB - RB4-7
PORTB - RB0-3
Intcon (registro dell'interrupt)
bit 7: GIE (Global Interrupt Enable bit)
Abilitazione generale dell'interrupt: 1 = interrupt abilitato, 0 = disabilitato
bit 6: EEIE (EE Write Complete Interrupt Enable bit)
Abilitazione interrupt su fine scrittura di un byte della Eeprom: 1 = interrupt abilitato, 0 = disabilitato
bit 5: T0IE (TMR0 Overflow Interrupt Enable bit)
Abilitazione dell'interrupt sull'overflow del modulo Timer0: 1 = interrupt abilitato, 0 = disabilitato
bit 4: INTE (RB0/INT External Interrupt Enable bit)
Abilitazione sull'interrupt da un fronte sul pin RB0/INT: 1 = interrupt abilitato, 0 = disabilitato
bit 3: RBIE (RB Port Change Interrupt Enable bit)
Abilitazione sull'interrupt da un cambiamento di stato sui pin RB4-7: 1 = interrupt abilitato, 0 = disabilitato
bit 2: T0IF (TMR0 Overflow Interrupt Flag bit)
Flag di interrupt sull'overflow del modulo Timer0: 1 = overflow su Timer0 , 0 = nessun overflow
bit 1: INTF (RB0/INT External Interrupt Flag bit)
Flag di interrupt da un fronte sul pin RB0/INT: 1 = interrupt attivo (va azzerato con il software), 0 = nessun interrupt
bit 0: RBIF (RB Port Change Interrupt Flag bit)
Flag di interrupt da un cambiamento di stato sui pin RB4-7: 1 = interrupt attivo (va azzerato con il software), 0 = nessun interrupt
EEcon1 (registro della Eeprom)
bit 4: EEIF (EEPROM Write Operation Interrupt Flag bit)
Flag di interrupt su fine scrittura di un byte della Eeprom: 1 = scrittura completata attivo (va azzerato con il software), 0 = non completate o non iniziata
bit 3: WRERR (EEPROM Error Flag bit)
Flag di errore sulla scrittura di un byte della Eeprom: 1 = scrittura fallita (può succedere con un Reset da MCLR, o con un reset dal WDT), 0 = scrittura completata
bit 2: WREN (EEPROM Write Enable bit)
Abilitazione del ciclo di scrittura sulla Eeprom: 1 = abilita, 0 = blocca la scrittura
bit 1: WR (Write Control bit)
Comando di scrittura sulla Eeprom: 1 = comando scrivi (il bit viene azzerato via hardware a fine scrittura), 0 = fine scrittura
bit 0: RD (Read Control bit)
Comandi di lettura sulla Eeprom: 1 = comando leggi (il bit viene azzerato via hardware a fine lettura), 0 = blocca lettura
Modulo Timer 0 (link al datasheet)
Il modulo Timer0 è un dispositivo che funziona da timer o da contatore con le seguenti caratteristiche.
• registro a 8-bit timer (se T0CS = 0 nel registro Option) o contatore (se T0CS = 1 nel registro Option)
• leggibile e scrivibile
• clock interno (se T0CS = 0 nel registro Option) o esterno (se T0CS = 1 nel registro Option)
• possibilità di selezione fronte di conteggio per il clock esterno (T0SE nel registro Option)
• divisore di frequenza (prescaler) a 8 bit programmabile via software
• interrupt sull'overflow da 0xFF a 0x00
TIPI di VARIABILI
Programma per attendere 5 secondi con lempeggio led su pin RB3
unsigned long count = 0;
// Quarzo = 4 MHz Clock=0,25us Frequenza sul Timer0 = 1 MHz Periodo =1 us
// Prescaler assegnato al Timer0 = 1/4 Periodo = 4 us
// Overflow del Timer ogni 250 conteggi (si parte da 0x06)
// Periodo interrupt = 250 x 4us = 1ms
void setup(void)
{
TRISB=0x00;
T0CS=0;
PSA=0;
PS2=0; // divide per 4
PS1=0;
PS0=1;
T0IE=1; // Enable Timer0 overflow interrupt
GIE=1; // Enable Interrupt
}
void interrupt isr(void)
{
if(T0IF)
{
count++;
TMR0=0x06;
T0IF=0; // clear interrupt flag - 2us
}
}
void delay(unsigned long millisecondi)
{
cont=0;
TMR0=0x06;
while(cont<millisecondi);
}
void attesa5secondi(void)
{
char led=0;
for (int i=0; i<5; i++)
if (!led)
{
led=1;
RB3=1; // led ON
delay(1000);
}
else
{
led=0;
RB3=0; // led OFF
delay(1000);
}
}
void loop(void)
{
attesa5secondi();
....
}
void main(void)
{
setuo();
while(1) loop();
}
Programma con interrupt per attendere 5 secondi e poi 1 secondo
unsigned int count = 77;
char led=0;
void interrupt isr (void) // interrupt program
{
if(T0IF)
{
count--;
if (!count)
{
if(!led)
{
led=1;
RB3=1;
count=15;
}
else
{
led=0;
RB3=0;
count=77;
}
}
}
T0IF=0;
}
void setup(void)
{
T0CS=0;
PSA=0;
PS2=1;
PS1=1;
PS0=1;
TOIE=1;
GIE=1;
}
void loop(void)
{
...
}
void main(void)
{
setuo();
while(1) loop();
}
Lettura e scrittura della Eeprom (link al datasheet)
La lettura di un byte della Eeprom avviene con il seguente sottoprogramma:
char ReadEeprom(char Eeprom_index)
{
EEADR=Eeprom_index; // load Eeprom address
RD=1; // read EEprom
return(EEDATA); // return EEDATA register byte as ReadEeprom value
}
La scrittura di un byte della Eeprom avviene con i seguenti metodi.
Metodo che utilizza un sottoprogramma delayTime(time)
void delayTime(unsigned int time) // wait until time
{
while (time) time--; // decrement time (34 us e Fclock=4MHz)
}
void WriteEeprom(char Eeprom_index, char Eeprom_data)
{
RB4=0; // led on -> start of EEprom writing process
do
{
EEADR=Eeprom_index; // load Eeprom address in EEADR register (address)
EEDATA=Eeprom_data; // load Eeprom data in EEDATA register (data)
GIE=0; // disable interrrupt
WREN=1; // write process step 1: enable write
EECON2=0x55; // write process step 2
EECON2=0xAA; // write process step 2
WR=1; // write process step 2: write command
GIE=1; // enable interrrupt
delayTime(2000); // wait when writing EEprom
RB4=1; // led off -> end of EEprom writing process
}
while(WRERR);
delayTime(10); // wait when led off
}
Metodo che utilizza il bit WR per attendere la fine della scrittura della Eeprom
void WriteEeprom(char Eeprom_index, char Eeprom_data)
{
RB4=0; // led on -> start of EEprom writing process
EEADR=Eeprom_index; // load Eeprom address in EEADR register (address)
EEDATA=Eeprom_data; // load Eeprom data in EEDATA register (data)
GIE=0; // disable interrrupt
WREN=1; // write process step 1: enable write
EECON2=0x55; // write process step 2
EECON2=0xAA; // write process step 2
WR=1; // write process step 2: write command
GIE=1; // enable interrrupt
while(WR); // wait when writing EEprom
RB4=1; // led off -> end of EEprom writing process
delayTime(10); // wait when led off
}
Metodo che utilizza l'interrupt per attendere la fine della scrittura della Eeprom
void interrupt isr (void) // interrupt program
{
flag = 1; // set flag: end of eeprom write process
EEIF=0; // clear interrupt flag
}
void initInterrupt(void)
{
EEIE=1; // Enable Eeprom write complete interrupt
GIE=1; // Enable Interrupt
}
void WriteEeprom(char Eeprom_index, char Eeprom_data)
{
RB4=0; // led on -> start of EEprom writing process
EEADR=Eeprom_index; // load Eeprom address in EEADR register (address)
EEDATA=Eeprom_data; // load Eeprom data in EEDATA register (data)
GIE=0; // disable interrrupt
WREN=1; // write process step 1: enable write
EECON2=0x55; // write process step 2
EECON2=0xAA; // write process step 2
WR=1; // write process step 2: write command
EEIE=1; // Enable Eeprom write complete interrupt
GIE=1; // Enable Interrupt
while(!flag); // wait when writing EEprom
flag=0;
RB4=1; // led off -> end of EEprom writing process
delayTime(10); // wait when led off
}
Funzioni speciali del Pic16f8 (link al datasheet)
Interrupt
pag 29 del datasheet
Come si può vedere dallo schema interno gli interrupt disponibili sono 4:
T0 - Overflow sul TMR0,
INT - Cambio tensione di ingresso sul pin RB0/INT,
RB - Cambio tensione di ingresso sui pin RB4-7,
EE - Termine scrittura Eeprom.
Quando si verifica una delle 4 condizioni sopra elencate il PIC mette a 1 il flag F corrispondente, se l'abilitazione E (enable) è a 1 il segnale di interruzione passa alla porta OR. I flag vanno azzerati dalla routine di interrupt.
Il GIE (Global Interrupt Enable) abilita l'interruzione.
L'interruzione prevede le seguenti operazioni:
- viene salvato il valore del Program Counter (che indica l'indirizzo dell'istruzione da eseguire) nello Stack
- viene eseguita il sottoprogramma di Interrupt (mettendo nel Program Counter l'indirizzo della prima istruzione del sottoprogramma di interrupt)
- viene ripristinato il valore del Program Counter
Watchdog Timer (WDT)
pag 30 del datasheet
Il Watchdog Timer è un contatore collegato ad un oscillatore RC interno che non richiede componenti esterni.
Il tempo di fine conteggio senza prescaler è di circa 18ms.
E' separato dall'oscillatore collegato al pin OSC1/CLKIN.
Il WDT può oscillare anche se il clock esterno sul pin OSC1/CLKIN è fermo (per esempio con l'esecuzione dell'istruzione SLEEP).
Il WDT può essere disabilitato mettendo il bit WDTE a zero nel registro speciale (pag 21 del datasheet) che si può cambiare solo nella fase di caricamento del programma dal computer al Pic.
Nel funzionamento normale un overflow sul WDT genera un Reset del Pic.
Se il Pic è in uno stato di SLEEP, un overflow sul WDT fa riprendere al Pic il funzionamento normale.
Registro di configurazione (registro segreto)
pag 21 del datasheet
Questo registro si può cambiare solo nella fase di caricamento del programma dal computer al Pic.
E' importante per configurare il programma Icprog (che gestisce questa operazione).
Contiene i seguenti:
WDTE - permette di disabilitare il Watchdog Timer
FOSC1-FOSC0 - permettono di selezionare il tipo di clock (pag. 22 del datasheet)
11 = oscillatore RC
10 = HS (High Speed Crystal/Resonator) oscillatore con quarzo esterno
01 = XT (Crystal/Resonator) oscillatore con quarzo esterno
00 = LP (Low Power Crystal) oscillatore con quarzo esterno
Nelle modalità HS, XT, LP è possibile sostituire al quarzo un oscillatore esterno.
In questo caso l'ingresso del clock è sul pin OSC1, mentre OSC2 si lascia libero.
Nella tabella sottostante sono indicati i valori del QUARZO e dei condensatori per le configurazioni LP, XT e HS
Nella tabella sottostante sono indicati i valori del RISONATORE CERAMICO e dei condensatori per le configurazioni XT e HS
Nella configurazione RC la frequenza dipende dai valori d R e C esterni.