Free Web Site - Free Web Space and Site Hosting - Web Hosting - Internet Store and Ecommerce Solution Provider - High Speed Internet
Search the Web

Módulo 5 : Manejo de interrupciones

Interrupciones

 

La familia Pic16F87x tiene 13 fuentes de interrupciones los de 28 pines y 14 los de 40 pines. Al aceptarse una interrupción se salva el valor del PC (contador de porgrama) en la pila y se carga aquel con el valor 0004h, que es el Vector de Interrupcion. La mayoría de los recursos o periféricos de que disponen los Pic16F87x son capaces de ocacionar una interrupción, si se programan adecuadamente los bits de los registros que pasamos a describir a continuación.

  1. Desbordamiento del TMR0

  2. Activación de la patita de interrupción RB0/INT

  3. Cambio de estado de una de las cuatro patitas de mas peso del puerto B

  4. Finalización de la escritura de un byte en la EEPROM

Hasta aqui se tienen las mismas causas de interrupción del Pic16F84

  1. Desbordamiento del Timer1

  2. Desbordamiento del Timer2

  3. Captura o comparación en el módulo CCP1

  4. Captura o comparación en el módulo CCP2

  5. Transferencia en la puerta serie Síncrona

  6. Colisión de bus en la puerta serie Síncrona

  7. Fin de la transmisión en el USART

  8. Fin de la recepción en el USART

  9. Fin de la conversión en el conversor A/D

  10. Transferencia en la puerta paralela esclava (Esta causa de interrupción no esta disponible en los Pic16F87x de 28 patitas)

Registro de Control de Interrupciones (INTCON)

Es un registro que podemos leer o escribir y lo lo encontramos en cualquiera de los cuatro bancos, ocupando las direcciones 0x0Bh, 0x8Bh, 0x10Bh, 0x18Bh, respectivamente. Tiene la mision de controlar las interrupciones provocadas por el TMR0, cambio de estado en las cuatro líneas de mas peso de la puerta B y activación de la patita RB0/INT. El bit PEIE actua como una segunda llave parcial de permiso o prohibición de las causas de interrupción que nos estan contenidas en INTCON y que las provocan los restantes periféricos del microcontrolador. GIE es el bit de permiso global de todas las interrupciones.

INTCON REGISTER (ADDRESS 0Bh, 8Bh, 10Bh, 18Bh)


bit 7 GIE: Bit de permiso global de interrupciones

    1 = Enables all unmasked interrupts

    0 = Disables all interrupts

bit 6 PEIE: Bit de permiso de los perifericos que no se controlan con INTCON

    1 = Enables all unmasked peripheral interrupts

    0 = Disables all peripheral interrupts

bit 5 TMR0IE: Bit de permiso de interrución del TMR0

    1 = Enables the TMR0 interrupt

    0 = Disables the TMR0 interrupt

bit 4 INTE : Bit de permiso de la interrución externa por RB0/INT

    1 = Enables the RB0/INT external interrupt

    0 = Disables the RB0/INT external interrupt

bit 3 RBIE: Bit de permiso de interrución por cambio en RB4-RB7

    1 = Enables the RB port change interrupt

    0 = Disables the RB port change interrupt

bit 2 TMR0IF: Señalizador de desbordamiento en TMR0

    1 = TMR0 register has overflowed (must be cleared in software)

    0 = TMR0 register did not overflow

bit 1 INTF: Señalizador de activación de la patita RB0/INT

    1 = The RB0/INT external interrupt occurred (must be cleared in software)

    0 = The RB0/INT external interrupt did not occur

bit 0 RBIF: Señalizador de cambio en RB4 - RB7

    1 = At least one of the RB7:RB4 pins changed state; a mismatch condition will continue to set

              the bit. Reading PORTB will end the mismatch condition and allow the bit to be cleared

             (must be cleared in software).

    0 = None of the RB7:RB4 pins have changed state

Registro de permiso de interrupciones 1 (PIE1)

Contiene los bits que permiten (1) o prohiben (0) las interrupciones provocadas por los periféricos internos del microcontrolador y que no estaban contempladas en INTCON.

Ocupa la dirección 8Ch y para que cumplan su función los bits de PIE1 es necesario que PEIE=1 en INTCON <6>. El bit PSPIE solo es valido en los modelos de 40 pines, manteniéndose a 0 en los que tienen 28 pines.

PIE1 REGISTER (ADDRESS 8Ch)


bit 7 PSPIE: Parallel Slave Port Read/Write Interrupt Enable bit(1)

    1 = Enables the PSP read/write interrupt

    0 = Disables the PSP read/write interrupt

Note 1: PSPIE is reserved on PIC16F873A/876A devices; always maintain this bit clear.

bit 6 ADIE : A/D Converter Interrupt Enable bit

    1 = Enables the A/D converter interrupt

    0 = Disables the A/D converter interrupt

bit 5 RCIE : USART Receive Interrupt Enable bit

    1 = Enables the USART receive interrupt

    0 = Disables the USART receive interrupt

bit 4 TXIE : USART Transmit Interrupt Enable bit

    1 = Enables the USART transmit interrupt

    0 = Disables the USART transmit interrupt

bit 3 SSPIE: Synchronous Serial Port Interrupt Enable bit

    1 = Enables the SSP interrupt

    0 = Disables the SSP interrupt

bit 2 CCP1IE: CCP1 Interrupt Enable bit

    1 = Enables the CCP1 interrupt

    0 = Disables the CCP1 interrupt

bit 1 TMR2IE: TMR2 to PR2 Match Interrupt Enable bit

    1 = Enables the TMR2 to PR2 match interrupt

    0 = Disables the TMR2 to PR2 match interrupt

bit 0 TMR1IE: TMR1 Overflow Interrupt Enable bit

    1 = Enables the TMR1 overflow interrupt

    0 = Disables the TMR1 overflow interrupt

Registro de permiso de interrupciones 2 (PIE2)

Contiene los bits de permiso de interrupción de las tres causas que no figuran en PIE1. La de fin de escritura en la EEPROM, colisión de bus en el modo SSP y producción de una captura o una comparación en el módulo CCP2.

PIE2 REGISTER (ADDRESS 8Dh)


bit 7 Unimplemented: Read as '0'

bit 6 CMIE: Comparator Interrupt Enable bit

    1 = Enables the Comparator interrupt

    0 = Disable the Comparator interrupt

bit 5 Unimplemented: Read as '0'

bit 4 EEIE: EEPROM Write Operation Interrupt Enable bit

    1 = Enable EEPROM write interrupt

    0 = Disable EEPROM write interrupt

bit 3 BCLIE: Bus Collision Interrupt Enable bit

    1 = Enable bus collision interrupt

    0 = Disable bus collision interrupt

bit 2-1 Unimplemented: Read as '0'

bit 0 CCP2IE : CCP2 Interrupt Enable bit

    1 = Enables the CCP2 interrupt

    0 = Disables the CCP2 interrupt

Registros de los señalizadores de interrupciones 1 y 2 (PIR1 y PIR2)

En correspondencia con los bits de permiso/prohibición de las causas de interrupción recogidas en los registros PIE1 y PIE2, existen otros dos registros, PIR1 y PIR2, cuyos bits actuan de señalizadores del momento en el que se origina la causa que provoca la interrupción, independientemente de si está permitida o prohibida. Ocupan las direcciones 0Ch y 0Dh, respectivamente.

PIR1 REGISTER (ADDRESS 0Ch)


bit 7 PSPIF: Parallel Slave Port Read/Write Interrupt Flag bit(1)

    1 = A read or a write operation has taken place (must be cleared in software)

    0 = No read or write has occurred

Note 1: PSPIF is reserved on PIC16F873A/876A devices; always maintain this bit clear.

bit 6 ADIF : A/D Converter Interrupt Flag bit

    1 = An A/D conversion completed

    0 = The A/D conversion is not complete

bit 5 RCIF : USART Receive Interrupt Flag bit

    1 = The USART receive buffer is full

    0 = The USART receive buffer is empty

bit 4 TXIF : USART Transmit Interrupt Flag bit

    1 = The USART transmit buffer is empty

    0 = The USART transmit buffer is full

bit 3 SSPIF: Synchronous Serial Port (SSP) Interrupt Flag bit

    1 = The SSP interrupt condition has occurred, and must be cleared in software before returning

              from the Interrupt Service Routine. The conditions that will set this bit are:

            • SPI

                - A transmission/reception has taken place.

            • I2C Slave

                - A transmission/reception has taken place.

            • I2C Master

                - A transmission/reception has taken place.

                - The initiated START condition was completed by the SSP module.

                - The initiated STOP condition was completed by the SSP module.

                - The initiated Restart condition was completed by the SSP module.

                - The initiated Acknowledge condition was completed by the SSP module.

                - A START condition occurred while the SSP module was idle (Multi-Master system).

                - A STOP condition occurred while the SSP module was idle (Multi-Master system).

    0 = No SSP interrupt condition has occurred

bit 2 CCP1IF: CCP1 Interrupt Flag bit

    Capture mode:

    1 = A TMR1 register capture occurred (must be cleared in software)

    0 = No TMR1 register capture occurred

    Compare mode:

    1 = A TMR1 register compare match occurred (must be cleared in software)

    0 = No TMR1 register compare match occurred

    PWM mode:

        Unused in this mode

bit 1 TMR2IF : TMR2 to PR2 Match Interrupt Flag bit

    1 = TMR2 to PR2 match occurred (must be cleared in software)

    0 = No TMR2 to PR2 match occurred

bit 0 TMR1IF: TMR1 Overflow Interrupt Flag bit

    1 = TMR1 register overflowed (must be cleared in software)

    0 = TMR1 register did not overflow

PIR2 REGISTER (ADDRESS 0Dh)


bit 7 Unimplemented: Read as '0'

bit 6 CMIF: Comparator Interrupt Flag bit

    1 = The Comparator input has changed (must be cleared in software)

    0 = The Comparator input has not changed

bit 5 Unimplemented: Read as '0'

bit 4 EEIF: EEPROM Write Operation Interrupt Flag bit

    1 = The write operation completed (must be cleared in software)

    0 = The write operation is not complete or has not been started

bit 3 BCLIF: Bus Collision Interrupt Flag bit

    1 = A bus collision has occurred in the SSP, when configured for I2C Master mode

    0 = No bus collision has occurred

bit 2-1 Unimplemented: Read as '0'

bit 0 CCP2IF: CCP2 Interrupt Flag bit

    Capture mode:

    1 = A TMR1 register capture occurred (must be cleared in software)

    0 = No TMR1 register capture occurred

Compare mode:

    1 = A TMR1 register compare match occurred (must be cleared in software)

    0 = No TMR1 register compare match occurred

PWM mode:

    Unused

Lógica de Interrupciones:


Ejercicios

 

Ejercicio 20

Diseñar y simular un programa que trabaja la interrupción RB0/INT para ir acumulando los flancos de subida que vayan ingresando por el pin RB0. En este primer ejemplo el bucle principal del programa no “tareas”.

a) Diseño del programa MPLAB

Condiciones:

  • Debe existir una variable “contador” que acumule los pulsos que llegan al RB0/INT. Al inicio del programa la variable ha de ser colocada a 0.

  • Los pulsos son detectados por el flanco de subida.

  • En el programa principal debe existir un bucle que ejecute instrucciones de no operación en forma infinita.

Diagrama de flujo El diagrama de flujo comienza con la configuración del microcontrolador, ingreso al banco 1, allí se configuran los registros INTCON, TRISB y el bit INTEDG del OPTION a fin de detectar pulsos de entrada en RB0/INT por flanco de subida. La rutina de interrupción incrementa la variable CONTADOR en una unidad, y además resetea el flag INTF.




Los valores para los bits del registro INTCON son:

GIE EEIE T0IE INTE RBIE T01F INTF RBIF

1 0 0 1 0 0 0 0 = 0x 90

Código del programa

    list p=16f877

    include "p16f877.inc"

    CONTADOR EQU 0x20 ;POSMEM en la que usaremos una variable

    ORG 0 ;Vector de RESET

    nop

    nop

    goto INICIO ;Alta a la direccion donde se inicia el programa

    ORG 4 ;Vector de INTERRUPCION

    incf CONTADOR,1 ;Contador++

    bcf INTCON,INTF ;Resetea el flag de la interrupcion RB0/INT

    retfie ;Fin rutina de interupcion

INICIO

    bcf STATUS,RP0 ;Ir banco 1

    bcf STATUS,RP1

    clrf TRISA ;PORTA salida

    clrf TRISB ;PORTB salida

    clrf TRISC ;PORTC salida

    clrf TRISD ;PORTD salida

    clrf TRISE ;PORTD salida

    bsf TRISB,0 ;RB0 como entrada

    movlw 0x90

    movwf INTCON ;Configura INTCON

    bsf STATUS,INTEDG ;Detecta flancos de subida que llegan a RB0/INT

    bcf STATUS,RP0 ;Ir banco 0

    bcf STATUS,RP1

    clrf CONTADOR ;Contador=0

BUCLE

    nop ;No operacion

    nop

    goto BUCLE ;Ir a BUCLE

END

b) Simulación MPLAB

Ingrese al MPLAB, cree un proyecto. Luego ingrese el código que se mencionado anteriormente, guárdelo en un archivo . Compile el programa para verificar que este libre de errores.

  • Asigne un botón al RB0/INT en el ASYNCHRONUS STIMULUS.

    Para hacer esta tarea:

  • Ingresar al menú -> DEBUG -> STIMULUS SIMULATOR -> ASYNCHRONUS STIMULUS

  • Para asociar Stim 1(P) a RBO haga clic derecho sobre el botón Stim 1 (P). Elija la opción Assing PIN. Seleccione RB0

  • Asegurece que el tipo de estimulo a ser aplicado sea tipo PULSE.



Abra las ventanas siguientes:

  • Stack Window

  • Special Funcion Register

  • File Register

Acomode las en la ventana a fin que pueda tener una visión de todas ellas a la vez.

  • Proceda a simular el programa ingrese al modo STEP (F7, avance paso a paso ). Avance hasta ingresar a la etiquta “BUCLE”.

  • Con ayuda del mouse simule un pulso en RB0/INT (haga un click en: RBO (P), ventana ASYNCHRONUS STIMULUS). Observara como es que simulador salta a la rutina de interrupción e incrementa el valor de la cuenta CONTADOR (registro 0x0C).

  • Observe el lo que sucede en la ventana STACK WINDOWS.


TRACE POINT



NOTA.- Los TRACE POINTS siempre se muestran en COLOR VERDE. Es posible usar el TRACE POINT en combinación con el BREAK POINT. Desde luego que solo visualizara los datos acumulados hasta encontrar el BREAK POINT.

OBSERVACIONES.-La ventana TRACE MEMORY reporta los cambios operados sobre la linea que ha sido marcada con el TRACE POINTS. Como nuestro objetivo era examinar el valor de CONTADOR pusimos el TRACE POINTS sobre la instrucción “incf CONTADOR,1”.

CUESTIONARIO: Use el simulador para responder las siguientes preguntas:

a) ¿Que es lo que pasa si elimina y/o comenta la línea?

bcf INTCON,INTF En la rutina de interrupción.¿ Porque?

b) ¿Qué es lo que pasaría en la ventana STACK del microcontrolador?

c) ¿Qué es lo que pasa con el bit GIE del registro INTCON cuando entramos a la rutina de interrupción?

Explique que utilidad tiene esto.

d) Si reemplazamos la instrucción:

retfie por la instrucción return.

¿Funcionaría el programa? ¿Porque?. Sugerencia. Observe el valor de GIE.

e) Reemplace la rutina de interrupción para que quede así:

    ORG 4

    incf CONTADOR,1

    bcf INTCON,INTF

    bsf INTCON,GIE

    goto BUCLE

¿Funcionaria el programa? Porque ? Cual es la intención en la ejecución de bsf INTCON, GIE?

¿Qué se puede ver en la ventana de STACK WINDOWS

¿Qué pasa cuando se presenta el overflow del STACK?

Ejercicio 21

Configurar el TMR1 para generar espacios de tiempo de 500ms. Cada vez que se cumpla el tiempo invertir el valor del RC7 (similar a un led intermitente). Emplear la interrupción RB0 para incrementar el valor del PORTC cada vez que llegue una petición.

Definiciones Previas

El PIC16F877 cuenta con 14 causas que pueden originar una interrupción; el uso de interrupciones es importante porque permite realizar varias tareas a la vez. Cuando se produce una interrupción se salva el valor del contador de programa y se carga con el valor 0x04 donde debe estar la rutina de interrupción. Una vez concluída la rutina de interrupción restablece el valor del contador del programa.


     list p=16f877 ;Comando que indica el Pic usado

    include "p16f877.inc" ;Etiquetas genéricas para el Pic16F877

org 0x00 ;Inicio del programa en la posición cero de memoria

    nop ;Libre (uso del debugger)

    goto _inicio ;Ir _inicio

org 0x04 ;Vector de interrupcion

    goto _interrupción ;Ir rutina de interrupcion

_inicio

    bsf STATUS,RP0 ;Ir banco 1

    bcf STATUS,RP1

    clrf TRISA ;PORTA salida

    clrf TRISB ;PORTB salida

    clrf TRISC ;PORTC salida

    clrf TRISD ;PORTD salida

    clrf TRISE ;PORTE salida

    bsf TRISB,0 ;RB0 entrada

    clrf INTCON ;Deshabilitar interrupciones

    clrf PIE1

    clrf PIE2

    bsf INTCON,INTE ;Habiltar la interrupción de RB0

    bcf OPTION_REG,INTEDG ;Flanco de subida en RBO

    bsf INTCON,GIE ;Habilitador general de interrupciones

    bcf STATUS,RP0 ;Ir banco 0

    bcf STATUS,RP1

    movlw b'00110000' ;Contador interno de 16 bits

    movwf T1CON

 

    clrf PORTC ;PORTC=0

_bucle

    bsf PORTC,7 ;RC7 = 1

    call _retardo ;Retardo de 500 ms

    bcf PORTC,7 ;RC7 = 0

    call _retardo ;Retardo de 500 ms

    goto _bucle ;Ir bucle

_retardo

    bcf PIR1,TMR1IF ;Borrar la bandera de desborde

    clrf TMR1H ;TMR1H = 0

    movlw 0xa ;TMR1L = 10

    movwf TMR1L

    bsf T1CON,TMR1ON ;Habilita el TMR1

_espera

    btfss PIR1,TMR1IF ;Verificar el desborde

    goto _espera ;Si no ir _espera

    bcf T1CON,TMR1ON ;Si desborda: limpiar bandera de desborde

    return ;Retorno

_interrupción ;Rutina de interrupcion

    bcf INTCON,INTF ;Borra flag de interrupcion RBO

    btfsc PORTC,7 ;RC7 = 0

    goto _compara ;No, ir _compara

    movlw 0x7f ;PORTC = 0x7f?

    subwf PORTC,W

    btfss STATUS,Z

    goto _salida ;No, ir _salida

    clrf PORTC ;Si, PORTC = 0

    retfie ;Fin interrupcion

_compara

    movlw 0Xff ;PORTC = 0xff?

    subwf PORTC,W

    btfss STATUS,Z

    goto _salida ;No, ir _salida

    clrf PORTC ;Si, PORTC = 0

    bsf PORTC,7 ;RC7 = 1

    retfie ;Fin interrupcion

_salida

    incf PORTC,F ;PORTC = PORTC + 1

    retfie ;Fin interrupcion

    END

Ejercicio 22

Configurar el canal AN0 del ADC para mostrar en forma permanente el valor de conversión en el puerto C. Cada vez que llegue una interrupción provocada por el hiperterminal el microcontrolador enviará a la PC el valor actual del ADC.

Durante la ejecucion de las interupciones se suele cambiar algunos valores por efecto de la ejecución de una instruccion (por ejemplo el STATUS se modifica cuando ejecutamos una instrucción). El contexto o los registros importantes deben guardarse al inicio de la rutina de interrupción y deben restituirse antes de salir de la misma. Por eso es que el fabricante sugiere guardar al menos los siguientes registros:

 




    list p=16f877 ;Comando que indica el Pic usado

    include "p16f877.inc" ;Etiquetas genéricas para el Pic16F877


    _int_save_W EQU 0x20 ;Var para guardar W

    _int_save_STATUS EQU 0x21 ;Var para guardar STATUS

    _int_save_FSR EQU 0x22 ;Var para guardar FSR

    _int_save_PCLATH EQU 0x23 ;Var para guardar PCLATH

    _int_save_OPTION_REG EQU 0x24 ;Var para guardar OPTION_REG

org 0x00 ;Inicio del programa en la posición cero de memoria

    nop ;Libre (uso del debugger)

    goto _inicio ;Ir _inicio

org 0x04 ;Vector de interrupcion

    movwf _int_save_W ;Guardar W

    swapf STATUS,W ;Guardar STATUS

    movwf _int_save_STATUS

    swapf FSR,W ;Guardar FSR

    movwf _int_save_FSR

    swapf PCLATH,W ;Guardar PCLATH (Pagina de programa)

    movwf _int_save_PCLATH

    swapf OPTION_REG,W ;Guardar OPTION_REG (Bancos)

    movwf _int_save_OPTION_REG

    goto _interrupción ;Ir rutina de interrupcion

_inicio

    bcf STATUS,RP0 ;Ir banco 0

    bcf STATUS,RP1

    movlw b'01000001' ;A/D conversion Fosc/8

    movwf ADCON0

    bsf STATUS,RP0 ;Ir banco 1

    bcf STATUS,RP1

    clrf TRISA ;PORTA salida

    clrf TRISB ;PORTB salida

    clrf TRISC ;PORTC salida

    clrf TRISD ;PORTD salida

    clrf TRISE ;PORTE salida

    bcf TRISC,6 ;RC6/TX salida, pin de transmisión

    bsf TRISC,7 ;RC7/Rx entrada, pin de recepción

    movlw d'25' ;2400 baud rate Xtal=4Mhz

    movwf SPBRG

    bcf TXSTA,BRGH ;Selección de baja velocidad

    bcf TXSTA,SYNC ;Modo asíncrono

    movlw b'00001110' ;A/D Port AN0/RA0

    movwf ADCON1

    bsf TRISA,0 ;RA0 linea de entrada para el ADC

    clrf INTCON ;Deshabilitar interrupciones

    clrf PIE1

    clrf PIE2

    bsf PIE1,RCIE ;Habilita INTR Recepcion Serial

    bsf INTCON,PEIE ;Habilita INTR perifericos

    bsf INTCON,GIE ;Habilitador general de interrupciones

    bcf STATUS,RP0 ;Ir banco 0

    bcf STATUS,RP1

    bsf RCSTA,SPEN ;habilita el puerto serie

    bsf STATUS,RP0 ;Ir banco 1

    bcf STATUS,RP1

    bcf TXSTA,TX9 ;8 bits de datos a transmitir

    bsf TXSTA,TXEN ;Activa la transmisión serial, TXIF = 1

    bcf STATUS,RP0 ;Ir banco 0

    bcf STATUS,RP1

    bcf RCSTA,RX9 ;8 Bits de datos

    bsf RCSTA,CREN ;Para Rx Continuo

    clrf PORTC ;PORTC=0

 

_bucle

    bsf ADCON0,GO ;Start A/D conversion

_espera

    btfsc ADCON0,GO ;ADCON0 es 0? (la conversion esta completa?)

    goto _espera ;No, ir _espera

    movf ADRESH,W ;Si, W=ADRESH

    movwf PORTC ;Muestra el resultado en PORTC

    goto _bucle ;Ir bucle

_interrupción ;Rutina de interrupcion

    bcf INTCON,PEIE ;Deshabilita INTR perifericos

    movfw ADRESH ;W= ADC

    movwf TXREG ;Transmitir dato, TXREG = W

_esperatx

    btfss PIR1,TXIF ;Espera hasta que transmisión culminó

    goto _esperatx ;No, ir _esperatx

    movf RCREG,W ;Limpia el flag de interrupcion RCIF =0

    bsf INTCON,PEIE ;Habilita INTR perifericos

    swapf _int_save_OPTION_REG,W ;Restaurar valor de OPTIO_REG

    movwf OPTION_REG

    swapf _int_save_PCLATH,W ;Restaurar valor de PCLATH

    movwf PCLATH

    swapf _int_save_FSR,W ;Restaurar valor de FSR

    movwf FSR

    swapf _int_save_STATUS,W ;Restaurar valor de STATUS

    movwf STATUS

    swapf _int_save_W,W

    retfie

END

 

Diseñe un programa en el Pic16F877 que funcione con la interrupción del USART. Si desde el hiperterminal se presiona la tecla ‘A’ RC0 = 1, ‘a’ RC0 = 0, ‘B’ RC1 = 1, ‘b’ RC1 = 0, ‘C’ RC2 = 1, ‘c’ RC2 = 0.


   list p=16f877 ;Comando que indica el Pic usado

     include "p16f877.inc" ;Etiquetas genéricas para el Pic16F877

      _int_save_W EQU 0x20 ;Var para guardar W

    _int_save_STATUS EQU 0x21 ;Var para guardar STATUS

     _int_save_FSR EQU 0x22 ;Var para guardar FSR

     _int_save_PCLATH EQU 0x23 ;Var para guardar PCLATH

     _int_save_OPTION_REG EQU 0x24 ;Var para guardar OPTION_REG

    tecla EQU 0x25

    indice EQU 0x26

 

org 0x00 ;Inicio del programa

    nop ;Libre (uso del debugger)

    goto _inicio ;Ir _inicio

 

org 0x04 ;Vector de interrupcion

    movwf _int_save_W ;Guardar W

    swapf STATUS,W ;Guardar STATUS

    movwf _int_save_STATUS

    swapf FSR,W ;Guardar FSR

    movwf _int_save_FSR

    swapf PCLATH,W ;Guardar PCLATH (Pagina de programa)

    movwf _int_save_PCLATH

    swapf OPTION_REG,W ;Guardar OPTION_REG (Bancos)

    movwf _int_save_OPTION_REG

    goto _interrupción ;Ir rutina de interrupcion

 

_inicio

    bsf STATUS,RP0 ;Ir banco 1

    bcf STATUS,RP   1     

    clrf TRISA ;PORTA salida

    clrf TRISB ;PORTB salida

    clrf TRISC ;PORTC salida

    clrf TRISD ;PORTD salida

    clrf TRISE ;PORTE salida

    

    bcf TRISC,6 ;RC6/TX salida, pin de transmisión

    bsf TRISC,7 ;RC7/Rx entrada, pin de recepción

    movlw d'25' ;2400 baud rate Xtal=4Mhz

    movwf SPBRG

    bcf TXSTA,BRGH ;Selección de baja velocidad

    bcf TXSTA,SYNC ;Modo asíncrono

 

    clrf INTCON ;Deshabilitar interrupciones

    clrf PIE1

    clrf PIE2

    

  bsf PIE1,RCIE ;Habilita INTR Recepcion Serial

    bsf INTCON,PEIE ;Habilita INTR perifericos

    bsf INTCON,GIE ;Habilitador general

                              ;de interrupciones

 

    bcf STATUS,RP0 ;Ir banco 0

  bcf STATUS,RP1

    bsf RCSTA,SPEN ;habilita el puerto serie

 

    bsf STATUS,RP0 ;Ir banco 1

    bcf STATUS,RP1

 

    bcf TXSTA,TX9 ;8 bits de datos a transmitir

    bsf TXSTA,TXEN ;Activa la transmisión serial TXIF=1

 

    bcf STATUS,RP0 ;Ir banco 0

    bcf STATUS,RP1

    bcf RCSTA,RX9 ;8 Bits de datos

    bsf RCSTA,CREN ;Para Rx Continuo

 

    clrf PORTC ;PORTC=0

 

_bucle goto _bucle ;Ir bucle

 

_interrupción ;Rutina de interrupcion

    bcf INTCON,PEIE ;Deshabilita INTR perifericos

    movf RCREG,W ;Limpia el flag de interrup RCIF =0

    movwf tecla

    clrf indice

 _busca_tecla

    movfw indice

    call _teclas

    subwf tecla,W

    btfsc STATUS,Z

    goto _sigue

    incf indice,F

    movlw D'6'

    subwf indice,W

    btfsc STATUS,Z

    goto _retorno

    goto _busca_tecla

_sigue

    movf indice,W

    call _salidas

    movfw tecla

    movwf TXREG ;Transmitir dato, TXREG = W

 

_esperatx

    btfss PIR1,TXIF ;Espera hasta que transmisión culminó

    goto _esperatx ;No, ir _esperatx

 

_retorno

    bsf INTCON,PEIE ;Habilita INTR perifericos

    swapf _int_save_OPTION_REG,W ;Restaurar valor de OPTIO_REG

    movwf OPTION_REG

    swapf _int_save_PCLATH,W ;Restaurar valor de PCLATH

    movwf PCLATH

    swapf _int_save_FSR,W ;Restaurar valor de FSR

    movwf FSR

    swapf _int_save_STATUS,W ;Restaurar valor de STATUS

    movwf STATUS

    swapf _int_save_W,W

    retfie

 

_teclas

    addwf PCL,F ;pcl + W >>>> W

                         ;El PCL se incrementa con el valor

                         ;de W proporcionando

                         ;un salto

    retlw A'A' ;retorna con valores para PORTC

    retlw A'B'

    retlw A'C'

    retlw A'a'

    retlw A'b'

    retlw A'c'

 

_salidas

    addwf PCL,F ;pcl + W >>>> W

                        ;El PCL se incrementa con el valor

                        ;de W proporcionando

                        ;un salto

    goto _on_RC0

    goto _on_RC1

    goto _on_RC2

    goto _off_RC0

    goto _off_RC1

    goto _off_RC2

 

_on_RC0 bsf PORTC,0

    return

_on_RC1 bsf PORTC,1

    return

_on_RC2 bsf PORTC,2

    return

_off_RC0 bcf PORTC,0

    return

_off_RC1 bcf PORTC,1

    return

_off_RC2 bcf PORTC,2

    return

 

END