En aquest exemple farem servir el PWM 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.
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
Retard1 EQU 0x20 ; Variables de retard Retard2 EQU 0x21 ValPR2 EQU 0x22 ; Aquí hi guardarem el valor de PR2 ValCCPR1L EQU 0x23 ; Aquí hi guardarem el valor de CCPR1L ValDC1B EQU 0x24 ; Aquí hi guardarem el valor de DC1B ValCCP1CON EQU 0x25 ; Aquí hi guardarem el valor de CCP1CON
PSECT code, class=CODE, delta=2, abs
main:
bsf RP0 ; Tria el banc 1
movlw 00100000B ; Definim com volem les E/S del port C
movwf TRISC ; RC5 (sortida del PWM) com a entrada
bcf RP0 ; Tria el banc 0
clrf PORTC ; Desactiva les sortides del port C
movlw 00001100B ; 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 00000011B ; 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
Bucle:
movlw 238 ; Valor que correspon aproximadament a do3
movwf ValPR2 ; Ho posem com a valor de PR2
movlw 119 ; Valor que correspon a un cicle del 50 %
movwf ValCCPR1L ; Valor de CCPR1L
movlw 2 ; Valor dels bits de menys pes del CCP
movwf ValDC1B ; Valor de DC1B
call TocaNota ; Toca la nota configurada
movlw 212 ; Valor que correspon aproximadament a re3
movwf ValPR2 ; Ho posem com a valor de PR2
movlw 106 ; Valor que correspon a un cicle del 50 %
movwf ValCCPR1L ; Valor de CCPR1L
movlw 2 ; Valor dels bits de menys pes del CCP
movwf ValDC1B ; Valor de DC1B
call TocaNota ; Toca la nota configurada
movlw 189 ; Valor que correspon aproximadament a mi3
movwf ValPR2 ; Ho posem com a valor de PR2
movlw 95 ; Valor que correspon a un cicle del 50 %
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
call RetM ; Espera 0,2 s
goto Bucle
TocaNota:
movf ValPR2,w ; Valor de PR2 per a la nota desitjada
bsf 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 RP0 ; Tria el banc 0
movf ValCCP1CON,w ; Agafa la configuració de CCP1CON
andlw 11001111B ; 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 00110000B ; 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 TMR2IF ; Desactiva el bit d'interrupció del Timer 2
bsf TMR2ON ; Activa el Timer 2
; No convé engegar el PWM fins que el Timer 2 no ha fet un cicle
btfss TMR2IF ; Espera l'activació del bit d'interrupció del Timer 2
goto $-1
bsf RP0 ; Tria el banc 1
bcf TRISC,5 ; Posem RC5 (sortida del PWM) com a sortida
bcf RP0 ; Tria el banc 0
call RetM ; Espera 0,2 s
bsf RP0 ; Tria el banc 1
bsf TRISC,5 ; Posem RC5 (sortida del PWM) com a entrada
; Fem silenci
bcf RP0 ; Tria el banc 0
call RetM ; Espera 0,2 s
return
RetM: ; Funció de retard de 0,2 s
decfsz Retard1,f
goto RetM
decfsz Retard2,f
goto RetM
return
END main

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