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. Després de la darrera nota, fa una pausa de 0,2 s i torna a començar el bucle.
#include <p16F690.inc> __config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
cblock 0x20 valPre ; Valor que posarem com a prescala (0 a 3) valPos ; Valor que posarem com a postescala (0 a 15) valPR2 ; Valor que carregarem a PR2 numbuc ; Nombre de cicles per fer 0,2 s bucles ; Comptador de cicles numsil ; Nombre de cicles per al silenci temp ; Variable temporal de la funció TocaNota control ; Variable de control de la funció TocaNota ; Si és 0 nota, si és 1 silenci port ; Variable per gestionar el port C endc cblock 0x70 ; Zona de memòria de dades que no depèn del banc triat W_Copia ; Guardarà el contingut de W durant la interrupció ST_Copia ; Guardarà STATUS durant la interrupció endc
org 0 goto Inici ; Saltem al lloc on hi ha el programa principal nop ; Zona de memòria de programa que no utilitzem nop nop
Interrup movwf W_Copia ; Copiem l'acumulador a W_Copia swapf STATUS,w ; Copiem STATUS a l'acumulador permutant els nibbles clrf STATUS ; Posa a 0 i així segur que el banc és el 0 movwf ST_Copia ; Guarda STATUS permutat a ST_Copia btfss PIR1,TMR2IF ; Mira si Timer2 ha arribat a zero ; Si hi ha arribat, no fa la instrucció següent goto FiInt ; Si la interrupció no és del Timer0 no fem res Timer2 ; Programa corresponent a Timer2 bcf PIR1,TMR2IF ; Si ha arribat, desactivem el bit movf control,f ; Mirem si estem fent sonar la nota btfss STATUS,Z goto TN1 ; Si és 1 no invertim la sortida movlw b'00100000' ; RC5 correspon al brunzidor xorwf port,f ; Inverteix el bit movf port,w ; Agafa port movwf PORTC ; i ho copia al port C TN1 decfsz bucles,f ; Comptador per a la durada de la nota goto FiInt ; Si no ha arribat a zero, ja hem acabat la interrupció movf control,f ; Mirem si estem fent sonar la nota btfss STATUS,Z goto TN2 ; Si estem en silenci vol dir que ja hem acabat bcf port,5 ; A l'acabar, deixa la sortida desactivada movf port,w movwf PORTC ; i ho copia al port C movf numsil,w ; Agafem la durada del silenci btfsc STATUS,Z goto TN2 ; Si el valor és zero no hi haurà silenci movwf bucles ; Nova durada del cicle movlw .1 ; Estem en silenci movwf control goto FiInt ; Comença el silenci TN2 bcf T2CON,TMR2ON ; Desactivem el Timer2 bsf STATUS,RP0 ; Tria el banc 1 bcf PIE1,TMR2IE ; Desactivem les interrupcions per Timer2 bcf STATUS,RP0 ; Tria el banc 0 FiInt swapf ST_Copia,w ; Copia permutant ST_Copia a l'acumulador movwf STATUS ; I ho passa a STATUS recuperant el valor d'abans ; de la interrupció swapf W_Copia,f ; Permuta els bits de W_Copia swapf W_Copia,w ; Torna a permutar els bits de W_Copia ; i els guarda a l'acumulador sense variar STATUS retfie ; Torna al programa principal, on s'havia quedat
Inici bsf STATUS,RP0 ; Tria el banc 1 clrf TRISC ; Tot el port C és de sortida bcf STATUS,RP0 ; Tria el banc 0 clrf port clrf PORTC ; Desactiva les sortides del port C movlw b'11000000' ; Activa GIE i PEIE movwf INTCON ; Activa les interrupcions a nivell general i les de PIE1 Bucle movlw .0 ; Valors que correspon aproximadament a do3 movwf valPre ; Prescalador movlw .7 movwf valPos ; Postescalador movlw .239 movwf valPR2 ; Valor per a PR2 movlw .105 movwf numbuc ; Nombre de cicles per fer 0,2 s clrf numsil ; Les notes van seguides call TocaNota ; Toca la nota configurada movlw .0 ; Valors que correspon aproximadament a re3 movwf valPre ; Prescalador movlw .6 movwf valPos ; Postescalador movlw .213 movwf valPR2 ; Valor per a PR2 movlw .117 movwf numbuc ; Nombre de cicles per fer 0,2 s clrf numsil ; Les notes van seguides call TocaNota ; Toca la nota configurada movlw .0 ; Valors que correspon aproximadament a mi3 movwf valPre ; Prescalador movlw .5 movwf valPos ; Postescalador movlw .190 movwf valPR2 ; Valor per a PR2 movlw .132 movwf numbuc ; Nombre de cicles per fer 0,2 s movwf numsil ; Silenci de 0,2 s call TocaNota ; Toca la nota configurada goto Bucle
; ; Funció per tocar una nota ; valPre Valor que posarem com a prescala (0 o 1) ; valPos Valor que posarem com a postescala (0 a 15) ; valPR2 Valor que carregarem a PR2 ; numbuc Nombre de cicles per fer 0,2 s ; Aquestes variables no es modifiquen si estan dins el rang TocaNota btfsc T2CON,TMR2ON ; Mira si està activat el Timer2 goto TocaNota ; Mentre sona una nota no podem tocar una altra movlw b'00001111' andwf valPos,f ; Per precaució, posem a zero els altres bits movf valPos,w ; Agafa el valor del postescalat movwf temp ; El guarda a la variable temporal rlf temp ; Posicionem el postescalat al seu lloc rlf temp rlf temp movlw b'00000011' andwf valPre,f ; Per precaució, posem a zero els altres bits movf valPre,w ; Agafa el valor del prescalat iorwf temp,w ; El combina amb el postescalador movwf T2CON ; Ho posa a la configuració del Timer2 movf valPR2,w ; Agafa la preselecció de PR2 bsf STATUS,RP0 ; Tria el banc 1 movwf PR2 ; I la posa al seu lloc bcf STATUS,RP0 ; Tria el banc 0 movf numbuc,w ; Agafa el nombre de cicles movwf bucles ; I el posa al seu lloc clrf control ; Comencem tocant la nota bsf STATUS,RP0 ; Tria el banc 1 bsf PIE1,TMR2IE ; Activem les interrupcions per Timer2 bcf STATUS,RP0 ; Tria el banc 0 bsf T2CON,TMR2ON ; Activem el Timer2 return end

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