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.
PROCESSOR 16F690 #include <xc.inc> config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
valPre EQU 0x20 ; Valor que posarem com a prescala (0 a 3)
valPos EQU 0x21 ; Valor que posarem com a postescala (0 a 15)
valPR2 EQU 0x22 ; Valor que carregarem a PR2
numbuc EQU 0x23 ; Nombre de cicles per fer 0,2 s
bucles EQU 0x24 ; Comptador de cicles
numsil EQU 0x25 ; Nombre de cicles per al silenci
temp EQU 0x26 ; Variable temporal de la funció TocaNota
control EQU 0x27 ; Variable de control de la funció TocaNota
; Si és 0 nota, si és 1 silenci
port EQU 0x28 ; Variable per gestionar el port C
; Zona de memòria de dades que no depèn del banc triat
W_Copia EQU 0x70 ; Guardarà el contingut de W durant la interrupció
ST_Copia EQU 0x71 ; Guardarà STATUS durant la interrupció
PSECT code, class=CODE, delta=2, abs main: ; Adreça 0 h goto Inici ; Saltem al lloc on hi ha el programa principal nop ; Zona de memòria de programa que no utilitzem nop nop
Interrup: ; Adreça 4 h
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 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 TMR2IF ; Si ha arribat, desactivem el bit
movf control,f ; Mirem si estem fent sonar la nota
btfss ZERO
goto TN1 ; Si és 1 no invertim la sortida
movlw 00100000B ; 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 ZERO
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 ZERO
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 TMR2ON ; Desactivem el Timer2
bsf RP0 ; Tria el banc 1
bcf TMR2IE ; Desactivem les interrupcions per Timer2
bcf 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 RP0 ; Tria el banc 1 clrf TRISC ; Tot el port C és de sortida bcf RP0 ; Tria el banc 0 clrf port clrf PORTC ; Desactiva les sortides del port C movlw 11000000B ; 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 TMR2ON ; Mira si està activat el Timer2 goto TocaNota ; Mentre sona una nota no podem tocar una altra movlw 00001111B 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 00000011B 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 RP0 ; Tria el banc 1 movwf PR2 ; I la posa al seu lloc bcf 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 RP0 ; Tria el banc 1 bsf TMR2IE ; Activem les interrupcions per Timer2 bcf RP0 ; Tria el banc 0 bsf TMR2ON ; Activem el Timer2 return END main

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