LIST P=16F887 ; MODELO DE PIC QUE ESTAMOS UTILIZANDO
INCLUDE <P16F887.INC> ; Fichero de definición que proporciona el fabricante, donde se
LIST
FRQ EQU 0x52 ; Variable para trabajar con la frecuencia
PDel0 EQU 0X53 ;
PDel1 EQU 0X54 ;
PDel2 EQU 0X55 ;
AUX EQU 0x58 ; Variable para trabajos auxilires
AUX_T2CON EQU 0X59
AUX_PR2 EQU 0X60
AUX_CCPR1L EQU 0X61
ORG 0x00 ; Dirección de comienzo del programa
goto inicio
ORG 0x04 ; Vector de interrupción (pag. 216 datasheet)
goto ServicioInterrupcion
inicio
;--------------------------------------------------------------------------------
; Inicialización de los valores para el correcto funcionamiento del PIC
; Se selecciona el banco 3
bsf STATUS,5 ; Pone a 1 el bit 5 (RP0) de STATUS y
bsf STATUS,6 ; Pone a 1 el bit 6 (RP1) de STATUS
clrf ANSEL
clrf ANSELH ; Se limpia este registro para activar las entradas
; como digitales en el PORTB
; Se selecciona el banco 0
bcf STATUS,5 ; Pone a 0 el bit 5 (RP0) de STATUS y
bcf STATUS,6 ; Pone a 0 el bit 6 (RP1) de STATUS
clrf PORTB ; Limpia el puerto B
clrf PORTC ; Limpia el puerto C
clrf PORTD ;Limpia el puerto D
clrf INTCON
clrf PIR2
movlw b'00001100' ; Combinación para selecccionar modo PWM
movwf CCP1CON ; Configura el PIC para trabajar en modo PWM da la señal PWM en la patilla RC2
; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
bsf STATUS,5 ; Pone a 1 el bit 5 (RP0) de STATUS y
bcf STATUS,6 ; Pone a 0 el bit 6 (RP1) de STATUS
movlw b'01000000' ;configura el reloj interno a 1MHz
movwf OSCCON
clrf TRISC ; puertas activadas como salidas
clrf TRISA ; puertas activadas como salidas
movlw b'00111111' ; W<-- (binario) puertas activadas como entradas
movwf TRISB ; W--> TRISB
clrf TRISD ; puertas activadas como salidas (LEDs de verificación)
clrf TRISE ; puertas activadas como salidas
bcf OPTION_REG,7 ; se activa las resistancias pull-up del puerto b
movlw b'00111111'
movwf WPUB ; pull up
movlw b'00111111' ; Habilita las interrupciones en los pin 0-6
movwf IOCB
; Se selecciona el banco 0
bcf STATUS,5 ; Pone a 0 el bit 5 (RP0) de STATUS y
bcf STATUS,6 ; Pone a 0 el bit 6 (RP1) de STATUS
clrf PORTD
clrf PORTC
movlw b'00001100' ; Combinación para selecccionar modo PWM
movwf CCP1CON ; Configura el PIC para trabajar en modo PWM da la señal PWM en la patilla RC2
call lee_puertab
call TIMER_interrupcion
;---------------------------------------------------------------------------------
principal
btfss INTCON,7 ; comprueba si bit 7 del registro INTCON es 0, si es 0 ejecuta la siguiente instruccion
call lee_puertab
goto principal
;-------------------------------------------------------------------------------------
;***************************************************************************************
lee_puertab ; Lectura de los interruptores para el ancho del pulso
; Se selecciona el banco 0
bcf STATUS,5
bcf STATUS,6
movf PORTB,W ; W<--PUERTA B. Se introduce el valor binario de los interruptores
andlw b'00001111'
addlw 0x05 ; Si el contenido de W es mayor que 10, al sumarle 5 se pone a uno el bit numero 4
movwf AUX
btfsc AUX,4 ; Si el bit 4 es un uno es porque en los interruptores se ha seleccionado un valor
; en binario mayor de 10, que al sumarle 5 (en la inst.anterior) provoca que el
; bit 4 se ponga a 1 (desbordamiento=numero mayor de 15)
movlw b'00001111' ; Pone como valor maximo 15 -5 = 10
addlw 0x0B ; Complemento a 2 de 5, para restar 5
andlw b'00001111' ; Se toman los 4 bit menos significativos.
; En ellos está el valor de los interruptores en binario (max. 10)
; (0=0%, 1=10%, 2=20%, ....10 =100%)
movwf AUX ; Para no perder el valor actual de W, se guarda su contenido en AUX
movwf PORTD ; Para activar los LEDs del ancho de pulso
;tratamiento de la frecuencia
swapf PORTB,W ; Se intercambian los 4 bit de mayor peso por los de menor peso del PORTB
andlw b'00000011' ; Se toman los 2 bit de menor peso donde se tiene la frecuencia seleccionada
; de la siguiente forma: 1X (5 kHz=200us), 01 = (1 kHz=1ms) y 00 = (100 Hz=10 ms)
movwf FRQ ; Se guarda el valor de la freq. seleccionada en la variable auxiliar FRQ
call trata_frq ; Se llama a la rutina que trata la frecuencia
; Se selecciona el banco 0
bcf STATUS,5
bcf STATUS,6
movf AUX,w ; Se recupera el valor que tenia W antes de tratar la frecuencia
call tabla
movwf AUX_CCPR1L ; Pag. 129 datasheet. Se selecciona el ancho del pulso
movlw b'00000000'
movwf PIR1 ;Limpia el flag de interrupcion cuando coinciden timer2 con pr2
; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
bsf STATUS,5 ; Pone a 1 el bit 5 (RP0) de STATUS y
bcf STATUS,6 ; Pone a 0 el bit 6 (RP1) de STATUS
movlw b'00000010'
movwf PIE1 ; Activa la interrupcion cuando coinciden timer2 con pr2
movlw b'11000000' ; Se habilitan las interrupciones
movwf INTCON
return
;***********************************************************************************
;--------------------------------------------------------------------------------------
;*************************** Rutina tratamiento de la frecuencia **********************
;--------------------------------------------------------------------------------------
; Como el PIC trabaja a 1MHz, el Timer2 evoluciona cada microsegundo pues los
; impulsos aplicados a TMR0 provienen de la señal de reloj interna (Fosc/4)
; f= 41Mhz, Tcm=periodo ciclo maquina, Tcm=4 Tosc , Tcm=4*1/f=4*1/4Mhz=1us.
; Temporizacion 200 us=4*Tcm*prescaler*(PR2 -1)
; 200=4*1*1*(PR2-1) --> PR2=49 --> se midio con osciloscopio y se observo suficiente precision
; (pag. 82 datasheet)
; PWMperiodo=(PR2+1)*4*Tosc*(TMR2 prescale value)
trata_frq
movlw b'00000000' ; si '00' (100 Hz=10 ms)
xorwf FRQ,W
btfsc STATUS,Z
goto ejec0.1k
movlw b'00000001' ; si '01' (1 kHz=1ms)
xorwf FRQ,W
btfsc STATUS,Z
goto ejec1k
ejec5k movlw b'00000000' ; Se suma 0 al desplazamiento de la tabla
movwf FRQ ; Se pone en FRQ el desplazamiento a sumar en la tabla
; Seleccion frecuencia
movlw b'00000000' ; preescaler=1
movwf AUX_T2CON ; Pag. 82 del datasheet
; LED verificación
bsf PORTD,6 ; Se pone a 1 el bit 6 PORTD
bcf PORTD,5 ; Se pone a 0 el bit 5 PORTD
bcf PORTD,4 ; Se pone a 0 el bit 4 PORTD
; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
bsf STATUS,5 ; Pone a 1 el bit 5 (RP0) de STATUS y
bcf STATUS,6 ; Pone a 0 el bit 6 (RP1) de STATUS
movlw .46 ; 49 para el registro PR2 (46 valor comprobado con el osciloscopio)
movwf AUX_PR2
goto fin_frq
ejec1k movlw b'00001011' ; Se suma 11 al desplazamiento de la tabla
movwf FRQ ; Se pone en FRQ el desplazamiento a sumar en la tabla
; Selección frecuencia
movlw b'00000000' ; preescaler=1
movwf AUX_T2CON ; Pag. 82 del datasheet
; LED verificación
bcf PORTD,6 ; Se pone a 0 el bit 6 PORTD
bsf PORTD,5 ; Se pone a 1 el bit 6 PORTD
bcf PORTD,4 ; Se pone a 0 el bit 6 PORTD
; Se selecciona el banco 1 de la memoria de datos para acceder a los registros TRIS
bsf STATUS,5 ; pone a 1 el bit 5 (RP0) de STATUS y
bcf STATUS,6 ; pone a 0 el bit 6 (RP1) de STATUS
movlw .236 ; 249 para el registro PR2 (236 valor comprobado con el osciloscopio)
movwf AUX_PR2
goto fin_frq
ejec0.1k
movlw b'00010110' ; Se suma 22 al desplazamiento de la tabla
movwf FRQ ; Se pone en FRQ el desplazamiento a sumar en la tabla
; Selección frecuencia
movlw b'00000011' ; preescaler=16
movwf AUX_T2CON ; Pag. 82 del datasheet
; LED verificación
bcf PORTD,6 ; Se pone a 0 el bit 6 PORTD
bcf PORTD,5 ; Se pone a 0 el bit 6 PORTD
bsf PORTD,4 ; Se pone a 1 el bit 6 PORTD
; Se selecciona el banco 1 de la memoria de datos para acceder a los registros TRIS
bsf STATUS,5 ; Pone a 1 el bit 5 (RP0) de STATUS y
bcf STATUS,6 ; Pone a 0 el bit 6 (RP1) de STATUS
movlw .146 ; 155 para el registro PR2 (146 valor comprobado con el osciloscopio)
movwf AUX_PR2
fin_frq
return
;----------------------------------------------------------------------------------------------
;*****************************************************************************************
;-----------------------------------------------------------------------------------------
;___________________________________________________________________________________________
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tabla
addwf FRQ,0
addwf PCL,1 ; PCL contador de programa pg. 37
retlw .0
retlw .5
retlw .9
retlw .14
retlw .18
retlw .23
retlw .28
retlw .33
retlw .38
retlw .42
retlw .47
;tab1k
retlw .0
retlw .24
retlw .47
retlw .70
retlw .95
retlw .118
retlw .142
retlw .165
retlw .189
retlw .212
retlw .237
;tab01k
retlw .0
retlw .15
retlw .29
retlw .44
retlw .58
retlw .73
retlw .88
retlw .102
retlw .117
retlw .131
retlw .147
return
;------------------------------------------------------------------------------
;******************* RUTINA TRATAMIENTO DE LA INTERRUPCION ********************
;------------------------------------------------------------------------------
ServicioInterrupcion
; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
bsf STATUS,5 ; Pone a 1 el bit 5 (RP0) de STATUS y
bcf STATUS,6 ; Pone a 0 el bit 6 (RP1) de STATUS
btfsc PIE1,1 ; comprueba si bit 1 del registro PIE es 1, si es 1 ejecuta la siguiente instruccion
goto TIMER_interrupcion
goto PORTB_interrupcion
PORTB_interrupcion
; Se selecciona el banco 0
bcf STATUS,5
bcf STATUS,6
movf PORTB,W ; Se lee el puerto B
movlw b'00000000'
movwf INTCON ; Se limpia el flag de interrupcion
; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
bsf STATUS,5 ; Pone a 1 el bit 5 (RP0) de STATUS y
bcf STATUS,6 ; Pone a 0 el bit 6 (RP1) de STATUS
; movlw b'00000000'
; movwf IOCB ; Se deshabilitan el puerto B como interrupciones
; movlw b'00000000'
; movwf PIE1 ;DesActiva la interrupcion cuando coinciden timer2 con pr2
return
TIMER_interrupcion
; Se selecciona el banco 0
bcf STATUS,5
bcf STATUS,6
clrf T2CON
clrf TMR2
clrf INTCON
; Se selecciona el banco 1 de la memoria de datos para acceder al registro TRIS
bsf STATUS,5 ; Pone a 1 el bit 5 (RP0) de STATUS y
bcf STATUS,6 ; Pone a 0 el bit 6 (RP1) de STATUS
clrf PIE1 ;DesActiva la interrupcion cuando coinciden timer2 con pr2
movf AUX_PR2,W
movwf PR2
; Se selecciona el banco 0
bcf STATUS,5
bcf STATUS,6
clrf PIR1 ;limpia el flag de reconocimiento de TIMER2 = PR2
bcf PIR1,TMR2IF
movf AUX_T2CON,W
movwf T2CON
movf AUX_CCPR1L,w
movwf CCPR1L ; Pag. 129 datasheet. Se selecciona el ancho del pulso
bcf PIR1,TMR2IF
bsf T2CON,TMR2ON ; se activa el timer 2
clrf PIR1 ;limpia el flag de reconocimiento de TIMER2 = PR
movf PORTB,W ; Se lee el puerto B
movlw b'10001000' ; Activa interrupción global y la pone activa
movwf INTCON
retfie
END ; Directiva final del programa