Un brunzidor piezoelèctric és un element capaç de generar un so d'una determinada freqüència quan se l'alimenta amb un senyal oscil·lant de la freqüència desitjada. En el nostre cas emprem un brunzidor CUI o un CAF4. El connexionat és molt simple. Només cal connectar el positiu del brunzidor a la sortida escollida i el negatiu a la pota VSS (negatiu de l'alimentació).
Tenim tres opcions per fer sonar les notes:
Al final de la pàgina hi podeu trobar alguns consells d'ús.
Atès que quan emprem PWM hem de fer servir la pota corresponent (RC5), en tots els casos i exemples utilitzarem la mateixa sortida.
Els brunzidors són elements petits i molt senzills de fer servir però el seu so no és de gaire qualitat. Si volem un so més agradable, podem emprar un altaveu.
Imaginem que volem fer un la (freqüència de 440 Hz) i amb un temps d'activació del 50 %. El període corresponent és:

El temps d'activació serà la meitat del període:

Aquest és el temps que hi haurà d'haver entre l'activació i la desactivació de la sortida. Per fer aquest temps emprarem uns bucles de retard però hi ha un petit temps (aproximadament 10 μs) que correspon a instruccions que no corresponen a aquest retard. Per tant el retard haurà de ser més petit en aquesta quantitat. El temps de retard serà, doncs, de:
Haurem de fer bucles de retard per aconseguir aquest temps. El gruix d'aquest temps l'obtindrem fent cicles de 771 μs. En caldran:

O sigui, en necessitarem només un però caldrà complementar-lo amb cicles de 3 μs. En faran falta:

Ara ens queda definir la durada de la nota. Imaginem que volem que sigui de 0,2 s, això voldrà dir que haurem de repetir aquest semiperíode el següent nombre de cops:

La taula següent indica els valors que cal configurar en el PWM per obtenir les notes de l'escala central del piano:

| Nota | Freqüència teòrica (Hz) | NS | N771 | N3 | |||
| do3 | C4 | 261,626 | 105 | 2 | 120 | ||
| do#3 | re b3 | C#4 | Db4 | 277,183 | 111 | 2 | 83 |
| re3 | D4 | 293,665 | 117 | 2 | 50 | ||
| re#3 | mi b3 | D#4 | Eb4 | 311,127 | 124 | 2 | 18 |
| mi3 | E4 | 329,628 | 132 | 1 | 245 | ||
| fa3 | F4 | 349,228 | 140 | 1 | 216 | ||
| fa#3 | sol b3 | F#4 | Gb4 | 369,994 | 148 | 1 | 190 |
| sol3 | G4 | 391,995 | 157 | 1 | 164 | ||
| sol#3 | la b3 | G#4 | Ab4 | 415,305 | 166 | 1 | 140 |
| la3 | A4 | 440,000 | 176 | 1 | 118 | ||
| la#3 | si b3 | A#4 | Bb4 | 466,164 | 186 | 1 | 97 |
| si3 | B4 | 493,883 | 198 | 1 | 77 | ||
| do4 | C5 | 523,251 | 209 | 1 | 58 | ||
La taula següent indica els valors que cal configurar per obtenir tres notes extremes:
| Nota | Freqüència teòrica (Hz) | NS | N771 | N3 | |||
| do0 | C1 | 32,7032 | 13 | 19 | 210 | ||
| re#4 | mi b4 | D#5 | Eb5 | 554,365 | 222 | 1 | 40 |
| do7 | C8 | 4186,01 | 1674 | 0 | 36 | ||
La funció que presentem pot fer qualsevol nota entre el do0 i el re#4. Per aconseguir notes de freqüència més alta només caldria, però, fer que el comptador de cicles (variables numbuc i bucles) puguin comptar valors superiors a 255, és a dir fent servir dos bytes per a aquestes funcions. També cal vigilar-ho en cas que desitgem durades de nota superiors a 0,2 s.
La funció següent toca la nota que se li indica durant el temps especificat. Per seleccionar la nota i la durada, cal escriure els valors corresponents a numbuc, numcicL i numcicC.
A l'exemple NS la podeu veure en funcionament.
cblock 0x20 numbuc ; Nombre de bucles per fer 0,2 s bucles ; Comptador de bucles numcicL ; Nombre de cicles de 771 us numcicC ; Nombre de cicles de 3 us port ; Variable per gestionar el port C Retard1 ; Variables de retard Retard2 ... endc
org 0 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 ; Desactiva les sortides del port C clrf PORTC ; Desactiva les sortides del port C ... movlw .105 ; Valors que correspon aproximadament a do3 movwf numbuc ; Nombre de bucles per fer 0,2 s movlw .2 movwf numcicL ; Nombre de cicles de 771 us movlw .120 movwf numcicC ; Nombre de cicles de 3 us call TocaNota ; Toca la nota configurada ...
; ; Funció per tocar una nota ; numbuc Nombre de bucles per fer 0,2 s ; numcicL Nombre de cicles de 771 us ; numcicC Nombre de cicles de 3 us ; Aquestes tres variables no es modifiquen TocaNota movf numbuc,w ; Nombre de cops que ho hem de repetir movwf bucles ; Variable per comptar-los TN0 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 ; Retard de numcicL x 771 us movf numcicL,w ; Nombre de cicles que cal fer movwf Retard2 btfsc STATUS,Z ; Mira si és zero goto TN2 ; No fem aquest retard TN1 decfsz Retard1,f goto TN1 decfsz Retard2,f goto TN1 TN2 ; Retard de numcicC x 3 us movf numcicC,w ; Nombre de cicles que cal fer movwf Retard1 btfsc STATUS,Z ; Mira si és zero goto TN2 ; No fem aquest retard TN3 decfsz Retard1,f goto TN3 TN4 decfsz bucles,f goto TN0 ; Fi del bucle bcf port,5 ; En acabar, deixem la sortida desactivada movf port,w ; Agafa port movfw PORTC ; i ho copia al port C return ...
El PWM ha de tenir la freqüència de la nota desitjada i un temps d'activació proper al 50 %.
Imaginem que volem fer un la (freqüència de 440 Hz) i amb un temps d'activació del 50 %.
Amb la configuració bàsica del microcontrolador, el rellotge treballa a 4 MHz que dona una freqüència de 1 MHz al rellotge del programa, amb el que es controla el Timer 2. Per tant ens caldria que el Timer 2 comptés fins a:

Però el Timer 2 és de 8 bits, per tant només pot comptar fins a 256 valors. Per tant, ens cal posar una prescala a Timer 2. Aquesta prescala ha de ser superior a:

Com el Timer 2 pot tenir prescales d'1, 4 i 16, agafarem aquesta darrera. Així el nombre que ens cal comptar serà:

Però atès que el comptador comença a 0, caldrà comptar de 0 a 141 per tenir 142.
El Timer 2 es configura a T2CON. En el mode PWM els cinc bits més significatius no tenen utilitat. El bit 2 engega el Timer quan està activat, si està desactivat el Timer no treballa. Els bits 0 i 1 configuren la prescala, segons la següent taula:
| Bit 1 | Bit 0 | Prescala |
| 0 | 0 | 1 |
| 0 | 1 | 4 |
| 1 | 0 | 16 |
| 1 | 1 |
Així, doncs, T2CON haurà de ser 00000111 on els dos darrers bits són els que permeten triar la prescala.
Ara ens cal trobar el valor de CCP per aconseguir el temps d'activació desitjat. Com treballem amb 10 bits, el valor de CCP pot anar de 0 a quatre cops PR2; és a dir 568.
Per a un 50 %, el valor corresponent serà 284.
Hem de separar els dos bits de menys pes i quedar-nos amb la resta. Els vuit bits de més pes seran la part entera de dividir per 4:

I els dos bits de més pes seran:
Per al mode normal, la configuració del registre CCP1CON ha de ser 00001100; on els dos bits marcats en color són els que corresponen a DC1B.
Malauradament, el microcontrolador no té prou precisió i les notes reals tindran una freqüència lleugerament diferent. En aquest cas, serà:

La taula següent indica els valors que cal configurar en el PWM per obtenir les notes de l'escala central del piano:

| Nota | Freqüència teòrica (Hz) | Prescala | PR2 | CCPR1L | DC1B | Freqüència real (Hz) | |||
| do3 | C4 | 261,626 | 16 | 238 | 119 | 2 | 261,506 | ||
| do#3 | re b3 | C#4 | Db4 | 277,183 | 16 | 224 | 112 | 2 | 277,778 |
| re3 | D4 | 293,665 | 16 | 212 | 106 | 2 | 293,427 | ||
| re#3 | mi b3 | D#4 | Eb4 | 311,127 | 16 | 200 | 100 | 2 | 310,945 |
| mi3 | E4 | 329,628 | 16 | 189 | 95 | 0 | 328,947 | ||
| fa3 | F4 | 349,228 | 16 | 178 | 89 | 2 | 349,162 | ||
| fa#3 | sol b3 | F#4 | Gb4 | 369,994 | 16 | 168 | 84 | 2 | 369,822 |
| sol3 | G4 | 391,995 | 16 | 158 | 79 | 2 | 393,082 | ||
| sol#3 | la b3 | G#4 | Ab4 | 415,305 | 16 | 149 | 75 | 0 | 416,667 |
| la3 | A4 | 440,000 | 16 | 141 | 71 | 0 | 440,141 | ||
| la#3 | si b3 | A#4 | Bb4 | 466,164 | 16 | 133 | 67 | 0 | 466,418 |
| si3 | B4 | 493,883 | 16 | 126 | 63 | 2 | 492,126 | ||
| do4 | C5 | 523,251 | 16 | 118 | 59 | 2 | 525,210 | ||
La taula següent indica els valors que cal configurar en el PWM per obtenir dues notes extremes:
| Nota | Freqüència teòrica (Hz) | Prescala | PR2 | CCPR1L | DC1B | Freqüència real (Hz) | |||
| si2 | B2 | 246,942 | 16 | 253 | 126 | 2 | 247,036 | ||
| do7 | C8 | 4186,01 | 1 | 239 | 119 | 2 | 4184,10 | ||
A la velocitat de 4 MHz del microcontrolador no podem obtenir una nota de menor freqüència que el si2. Per obtenir freqüències més baixes caldria reduir la velocitat del rellotge.
La funció següent toca la nota que se li indica durant 0,2 s i després deixa un silenci de 0,2 s més. Per especificar la nota, cal escriure els valors corresponents a PR2, CCPR1L i DC1B a les respectives variables ValPR2, ValCCPR1L i ValDC1B.
A l'exemple NM la podeu veure en funcionament.
cblock 0x20 Retard1 ; Variables de retard Retard2 ValPR2 ; Aquí hi guardarem el valor de PR2 ValCCPR1L ; Aquí hi guardarem el valor de CCPR1L ValDC1B ; Aquí hi guardarem el valor de DC1B ValCCP1CON ; Aquí hi guardarem el valor de CCP1CON ... endc
org 0 Inici bsf STATUS,RP0 ; Tria el banc 1 movlw b'00100000' ; Definim com volem les E/S del port C movwf TRISC ; RC5 (sortida del PWM) com a entrada bcf STATUS,RP0 ; Tria el banc 0 clrf PORTC ; Desactiva les sortides del port C movlw b'00001100' ; Configura el PWM, bits P1M (bits 7-6) a 00 mode senzill ; DC1B = 00 (bits 5-4) els dos bits de menys pes són 0 ; CCP1M = 11xx en mode senzill els bit 0 i 1 no afecten movwf ValCCP1CON ; Ho guarda per fer-ho servir més tard movwf CCP1CON ; Ho posa com a configuració del PWM movlw b'00000011' ; Configura el Timer 2 ; bits T2KCPS (bits 1-0) a 11 prescalat de 16 ; bit 2 (TMR2ON) a 0, Timer aturat ; Postscaler TOUTPS (bits 6-3) no afecten al PWM movwf T2CON ; Ho posa com a configuració del Timer 2 ... movlw .141 ; Valor que correspon aproximadament a 440 Hz (LA3) movwf ValPR2 ; Ho posem com a valor de PR2 movlw .71 ; Valor que correspon a un cicle del 50 % a 440 Hz movwf ValCCPR1L ; Valor de CCPR1L movlw .0 ; Valor dels bits de menys pes del CCP movwf ValDC1B ; Valor de DC1B call TocaNota ; Toca la nota configurada ...
; ; Funció per tocar la nota configurada ; TocaNota movf ValPR2,w ; Valor de PR2 per a la nota desitjada bsf STATUS,RP0 ; Tria el banc 1 bsf TRISC,5 ; Posem RC5 (sortida del PWM) com a entrada movwf PR2 ; Ho posem com a comparació al Timer 2 bcf STATUS,RP0 ; Tria el banc 0 movf ValCCP1CON,w ; Agafa la configuració de CCP1CON andlw b'11001111' ; Posa els bits que corresponen a DC1B a zero per precaució movwf ValCCP1CON ; I ho torna a guardar swapf ValDC1B,w ; Agafa el valor que ha d'anar a DC1B ; I el guarda, permutat, a W ; Els dos bits han de quedar a les posicions 4-5 andlw b'00110000' ; Posa els altres sis bits a zero per precaució iorwf ValCCP1CON,w ; I ho afegeix a CCP1CON movwf CCP1CON ; Ho posa com a configuració del PWM movf ValCCPR1L,w ; Valor de CCPR1L movwf CCPR1L ; Registre que ens dona l'amplada de tON bcf PIR1,TMR2IF ; Desactiva el bit d'interrupció del Timer 2 bsf T2CON,TMR2ON ; Activa el Timer 2 ; No convé engegar el PWM fins que el Timer 2 no ha fet un cicle btfss PIR1,TMR2IF ; Espera l'activació del bit d'interrupció del Timer 2 goto $-1 bsf STATUS,RP0 ; Tria el banc 1 bcf TRISC,5 ; Posem RC5 (sortida del PWM) com a sortida bcf STATUS,RP0 ; Tria el banc 0 call RetM ; Espera 0,2 s bsf STATUS,RP0 ; Tria el banc 1 bsf TRISC,5 ; Posem RC5 (sortida del PWM) com a entrada ; Fem silenci bcf STATUS,RP0 ; Tria el banc 0 call RetM ; Espera 0,2 s return ...
Aquest mètode és conceptualment més complicat però té l'avantatge que la gestió del so es fa en un segon pla i, per tant, el programa es continua executant mentre sonen les notes. Això, però, implica que la gestió de la durada de la nota (i, si escau, del temps entre notes) no es pot gestionar amb retards.
La funció TocaNota configurarà el timer 2 per tal que faci interrupcions periòdicament. A cada interrupció invertirem la sortida RC5 (corresponent al brunzidor). Per poder comptar la durada de la nota, hi haurà un comptador que permetrà acabar el so quan s'hagin fet un nombre predeterminat d'interrupcions. Un cop acabat el so, es comptaran un altre cop les interrupcions per establir la durada del silenci que, si es desitja, pot ser inexistent.
Atès que la gestió del temps la fa la pròpia interrupció, podria passar que es torni a cridar la funció TocaNota mentre encara està tocant la nota anterior. Si això passa, la funció s'espera a que hagi finalitzat.
Imaginem que volem fer un la (freqüència de 440 Hz) i amb un temps d'activació del 50 %. El període corresponent és:

El temps d'activació serà la meitat del període:

Aquest és el temps que hi haurà d'haver entre una interrupció i la següent. El càlcul del temps del timer 2 el podem fer multiplicant el període del rellotge del microcontrolador (1 μs si no hem canviat la velocitat) per l'invers del postescalador, l'invers del prescalador i el valor que posem a PR2.

Podem escollir qualsevol combinació de valors que ens doni els 1136 μs però els valors que tenen més opcions de variació són PR2 i PostEs, per tant és recomanable buscar la combinació que ens doni el valor més gran possible (però inferior a 255) per a PR2 i, seguidament, el més gran possible per a PostEs. Si agafem 1 com a prescala, el valor més gran de postescala possible és 1/5 i obtindrem el següent valor de PR2:

Ara ens queda definir la durada de la nota. Imaginem que volem que sigui de 0,2 s, això voldrà dir que haurem de repetir aquest semiperíode el següent nombre de cops:

Si volem que després hi hagi un silenci del mateix valor, farem el mateix nombre de cicles. Si no volem silenci farem servir un zero.
La taula següent indica els valors que cal configurar en el PWM per obtenir les notes de l'escala central del piano:

| Nota | Freqüència teòrica (Hz) | Prescalat | Postescalat | PR2 | NS | Freqüència real (Hz) | |||||
| PreEs | PS | PostEs | TOUTPS | ||||||||
| do3 | C4 | 261,626 | 1 | 0 | 1/8 | 7 | 239 | 105 | 261,506 | ||
| do#3 | re b3 | C#4 | Db4 | 277,183 | 1 | 0 | 1/8 | 7 | 225 | 111 | 277,778 |
| re3 | D4 | 293,665 | 1 | 0 | 1/7 | 6 | 243 | 118 | 293,945 | ||
| re#3 | mi b3 | D#4 | Eb4 | 311,127 | 1 | 0 | 1/7 | 6 | 230 | 124 | 310,559 |
| mi3 | E4 | 329,628 | 1 | 0 | 1/6 | 5 | 253 | 132 | 329,381 | ||
| fa3 | F4 | 349,228 | 1 | 0 | 1/6 | 5 | 239 | 139 | 348,675 | ||
| fa#3 | sol b3 | F#4 | Gb4 | 369,994 | 1 | 0 | 1/6 | 5 | 225 | 148 | 370,370 |
| sol3 | G4 | 391,995 | 1 | 0 | 1/6 | 5 | 213 | 156 | 391,236 | ||
| sol#3 | la b3 | G#4 | Ab4 | 415,305 | 1 | 0 | 1/5 | 4 | 241 | 166 | 414,938 |
| la3 | A4 | 440,000 | 1 | 0 | 1/5 | 4 | 227 | 176 | 440,529 | ||
| la#3 | si b3 | A#4 | Bb4 | 466,164 | 1 | 0 | 1/5 | 4 | 215 | 186 | 465,116 |
| si3 | B4 | 493,883 | 1 | 0 | 1/4 | 3 | 253 | 198 | 494,071 | ||
| do4 | C5 | 523,251 | 1 | 0 | 1/4 | 3 | 239 | 209 | 523,013 | ||
La taula següent indica els valors que cal configurar per obtenir tres notes extremes:
| Nota | Freqüència teòrica (Hz) | Prescalat | Postescalat | PR2 | NS | Freqüència real (Hz) | |||||
| PreEs | PS | PostEs | TOUTPS | ||||||||
| do0 | C1 | 32,7032 | 1/4 | 1 | 1/16 | 15 | 239 | 13 | 32,6883 | ||
| re#4 | mi b4 | D#5 | Eb5 | 554,365 | 1 | 0 | 1/4 | 3 | 225 | 222 | 555,556 |
| do7 | C8 | 4186,01 | 1 | 0 | 1 | 0 | 119 | 1681 | 4201,68 | ||
La funció que presentem pot fer qualsevol nota entre el do0 i el re#4. Per aconseguir notes de freqüència més alta només caldria, però, fer que el comptador de cicles (variables numbuc i bucles) puguin comptar valors superiors a 255, és a dir fent servir dos bytes per a aquestes funcions. També cal vigilar-ho en cas que desitgem durades de nota o de silenci superiors a 0,2 s.
La funció següent toca la nota que se li indica durant el temps especificat seguida d'un silenci també especificat. Per seleccionar la nota i la durada, cal escriure els valors corresponents a valPre, valPos, valPR2 i numbuc. Per especificar el silenci posem un valor (calculat igual que numbuc) a numsil. Si hi posem el mateix valor, el silenci durarà el mateix que la nota. Si hi posem un zero no hi haurà silenci
A l'exemple NT la podeu veure en funcionament.
#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 hhem 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 ... 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 ...
; ; 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
Quan s'han de tocar diverses notes el programa es pot tornar força llarg si es va copiant de manera seqüencial cada un dels valors corresponents a la nota i després es crida a la funció TocaNota. Pot ser una bona idea guardar les notes en una taula de la memòria de programa i anar-les llegint d'allà modificant el comptador de programa. Com a referència, es pot consultar l'exemple PC.
També és possible guardar els valors a la memòria de programa i fer una funció que (indicant la posició del primer valor) els llegeixi seqüencialment de la memòria de programa i els guardi als registres corresponents. Com a referència, es pot consultar l'exemple MP.
En el cas de voler tocar una melodia ens trobarem que cada una de les notes es pot tocar diverses vegades. Llavors es pot guardar la melodia a base d'indicar la posició de cada una de les notes guardades. La seqüència de la melodia també es pot guardar en un vector o a la memòria de programa.

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