En muchas ocasiones nuestros programas necesitan realizar varias tareas y algunas pueden ser más importantes que otras, es por eso que cuando trabajamos con interrupciones podemos declarar diferentes prioridades para ellas, entre más alta sea su prioridad más importante es la tarea a realizar, entonces si se activa una interrupción de alta prioridad, no importa lo que esté realizando nuestro programa (incluso aunque esté realizando otra función de interrupción de baja prioridad) saltará a la función correspondiente y después regresará a donde estaba.
En este caso vamos a utilizar nuestro ADC, pero activaremos las interrupciones del mismo, las cuales nos avisarán cuando el dato recibido en el ADC esté listo para ser utilizado, esta será nuestra interrupción de baja prioridad, nuestra interrupción de alta prioridad será activada por desborde de timer, el cual congelará el sistema por un segundo, sin importar lo que esté realizado nuestro programa.
Lo primero que haremos será definir los vectores tanto para las interrupciones de baja prioridad como los de alta prioridad, este dato se puede encontrar en la hoja de datos, y se hará de la siguiente forma:
ORG 0x0008
goto ISR_H
ORG 0x0018
goto ISR_L
El vector 0x0008 para alta prioridad y el vector 0x0018 para baja prioridad, posteriormente definiremos lo que se hará en cada función de interrupción.
Ahora vamos a configurar tanto el timer0 como el ADC, así como las interrupciones de alta y baja prioridad.
INICIO movlw 0x00 movwf TRISB ;Puerto B como salida movlw 0x00 movwf TRISE ;Puerto E como salida movlw 0x07 movwf PORTE ;Apago el led RGB movlw 0x84 movwf T0CON ;Configura timer0, prescaler, 16 bits bsf INTCON,7;Habilitar interrupciones de alta prioridad bsf INTCON,5;Habilitar interrupciones por desborde movlw 0x00 movwf adc_result ;Reinicio adc_result ;Inicialización del ADC movlw 0x0E movwf ADCON1 movlw 0x00 movwf ADCON0 movlw 0x08 movwf ADCON2 bsf ADCON0,ADON
Ahora habilitaremos las interrupciones asociadas a la conversión de datos del ADC, esto ser hace mediante los registros PIR1, PIE1, IPR1, INTCON, ADCON y RCON, puedes encontrar más detalle de estos registros en la sección 9 de la hoja de datos.
;INTERRUPCIONES DEL ADC
bcf PIR1,ADIF ;Limpio bit bandera
bsf PIE1,ADIE ;Habilito bit enable
bcf IPR1,ADIP ;Limpio bit de prioridad (low priority)
bsf INTCON,6 ;Habilito interrupciones baja prioridad
bsf ADCON0,GO_DONE ;Comienzo conversion
bsf RCON,IPEN ;Habilito niveles de prioridad
Ahora definiremos las funciones de interrupción, para el fin de conversión del ADC y el desborde del timer:
ISR_H
call RETARDO1s ;Congelo el sistema 1 segundo
movff adc_result,PORTB ;Muestro en los leds el valor del ADC guardado
bcf INTCON,TMR0IF ;Limpia la bandera del timer
bsf INTCON,7 ;Habilito interrupciones alta prioridad
return ;Regreso
ISR_L
bcf PIR1,ADIF ;Limpia la bandera del ADC
bsf INTCON,6 ;Habilita interrupciones baja prioridad
movff ADRESH,adc_result ;Leo el valor del ADC
movff adc_result,PORTB ;Muestro en el puerto B el valor del ADC
bsf ADCON0,GO_DONE ;Habilito conversión del ADC
return
Nuestro código quedará de la siguiente forma:
LIST P = 18F4550 ;PIC a utilizar
INCLUDE <P18F4550.INC>
;************************************************************
;Configuración de fusibles
CONFIG FOSC = HS ;Oscilador de 8MHz
CONFIG PWRT = ON
CONFIG BOR = OFF
CONFIG WDT = OFF
CONFIG MCLRE = ON
CONFIG PBADEN = OFF
CONFIG LVP = OFF
CONFIG DEBUG = OFF
CONFIG XINST = OFF
CBLOCK 0x000
contador
adc_result
ret1
ret2
ret3
ENDC
ORG 0x0000
goto INICIO
ORG 0x0008
goto ISR_H
ORG 0x0018
goto ISR_L
INICIO
movlw 0x00
movwf TRISB ;Puerto B como salida
movlw 0x00
movwf TRISE ;Puerto E como salida
movlw 0x07
movwf PORTE ;Apago el led RGB
movlw 0x84
movwf T0CON ;Configura timer0, prescaler, 16 bits
bsf INTCON,7;Habilitar interrupciones de alta prioridad
bsf INTCON,5;Habilitar interrupciones por desborde
movlw 0x00
movwf adc_result ;Reinicio adc_result
;Inicialización del ADC
movlw 0x0E
movwf ADCON1
movlw 0x00
movwf ADCON0
movlw 0x08
movwf ADCON2
bsf ADCON0,ADON
;INTERRUPCIONES DEL ADC
bcf PIR1,ADIF ;Limpio bit bandera
bsf PIE1,ADIE ;Habilito bit enable
bcf IPR1,ADIP ;Limpio bit de prioridad (low priority)
bsf INTCON,6 ;Habilito interrupciones baja prioridad
bsf ADCON0,GO_DONE ;Comienzo conversion
bsf RCON,IPEN ;Habilito niveles de prioridad
BUCLE
;La función principal de nuestro programa
goto BUCLE
ISR_H
call RETARDO1s ;Congelo el sistema 1 segundo
movff adc_result,PORTB ;Muestro en los leds el valor del ADC guardado
bcf INTCON,TMR0IF ;Limpia la bandera del timer
bsf INTCON,7 ;Habilito interrupciones alta prioridad
return ;Regreso
ISR_L
bcf PIR1,ADIF ;Limpia la bandera del ADC
bsf INTCON,6 ;Habilita interrupciones baja prioridad
movff ADRESH,adc_result ;Leo el valor del ADC
movff adc_result,PORTB ;Muestro en el puerto B el valor del ADC
bsf ADCON0,GO_DONE ;Habilito conversión del ADC
return
RETARDO1s ;Se crea un retardo de 1 segundo
movlw D'255'
movwf ret1
movlw D'255'
movwf ret2
movlw D'11'
movwf ret3
Ret1s
decfsz ret1, F
goto Ret1s
decfsz ret2, F
goto Ret1s
decfsz ret3, F
goto Ret1s
return
END
FUNCIONAMIENTO
