Programació en C del PIC 16F690

Referència Trucs Perifèrics   Recursos CITCEA
Tutorial Exemples Projectes   Inici

Exemple NT - Fem sonar notes musicals amb interrupcions

En aquest exemple farem servir interrupcions creades pel timer 2 per fer sonar unes notes musicals en un brunzidor piezoelèctric o un altaveu.

El següent programa toca la seqüència do - re - mi, fa una pausa de 0,2 s i la torna a tocar.

#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF
#pragma config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
#include <xc.h>					// Carrega el fitxer de funcions necessari per al compilador XC8
#define _XTAL_FREQ  4000000			// La freqüència del rellotge és 4 MHz
#define clrbit(var, bit) ((var) &= ~(1 << (bit)))
#define flipbit(var, bit) ((var) ^= (1<<(bit)))
char port;					// Variable auxiliar del port C
char control;					// Variable de control de la funció TocaNota
						// Si és 0 nota, si és 1 silenci
int bucles;					// Comptador d'iteracions de la nota
int silenci;					// Durada del silenci
						// Definició de les funcions que farem servir 
void TocaNota(char valPre, char valPos, char valPR2, int numbuc, int numsil);
void main (void){
	TRISC = 0;				// Tot el port C és de sortida
	port = 0;
	PORTC = 0;				// Desactiva les sortides del port C
	INTCON = 0b11000000;			// Activa GIE i PEIE
	while (1) {				// Inici del bucle de programa
		TocaNota(0, 7, 239, 105, 105);	// Valor que correspon aproximadament a do3
		TocaNota(0, 6, 243, 118, 118);	// Valor que correspon aproximadament a re3
		TocaNota(0, 5, 253, 132, 132);	// Valor que correspon aproximadament a mi3
	}
}
void __interrupt() temporit(void){
	if (PIR1bits.TMR2IF) {			// Comprovem que hi ha interrupció per Timer2
		PIR1bits.TMR2IF = 0;		// Desactiva el bit que indica interrupció pel Timer2
		if (control == 0){		// Si estem tocant una nota
			flipbit(port, 5);	// Inverteix la sortida del brunzidor
			PORTC = port;		// Ho copia al port C
		}
		bucles--;			// Comptador per a la durada de la nota
		if (bucles == 0){		// Si és zero, ja ha passat la durada de la nota
			if ((control == 1) || (silenci == 0)){	// Si s'acaba el silenci
				T2CONbits.TMR2ON = 0;		// Desactiva el Timer2
				PIE1bits.TMR2IE = 0;		// Desactiva les interrupcions per Timer2
			}
			if (control == 0){			// Si estem tocant una nota
				clrbit(port, 5);		// A l'acabar, deixa la sortida desactivada
				PORTC = port;			// Ho copia al port C
				if (silenci > 0){		// Si es preveu silenci
					bucles = silenci;	// Agafem la durada del silenci
					control = 1;		// Toca silenci
				}
			}
		}
	}
}
void TocaNota(char valPre, char valPos, char valPR2, int numbuc, int numsil) {
						// Funció per tocar una nota
	while(T2CONbits.TMR2ON)			// Si està tocant una nota
		;				// Esperem que acabi
	valPos &= 0b00001111;			// Per precaució, posem a zero els bits no emprats
	valPre &= 0b00000011;			// Per precaució, posem a zero els bits no emprats
	T2CON = (unsigned char) ((valPos<<3) | valPre);		// Ho posa a la configuració del temporitzador
	PR2 = valPR2;				// Preselecció del Timer2
	bucles = numbuc;			// Comptador d'iteracions
	silenci = numsil;			// Durada del silenci
	control = 0;				// Comencem tocant la nota
	PIE1bits.TMR2IE = 1;			// Activem les interrupcions per Timer2
	T2CONbits.TMR2ON = 1;			// Activem el Timer2
}

 

 

Llicència de Creative Commons
Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.