Programació en pic-as del PIC 16F690

Referència Trucs Perifèrics   Recursos CITCEA
Tutorial Exemples Projectes   Inici

Exemple NT - Fem sonar notes musicals amb interrupcions

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

 

 

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