| |||||||
|
|
|
| |||||
|
| |||||||
Módulo 5 : Manejo de 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.
Desbordamiento del TMR0
Activación de la patita de interrupción RB0/INT
Cambio de estado de una de las cuatro patitas de mas peso del puerto B
Finalización de la escritura de un byte en la EEPROM
Hasta aqui se tienen las mismas causas de interrupción del Pic16F84
Desbordamiento del Timer1
Desbordamiento del Timer2
Captura o comparación en el módulo CCP1
Captura o comparación en el módulo CCP2
Transferencia en la puerta serie Síncrona
Colisión de bus en la puerta serie Síncrona
Fin de la transmisión en el USART
Fin de la recepción en el USART
Fin de la conversión en el conversor A/D
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

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:
|
|
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. |
|
|
|
|
Abra las ventanas siguientes:
Acomode las en la ventana a fin que pueda tener una visión de todas ellas a la vez. |
|

TRACE POINT
Resetee el programa (DEBUG->RUN->RESET)
Coloque el mouse sobre la línea “bcf INTCON,INTF” , click izquierdo, BREAK POINT
Cree un punto de revisión (TRACE POINT)
Coloque el mouse sobre la instrucción “incf CONTADOR,1”, click izquierdo, TRACE POINT

Abra la ventana TRACE WINDOWS (menú Windows -> Trace Memory)
Ahora corra el programa (click sobre el semáforo verde). Ingrese 5 pulsos en el pin RB0/INT del microcontrolador.
Detenga el programa (click en el SEMAFORO ROJO).
Observe que aparece en la ventana TRACE MEMORY.
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