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
}

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