Ensamblador 7: Prioridades de interrupción

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
Menú