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