Tutorial → PIC18 in C → 
	Timer1 e ECCP → 
	Timer1 e ECCP con le PLIB
	
	
	
	
	
 
	Le PLIB sono dal luglio 2015 sconsigliate per nuovi progetti
	
	
	Questa pagina affronta l'uso dei moduli Timer1 e ECCP (Enhanced Capture, 
	Compare, and PWM) in modalità Compare Mode, utilizzando le PLIB
	Il modulo ECCP in modalità "compare"
	Utilizzando il modulo ECCP insieme a Timer1 è possibile generare in modo 
	totalmente hardware frequenze programmabili. Questo da una parte semplifica il lavoro 
	del PIC18, dall'altra permette di generare intervalli temporali 
	che dipendono esclusivamente dalla precisione del clock. Si osserva che 
	nella descrizione seguente non sono necessarie le capacità enhanced, 
	quindi la descrizione dovrebbe essere corretta anche per i PIC18 più vecchi.
	Due sono i blocchi fondamentali:
	
		- Il blocco di confronto che attiva un segnale quando il contenuto del 
		registro CCPR1 coincide con il conteggio raggiunto da Timer1 (o Timer3)
 
		- La logica di uscita, che sceglie l'azione da intraprendere: azzerare 
		Timer1 oppure Timer3, avviare il convertitore AD, generare un interrupt, 
		modificare lo stato del pin CCP1
 
	
		 In sintesi il funzionamento di Timer1 + ECCP è simile a quello di un 
		 contatore asincrono il cui modulo dipenderà dal contenuto del registro 
		 CCPR1; quindi il conteggio di Timer1 inizia da zero e termina ad un 
		 valore programmabile inferiore a 65536. Se fa notare che il termine asincrono è stato 
		 usato impropriamente in quanto la struttura interna è in realtà 
		 interamente sincrona.
	
	
	 Il codice di esempio configura ECCP per azzerare 
	Timer1 ed attivare un interrupt allo scopo di far lampeggiare un LED un paio 
	 di volte al secondo. Sono utilizzate le PLIB, ma leggete la 
	richiesta del terzo esercizio.
	Il circuito è semplicemente un LED ed una resistenza connessi a PORTC0:
	
	
	Leggiamo il codice. La funzione main():
	
		- Imposta le porte e i registri degli interrupt, come già visto più volte
 
		- Imposta Timer1 per funzionare a 16 bit, con clock interno e senza 
		prescaler. Si noti che non è attivo l'interrupt: sarà infatti il modulo 
		ECCP ad incaricarsi di questo aspetto. Si noti inoltre che il conteggio 
		non viene inizializzato, cioè partirà da zero.
OpenTimer1(TIMER_INT_OFF & T1_16BIT_RW & 
		T1_SOURCE_INT & T1_PS_1_1); 
		- Il modulo ECCP viene inizializzato per generare un interrupt quando 
		il confronto avrà successo e per generare uno Special Event 
		Trigger. Viene inoltre inizializzato al valore di 49 999 ( f 
		= 250 kHz / 
		(49 999 + 1)) produce un segnale di durata 200 ms)
		OpenCompare1(COM_INT_ON & COM_TRIG_SEVNT, 
		TIMER1_VALUE); 
		- Associa il modulo ECCP al Timer1
T3CONbits.T3CCP1 = 0; // Timer1 is the clock source 
		for compare 
		- Infine impostare la priorità dell'interrupt ad alta:
		IPR1bits.CCP1IP = 1; // CCP1 Interrupt Priority set 
		to high 
		- A questo punto l'attività termina
 
	
	L'attività della ISR è particolarmente semplice:
	
		- Verifica se l'interrupt proviene da ECCP
		if (PIR1bits.CCP1IF == 1) // Interrupt from ECCP ? 
		- Cambia lo stato dell'uscita PORTC0
 
		- Azzera il flag che ha generato l'interruzione
		PIR1bits.CCP1IF = 0; // Clear interrupt status 
	
	Si noti che, nel caso particolare, il LED poteva essere collegato 
	direttamente al pin CCP1 (pin 13), liberando completamente il processore da 
	questa incombenza (quarto esercizio).
	 Il modulo ECCP è molto più flessibile di quanto mostrato: si legga 
	 quanto proposto nell'approfondimento.
	Un altro esempio, associato all'uso dell'ADC
	lo trovate in questa pagina.
	
	Disporre di due sorgenti di interrupt indipendenti come Timer0 e Timer1 
	ci permette di visualizzare come opera un sistema in cui sono presenti più 
	attività "contemporanee".
	Il codice, presente a fine pagina, esegue tre attività 
	diverse e indipendenti, ma con il vincolo che il processore è uno solo:
	
		- Il main(), dopo la configurazione delle 
		periferiche, non fa altro che cambiare continuamente lo stato di
		RED, cioè del pin PORTC0
 
		- La funzione my_isr_low(), è attivata da Timer0 
		ogni 6.1 ms circa (conteggio da 64000 a 65536 di un clock con frequenza 
		250 kHz). La sua attività è cambiare per 50 
		volte lo stato di BLUE, cioè il pin PORTC1, per far ciò impiega un tempo di circa 1,2 
		ms (tempo misurato, non calcolato)
 
		- La funzione my_isr_high(), è attivato da Timer1 
		ogni 4 ms (conteggio da 0 a 1000 di un clock con frequenza 205 kHz). La 
		sua attività è cambiare per 10 
		volte lo stato di GREEN, cioè del pin PORTC2. per far ciò impiega un 
		tempo di circa 0,2 
		ms (tempo misurato, non calcolato)
 
	
	La descrizione dettagliata del codice è la stessa già presentata 
	per Timer0 e Timer1.
	Osserviamo quello che succede sul grafico reali delle tre uscite, 
	misurato dopo le fasi iniziali del programma: 
	
		- Al tempo zero di riferimento è attivo main() 
		e quindi RED 
		cambia continuamente stato
 
		- Dopo circa 0,8 ms dal tempo zero, RED interrompe il suo funzionamento 
		ed il controllo passa a my_isr_high(), alias 
		GREEN, per poco più di 0,2 ms
 
		- Quindi riprende il lavoro di RED, dallo stato rimasto nell'istante di 
		sospensione (nell'esempio l'uscita PORTC0 è rimasta casualmente alta)
 
		- Dopo poco più di 2 ms dal tempo zero, 
		my_isr_low(), alias BLUE, interrompe il funzionamento di RED, per 
		poco più di 1 ms. 
 
		- Al termine, RED riprende il suo lavoro (questa volta l'uscita PORTC0 
		è rimasta casualmente bassa)
 
		- Dopo 4,8 ms dal tempo zero il controllo torna nuovamente a GREEN, che lo 
		lascia poco dopo
 
		- Dopo 8,5 ms dall'inizio, il controllo torna a BLUE
 
		- Dopo un ulteriore breve intervallo il controllo passa a GREEN, che 
		ha priorità maggiore e quindi interrompe l'attività di BLUE
 
		- Dopo 0,2 ms il controllo torna a BLU, visto che non ha ancora 
		finito il sui lavoro. 
 
		- Infine il processore tornerà a RED, passaggio non mostrato nel 
		grafico
 
	
	
	
	
	Aspetti da osservare:
	
		- Ogni cambio del processo in esecuzione richiede un certo tempo per 
		la commutazione di contesto (context switch).
		Abbiamo già visto che tale tempo è 
		nelle condizioni date, 
		dell'ordine dei 150 µs
 
		- Un interrupt ad alta priorità può interrompere un interrupt a bassa 
		priorità (ma non viceversa)
 
		- In presenza di interruzioni, la durata precisa di un'attività non 
		può essere calcolato con certezza
 
	
	
	
	
	
		- Scrivere il codice che utilizza Timer1 per far lampeggiare un LED 
		utilizzando PLIB, come già fatto con Timer0
 
	
	
	
	
	Data di creazione di questa pagina: luglio 2014
	Ultima modifica: 31 luglio 2015