# Interrupciones múltiples en un PIC



## hernan.andres (Nov 26, 2008)

Hola necesito A Y U D A
Estoy utilizando PIC18f452 y el MPLAB con el C18.
Se supone que voy a usar varias interrupciones, tanto externas como de timer, el problema es que no se como incluirlas todas y como asociar una rutina a una interrupcion en particular.

El único ejemplo que he encontrado para el C18 es:

/////////////////////////////////////////////////////////////////////
void timer_isr( void );

#pragma code low_vector = 0x18
void low_vector( void )
{    _asm   GOTO   timer_isr   _ensasm
} 
#pragma code

#pragma interruptlow timer_isr
void timer_isr( void )
{ ........
}
/////////////////////////////////////////////////////////////

-Para crear varias interrupciones de baja prioridad debo crear varios low_vector?
 Si es asi, la direccion 0x18 debo cambiarla para cada nueva interrupccion?
-No veo en donde esta asociada a un timer especifico, en el main del ejemplo utilizan el timer0, pero si tambien utilizo los demas timers tambien se me activaria esta rutina de interrupcion?

- En mi caso creo que tengo los 3 INTCON bien, pero aqui estan por si a caso
        RCONbits.IPEN = 1;                         //no se si ponerlo en 0
	INTCON = 0b11111000;
	INTCON2 = 0b01110000;
	INTCON3 = 0b11011000;

Gracias.


----------



## Ardogan (Nov 26, 2008)

El vector de interrupción es uno solo siempre, mejor dicho dos: uno de alta prioridad y otro de baja.
Digamos que sería:
" _asm GOTO Interrupcion_BajaPrioridad" en vez de " _asm GOTO timer_isr _ensasm "

Dentro de la rutina de interrupción tenés que chequear los flags/banderas de interrupción para saber de donde vino y ejecutar el código correspondiente.

Entonces, supongamos que definimos interrupciones de baja prioridad.  A través de los registros INTCON seteamos la prioridad, luego habilitamos las interrupciones que vayamos a usar bits xxIE de registros INTCON. Limpiamos todos los flags de interrupciones (bits xxIF =0), y habilitamos las interrupciones de baja prioridad (GIEL=1).

A partir de este punto cualquier interrupción de baja prioridad que hayamos habilitado (a través de los bits xxIE) nos llevará a ejecutar la rutina Interrupcion_BajaPrioridad; que podría tener una  estructura de este estilo:

```
void Interrupcion_BajaPrioridad(void){ //IMPORTANTE: nunca una rutina de interrupción toma parámetros 
    //ni devuelve nada, siempre es void Nombrefuncion(void). Para leer o
   //escribir valores se usan variables globales declaradas con la directiva volatile

  if (xxIF == 1){
    xxIF==0;//siempre limpiar el flag al principio, a veces lo hace el mismo hard
   //Codigo de atensión de interrupcion xx
  }
  else if (yyIF==1){//idem que en el if anterior
  }
  //-------  se hacen la cantidad de "else if(){} " que se precise
  else if (zzIF==1){
  }
  else{
  //descartadas todas las interrupciones menos una, 
  //solo queda la posibilidad de la interrupción
  //que provocó la llamada sea la que no se chequeo, 
  //por eso un "else{}" y no un "else if{}"
  }//fin cadena de if's

}//fin rutina interrupción
```

Lo que no recuerdo era si el bit GIEL lo cambiaba directamente el compilador, o si lo tenía que hacer uno a mano... no, se deshabilita GIEL automáticamente y se vuelve a habilitar cuando se termina de ejecutar la rutina de interrupción.
Si uno habilita el GIEL en la rutina de interrupción bien puede pasar que mientras se atiende una interrupción se de otro evento de interrupción y se ejecute nuevamente la rutina de interrupción, que se interrumpiría a sí misma   .

RCONbits.IPEN habilita prioridad de interrupciones: solo dos prioridades alta y baja. Los bits xxIP configuran la prioridad de cada generador de interrupciones.

Bueno, contanos como te va...


----------



## hernan.andres (Nov 27, 2008)

Muchas gracias Ardogan

Estaba hace tiempo buscando como hacerlo.
Ha funcionado a la perfección.


----------



## Ardogan (Nov 27, 2008)

Qué bien! me alegro mucho. Estaría bueno que pongas el código fuente de las interrupciones así queda como ejemplo para otros que tengan la misma duda.

Saludos


----------



## hernan.andres (Dic 12, 2008)

Hola
Sorry por la demora pero estuve fuera un tiempo.
Aca va el codigo que utilice.
Utilizo las interrupciones externas, y ademas necesitaba que se ocurrieran tanto en los cantos de subida como los de bajada por lo que cambio los INTEDGX segun sea el caso.
Lo mismo hice para las de baja donde solo cambia el vector = 0x18 y el pragama interrupt por interruptlow.
Espero que le sea de ayuda a alguna persona.


```
////////////////////////////////////////////////////////////////////////////////////////
void Alta_isr( void );


#pragma code high_vector = 0x08
void H_interrupt( void )
{	_asm     GOTO Alta_isr    _endasm
}
#pragma code

#pragma interrupt Alta_isr
void Alta_isr( void )
{	if( INTCONbits.INT0IF )				
	{	INTCONbits.INT0IF = 0;
		if( INTCON2bits.INTEDG0 )
		{	INTCON2bits.INTEDG0 = 0;
			// Codigo					
		}
		else
		{	INTCON2bits.INTEDG0 = 1;
			//..
		}
		
	}

	if( INTCON3bits.INT1IF )			//S
	{	INTCON3bits.INT1IF = 0;
		if( INTCON2bits.INTEDG1 )
		{	INTCON2bits.INTEDG1 = 0;
			//...
		}
		else
		{	INTCON2bits.INTEDG1 = 1;
			//...	
		}
	}

	if( INTCON3bits.INT2IF )			
	{	INTCON3bits.INT2IF = 0;
		if( INTCON2bits.INTEDG2 )
		{	INTCON2bits.INTEDG2 = 0;
		        //...		
		}
		else
		{	INTCON2bits.INTEDG2 = 1;
			//...	
		}
	}
}
```


----------



## MordorInc (Feb 20, 2009)

Hola,
espero les sirva como template para hacer sus propios programas, el programa esta completo y probado en C18 v3.22

```
/*************************************************************************************
/*	Programa que trabaja con interrupcion por RB0
/*	sin hacer uso de libreria - cambia el estado del pin RA0 cada vez
/* 	que se pulsa en el pin RB0
/*************************************************************************************
/*	desarrollado por Luis Becerra para roboticaID
/************************************************************************************/
#include <p18f4520.h>
#include <timers.h>
/************************************************************************************/
#pragma config OSC = HSPLL, FCMEN = OFF, IESO = OFF                       // CONFIG1H
#pragma config PWRT = OFF, BOREN = SBORDIS, BORV = 3                      // CONFIG2L
#pragma config WDT = OFF, WDTPS = 32768                                   // CONFIG2H
#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = OFF, CCP2MX = PORTC    // CONFIG3H
#pragma config STVREN = ON, LVP = OFF, XINST = OFF, DEBUG = ON            // CONFIG4L
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF                 // CONFIG5L
#pragma config CPB = OFF, CPD = OFF                                       // CONFIG5H
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF             // CONFIG6L
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF                         // CONFIG6H
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF         // CONFIG7L
#pragma config EBTRB = OFF                                                // CONFIG7H
//****************************************************************************************************************************
//				TIPOS DE DATOS
// ****************************************************************************************************************************
#define	LED	LATAbits.LATA0
/*******************************************************************************************************
/*	variables globales
/*******************************************************************************************************/
	char contador;
/******************************************************************************************************* 
/*	Interrupcion con direccion 0x08
/***************************************************************************************************** */
void InterruptServiceHigh(void);
#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh (void)
{
  _asm
    goto InterruptServiceHigh //Salta a la direccion de interrupcion ALTA
  _endasm
}
/******************************************************************************************************* 
/*	Interrupcion con direccion 0x18
/***************************************************************************************************** */
void InterruptServiceLow(void);
#pragma code InterruptVectorLow = 0x18
void InterruptVectorLow (void)
{
  _asm
    goto InterruptServiceLow //Salta a la direccion de interrupcion BAJA
  _endasm
}
/*************************************************************************************
/* 	Programa Principal
/*************************************************************************************/
#pragma code
void main(void)
{
	/* *******************************************
	/* 	Configuro el puerto A como salida digital
	/* ****************************************** */
	ADCON0 = 0X00;		// Manual del pic 18F4520 - DS39631D-page 223 - Modo Analogo
	ADCON1 = 0X0F;		// Manual del pic 18F4520 - DS39631D-page 224 - Modo Analogo
	CMCON = 0X07;		// Manual del pic 18F4520 - DS39631D-page 233 - Modo Comparador
	TRISA = 0X00;
	TRISB = 0X01;		// debo colocar el RB0 como entrada para trabajar la interrupcion
	TRISD = 0X00;	
	PORTA = 0X00;
	PORTB = 0X00;
	PORTD = 0X00;
	/**********************************************************************
	/* 	Interrupcion debido a los pines RB0
	/* ********************************************************************/
	INTCONbits.INT0IE=1;		// INTCON(4); Habilito la interrupcion por el pin RB0
	INTCONbits.INT0IF=0;		// INTCON(1); Coloco el cero el flag de interrupcion por el pin RB0
	INTCON2bits.INTEDG0=1;		// INTCON2(6); Decido con que flanco trabajo; 1: Subida; 0: Bajada
	INTCONbits.GIE=1;			// INTCON(7); Habilito la interrupcion global
	while(1);
  }

/******************************************************************************************************* 
/*	Interrupcion con direccion 0x08
/***************************************************************************************************** */
#pragma interrupt InterruptServiceHigh  // Directiva pragma "interrupt" para interrupcion de alta prioridad
void InterruptServiceHigh(void)
{
	if(INTCONbits.INT0IF)
	{
		LED=~LED;				// invierto el estado del LED
		INTCONbits.INT0IF=0;	// Coloco el cero el flag de interrupcion por el pin RB0
	}
}
/*******************************************************************************************************
******************************************************************************************************** 
/*	Interrupcion con direccion 0x18
/***************************************************************************************************** */
#pragma interruptlow InterruptServiceLow// Directiva pragma "interruptlow" para interrupcion de baja prioridad
void InterruptServiceLow(void)
{
  /**********************
    /* aqui va el programa que corresponde a la interrupcion de baja prioridad
    ***********************/
}
```
Ojla les sirva.
Feliz dia
MordorInc


----------



## miguelamedina (Feb 24, 2011)

Gracias por compartir.
      Saludos.
           Miguel


----------



## alvarotasco (Jul 26, 2013)

Ando trabajando en la generación de una señal pwm desde hace uuff jeje  con el timer 0 la idea es ir variando el ciclo de trabajo, no voy a utilizar los modulos CCP por que necesito generar mas de 2 señales pwm, para arrancar he estado cacharreando con el timer 0 generando una señal cuadrada de frecuencia de 20kHZ, en el momento de hacer el código y simularlo en proteus, no concuerda con los cálculos hechos.. Quiero un desbordamiento de 25us PERO al poner los cursores en el osciloscopio en proteus me sale de 30us Aprox. No se que ando haciendo mal, espero me puedan ayudar anexo código

```
#include <p18f4550.h>
#include <delays.h>

//////////////////Configuaracion de bits//////////////////////////

#pragma config PLLDIV = 1 //En este caso no importa por que vamos a utilizar Oscilador Interno
#pragma config CPUDIV = OSC1_PLL2 ////En este caso no importa por que vamos a utilizar Oscilador Interno
#pragma config USBDIV = 1   /////En este caso no importa por que vamos a utilizar Oscilador Interno
#pragma config FOSC = INTOSCIO_EC  //Configurando oscilador interno_ si se deja por default trabajará a 1Mhz
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRT = OFF
#pragma config BOR = OFF
#pragma config BORV = 0
#pragma config VREGEN = OFF
#pragma config WDT = OFF
#pragma config WDTPS = 16384
#pragma config MCLRE = OFF
#pragma config LPT1OSC = OFF
#pragma config PBADEN = ON
#pragma config CCP2MX = OFF
#pragma config STVREN = OFF
#pragma config LVP = OFF
#pragma config ICPRT = OFF
#pragma config XINST = OFF
#pragma config DEBUG = OFF
#pragma config CP0 = OFF,CP1 = OFF,CP2 = OFF,CP3 = OFF
#pragma config CPB = OFF
#pragma config CPD = OFF
#pragma config WRT0 = OFF,WRT1 = OFF,WRT2 = OFF,WRT3 = OFF
#pragma config WRTB = OFF
#pragma config WRTC = OFF
#pragma config WRTD = OFF
#pragma config EBTR0 = OFF
#pragma config EBTR1 = OFF,EBTR2 = OFF,EBTR3 = OFF

#define  bandera INTCONbits.TMR0IF

void Interrupt_isr_TMR0(void);

//-------------------------------------------------------

void main (void)
{
 //------------Configuracion de puertos--------------------------
    TRISB=0x00;
    LATB=0x00;
    ADCON1=0x0F;  //Todos los pines digitales.

//----------------Configuracion de oscilador interno------------------
    OSCCON=0b01110110;  //Oscilador Interno a 8Mhz
//--------------------------------------------------------
    RCONbits.IPEN=1; //Habilito prioridad de interrupcion.
    INTCONbits.GIE_GIEH=1; //Habilito todas las interrupciones de alta prioridad
    INTCONbits.TMR0IE=1; //Habilito Interrupcion TMR0 por desbordamiento
    bandera=0; //Pongo a cero la bandera de desbordamiento.
//-------------------------------------------------------------
//------------Configurando el Timer0--------------------------
    T0CON=0b11001000;   //Configurado a 8 bits sin prescales
    TMR0L=00;

    while(1){}

    
}

#pragma code HighVector = 0x08

void high_ISR(void){
    _asm goto Interrupt_isr_TMR0 _endasm
}
//Rutina de Interrupciones de alta prioridad

#pragma code
#pragma interrupt Interrupt_isr_TMR0

void Interrupt_isr_TMR0 (void){
    TMR0L=206;   // 256-206= 50 paso: Como se sabe que cada paso es de 500ns 500ns*50=25us el desbordamiento.
    if(bandera==1){
        bandera=0;
        LATBbits.LATB0=!LATBbits.LATB0;
        
    }

 }
```
 
Gracias.

Éxitos a todos


----------



## Ardogan (Jul 26, 2013)

¿La frecuencia con la que está trabajando el pic es de 1 MHz?.
TMR0 solo puede tener una frecuencia de fosc/2 -> 500KHz
1 cuenta de TMR0 = 2 us en vez de 500 ns como dice en los comentarios.

Pero si ese fuera el problema deberías ver el doble de tiempo y no los 30 us. Alguna configuración debe hacer que el pic este a 2 MHz en vez de 1 MHz.
Ahí me doy cuenta que usas 50 cuentas de TMR0 => la frecuencia es de 2 MHz

Esos 5 us "sobrantes" pueden deberse a que es el tiempo necesario que precisa el pic para disparar la rutina de interrupción (salvar contexto: guardar el contador de programa y quizás algo más, ir al vector de interrupción, ejecutar el goto interrupción) y ejecutar el código en la misma (la asignación de TMR0L + evaluación del if y asignación del puerto).

Una prueba que podés hacer si el problema es ese es poner dentro del while(1) del main un retardo del tiempo deseado (25 us) y ver cuanto tiempo tarda, es decir:


Poner a 0 pin del puerto
Poner a 1 pin del puerto -->> generamos un flanco ascendente para el osciloscopio
Llamar a rutina delay optimizada: como el tiempo es pocos ciclos de reloj te diría de poner NOPs uno debajo del otro. Cada NOP requiere 4 ciclos de fosc = 1 fcy -> 50/4 -> 12 NOPs. Pero 1 menos debido a la instrucción siguiente. 11 NOPs => 44 ciclos de reloj
Poner a 0 pin del puerto -> 4 ciclos de reloj.
El tiempo en alto sería el retardo. Eso en teoría debería dar 44 + 4 = 48 ciclos de reloj, con reloj a 2 MHz => 24 us

Por último, la exactitud va a ser tan buena como la del oscilador usado, que para el oscilador interno puede ser tan mala como 10%.


----------



## alvarotasco (Jul 26, 2013)

Ardogan Gracias por responder... Bueno, esos 1MHZ se me olvido borrarlo, eso fue una prueba que hice inicialmente para ver si lo que había leído era cierto, que era que cuando el oscilador se configura como interno (FOSC = INTOSCIO_EC) y no se especifica por medio de registro OSCCON la frecuencia de trabajo, el mismo tomaba como default una frecuencia de 1Mhz.. Pero si nos fijamos bien yo configuro el oscilador a 8Mhz activando los bits del registro OSCCON..

Voy analizar bn lo que dices para ver si puedo solucionar el problema..

Gracias

Exitos a Todos.


----------



## terminator (Sep 9, 2018)

Saludos, he utilizado gracias a ustedes las interrupciones por cambio de estado RB4-RB7 y la RB0, con sus explicaciones logré hacer dos programas independientes  que funcionan a la maravilla; pero tengo una consulta, por ejemplo si necesito NUEVE (9) interrupciones (y sí que las necesito) cómo sería el método? Por favor, alcanzarme algun dato de cómo lograrlo, si es que acaso se puede. El proyecto que quiero implementar es que tengo 9 interruptores (pulsadores) que deben detectar un pulso (5 voltios o 0 voltios) y se le asigna un led y un buzzer, a cada uno y para saber cuál pulsador fue accionado. Gracias de antemano. Utilizo Pic Basic Pro. Saludos.


----------



## Gudino Roberto duberlin (Sep 9, 2018)

Hola, veamos si comprendí.
Quieres implementar 9 pulsadores, sobre el puerto RB4-RB7?
Es decir, debes multiplexar los pulsadores para poder leerlos en 4bits.
Ahora, no estaríamos hablando de 9 interrupciones, sino sólo una. Pues al atender la interrupción por cambio de estado en dicho puerto, la subrutina debe discriminar el botón pulsado.


----------



## DJ T3 (Sep 10, 2018)

Podrias utilizar un integrado similar al MAX7313, I2C y pin de bandera de interrupciones.
Lee el datsheet para comprender lo que digo.
Sino como dice Gudino, en ese caso, pon el codigo de cómo estas implementando las interrupciones y demas


----------



## terminator (Sep 10, 2018)

Gudino Roberto duberlin dijo:


> Hola, veamos si comprendí.
> Quieres implementar 9 pulsadores, sobre el puerto RB4-RB7?
> Es decir, debes multiplexar los pulsadores para poder leerlos en 4bits.
> Ahora, no estaríamos hablando de 9 interrupciones, sino sólo una. Pues al atender la interrupción por cambio de estado en dicho puerto, la subrutina debe discriminar el botón pulsado.


Hola Gudino, gracias por tu respuesta. Lo que quiero es hacer uso de las interrupciones que tienen los pics, mi pregunta es saber si se pueden utilizar 9 en un mismo programa. Voy a analizar lo de la multiplexación. Gracias


DJ T3 dijo:


> Podrias utilizar un integrado similar al MAX7313, I2C y pin de bandera de interrupciones.
> Lee el datsheet para comprender lo que digo.
> Sino como dice Gudino, en ese caso, pon el codigo de cómo estas implementando las interrupciones y demas





DJ T3 dijo:


> Podrias utilizar un integrado similar al MAX7313, I2C y pin de bandera de interrupciones.
> Lee el datsheet para comprender lo que digo.
> Sino como dice Gudino, en ese caso, pon el codigo de cómo estas implementando las interrupciones y demas



HolaDJ gracias por responder. voy a analizar lo del integrado similar al MAX7313. Lo que quiero saber es si se pueden hacer uso de las interrupciones que posee un pic en el mismo programa. Los he hecho en forma independiente por RB0 y RB4-RB7, sin problemas. Sino que necesito 9 interrupciones. Gracias.


----------



## DJ T3 (Sep 10, 2018)

Poder, podes usar todas las interrupciones que te permita el PIC, el tema es cómo las implementas/organizas/atiendes/etc...
Pon el codigo que llevas hecho


----------



## terminator (Sep 10, 2018)

DJ T3 dijo:


> Poder, podes usar todas las interrupciones que te permita el PIC, el tema es cómo las implementas/organizas/atiendes/etc...
> Pon el codigo que llevas hecho


 Gracias por la respuesta. En cuanto tenga el código con vuestras sugerencias, lo subiré.. Saludos.


----------



## terminator (Sep 11, 2018)

DJ T3 dijo:


> Poder, podes usar todas las interrupciones que te permita el PIC, el tema es cómo las implementas/organizas/atiendes/etc...
> Pon el codigo que llevas hecho


Hola DJ T. Coloco los programas el que trabaja con RB0 y por cambio de estado RB4-RB7.
Ambos funcionan muy bien.
Les comento, estos programas los utilizo PARA DETECTAR los IMPACTOS de balín de carabinas neumáticas.
Inicialmente los hice detectando el impacto SIN interrupciones, simplemente detectado un 1 ó un 0, con cualquier puerto y en el taller funcionaba a las mil maravillas, pero en el campo NO.
Pensé que era por el CORTÍSIMO tiempo que se detectaba el impacto. Pero averigüé que el PIC puede detectar tiempos de hasta 200 nseg. Entonces, ese no era el problema.
El problema era que, a pesar de ese corto tiempo, la subrutina del IF ELSE, no permitía, en alguno casos detectar el impacto en un pin del puerto, por que el pic estaba "leyendo" otro puerto.

Bueno, gracias a D@rkbytes y a ustedes logré usar las interrupciones; de tal manera, que dentro de una subrutina principal, no permito que el micro haga nada, entonces, SOLO se dedica a esperar las interrupciones.
Con interrupción RB0 funciona bien, con interrupciones con RB4-RB7 también, pero quisiera que me den el hilo para poder usar 5 interrupciones (RB0 y RB4-RB7 en el mismo programa)
Si con su ayuda logro hacerlo, creo que podré utilizar luego nueve interrupciones. Gracias.

Programa con interrupción por RB0 ( funcionando OK en forma independiente):

```
cmcon=7             ; todo el puerto A como digital.

Trisa=%00000000     ; todo el puerto A como salida.

Trisb=%00000001     ; Pin RB0 como entrada por interrupción.



x var byte

ledvive var portb.2 ; muestra el inicio del sistema.

porta=0   

portb=0



for x=0 to 5        ; led que muestra el inicio del programa.     

high ledvive

pause 300

low ledvive

pause 100

next x



on interrupt goto ACCION

intcon =%10010000    ; habilita la interrupcion por RB0

option_reg.6=1       ; para que se active la interrupcion en el flanco de SUBIDA



inicio:

;(vacío)Ya que se trata de detectar el impacto de un balín y como éste se realiza

; muy rápidamente sobre un interruptor, es preferible que el micro NO esté

; realizando NINGUNA acción; por eso, no hay líneas de comando en esta subrutina.

goto inicio

disable         ; deshabilita las interrupciones en el handler.



ACCION:    ; Etiqueta llamada por la interrupción por RB0.

porta.1=1

pause 200  ; tiempo suficiente para que el HT12E detecte el pulso del PIC.

porta.1=0



intcon=%10010000  ; Habilita la interrupción del bit RB0

resume            ; Retorna a la línea donde se quedó,(aunque esté vacía).

enable            ; Habilita las interrupciones

goto inicio



end

-------------------------------------------



Programa por cambio de estado RB4-RB7, funciona OK en forma independiente:



********************************

include "modedefs.bas"

cmcon=7             ; todo el puerto A como digital.

Trisa=%00000000     ; todo el puerto A como salida.

Trisb=%11110000     ; Pines RB4 al RB7 como entradas.



datos var byte

x var byte

ledvive var portb.3 ; muestra el inicio del sistema.

porta=0   

portb=0



for x=0 to 4        ; led que muestra el inicio del programa.     

high ledvive

pause 100

low ledvive

pause 50

next x

pause 500



on interrupt goto EXT_INT_RB4_RB7

intcon=%10001000    ;configurar el Registro INTCON

                    ; con interrupción por cambio de estado RB4_RB7



main:

' VACIO. Para tener la certeza de detectar el impacto del balín sin

' que ninguna rutina evite esto.

goto main



disable

EXT_INT_RB4_RB7:

   INTCON.7=0       ; Todas las interrupciones desactivadas momentáneamente.

select case portb

    case $10        ; Si puerto B=b'00010000 (RB4=1) Primer sensor

serout portb.2,n2400,[$FF,$FF,"4A","M"]



    case $20        ; Si puerto B=b'00100000 (RB5=1) Segundo sensor

serout portb.2,n2400,[$FF,$FF,"4A","N"]



    case $40        ; Si puerto B=b'01000000 (RB6=1) Tercer sensor (no usado)

serout portb.2,n2400,[$FF,$FF,"4A","C"]



    case $80        ; Si puerto B=b'10000000 (RB7=1) Cuarto sensor (no usado)

serout portb.2,n2400,[$FF,$FF,"4A","D"]

end select

' Hay 4 puntos de detección de interrupciones, pero sólo se usarán 2, para los

' dos diplays en el lado de recepción.

portb=0

intcon=%10001000

resume

enable



end
```
Nota importante:
Estos son los programas que aplico al lado de TRANSMISION (por que los uso con módulos RF, que dicho sea de paso, andan a las mil maravillas.
Gracias nuevamente.


----------



## terminator (Sep 12, 2018)

terminator dijo:


> Hola Gudino, gracias por tu respuesta. Lo que quiero es hacer uso de las interrupciones que tienen los pics, mi pregunta es saber si se pueden utilizar 9 en un mismo programa. Voy a analizar lo de la multiplexación. Gracias
> 
> 
> 
> HolaDJ gracias por responder. voy a analizar lo del integrado similar al MAX7313. Lo que quiero saber es si se pueden hacer uso de las interrupciones que posee un pic en el mismo programa. Los he hecho en forma independiente por RB0 y RB4-RB7, sin problemas. Sino que necesito 9 interrupciones. Gracias.


Hola DJ, pongo el código que estoy implementado para usar dos tipos de interrupciones, por RB0 y por cambio de estado RB4-RB7. Te comento que los pruebo en Proteus Isis y que cuando funcionan en programas independientes funciona bien, pero aun no logro hacerlo que trabajen en conjunto. Espero que me den una luz para su solución. Saludos.
NOTA: cuando coloco la subrutina main luego de las instrucciones del RB0, funciona el RB0 y cuando lo coloco despues del Rb4-RB7, funcionan las interrupciones del RB4 al RB7, pero nunca ambas.
************************************
cmcon=7         ; todo el puerto A como digital
Trisa=%00000000 ; toto el puerto A como salida
Trisb=%11110001 ; Pines RB4 al RB7 y RB0 como entradas
porta=0
portb=0

on interrupt goto RB0
intcon=%10010000     ; habilita la interrupcion por RB0
option_reg.6=1      ; para activarla por el flanco de subida

'main:
' VACIO. Para tener la certeza de detectar el impacto del balín sin
' que ninguna rutina demore esto.
'goto main
on interrupt goto EXT_INT_RB4_RB7
intcon=%10001000

main:
high portb.1
pause 100
low portb.1
pause 100
goto main

disable             ; deshabilita las interrupciones en el handler
RB0:
high porta.0=1
pause 50
low porta.0

intcon=%10010000   ; habilita la interrupcion del bit RB0
resume              ; GIE = 1 y retorna al punto donde había quedado
                    ; antes de la interrupción. 
enable              ; habilita el inspector de interrupciones
;************

disable

EXT_INT_RB4_RB7:
   INTCON.7=0       ; Todas las interrupciones desactivadas momentáneamente.

if portb.4=1 then porta.1=1

if portb.5=1 then porta.2=1

if portb.6=1 then porta.3=1

if portb.7=1 then portb.2=1

;pause 200   ' tiempo necesario para que el HT12E detecte el pulso del PIC.
intcon=%10011000
resume
enable

end
*****************************


----------



## Gudino Roberto duberlin (Sep 12, 2018)

Hola, no entiendo cuál es el problema con utilizar dos interrupciones.
Sólo debes habilitarlas y crear las subrutinas correspondientes, así son atendidas cuándo sean llamadas.
Hace tiempo que no utilizo PIC Basic, para recomendar que al activarse una interrupción deshabilites la posibilidad de que se active otra, hasta que termines de ejecutar la que fué atendida.


----------



## Scooter (Sep 13, 2018)

Depende de si las rutinas son o no reentrantes y depende de si la interrupción puede repetir antes de que acabes de atenderla.
Ambos problemas se solucionan haciendo rutinas de atención a interrupción mínimas y deshabilitando interrupciones hasta que se acaben, pero esto último no siempre es bueno, puedes perder otra interrupción de mayor prioridad.
Salvo que sea un sistema bombardeado a interrupciones y a tiempos críticos estos detalles suelen importar poco.


----------



## terminator (Sep 13, 2018)

Gudino Roberto duberlin dijo:


> Hola. No entiendo cuál es el problema con utilizar dos interrupciones.
> Sólo debes habilitarlas y crear las subrutinas correspondientes, así son atendidas cuándo sean llamadas.
> Hace tiempo que no utilizo PIC Basic, para recomendar que al activarse una interrupción deshabilites la posibilidad de que se active otra, hasta que termines de ejecutar la que fué atendida.



Hola, amigo Gudino. El problema es que no me salen. jajaja.
No logro hacer esas subrutinas, es decir, cómo hacer que el programa diferencia entre una interrupción por RB0 y entre por cambio de estado RB4-RB7. Saludos.

Saludos amigos.  Después de tanto batallar, creo que he logrado hacer un programa donde se utilizan las interrupciones por RB0 y por cambio de estado RB4-RB7 juntas.
Lo he probado en Proteus Isis, ahora lo voy a implementar en mi protoboard y ojalá funcione.
Lo que no logro entender hasta ahora es por qué no funcionan las instrucciones luego de la etiqueta "accion:" ( las que las tengo desactivas) a pesar de que hacen lo mismo.

Gracias por alguna ayuda más o corregir este programa.


```
cmcon=7         ; todo el puerto A como digital

Trisa=%00000000 ; toto el puerto A como salida

Trisb=%11110001 ; Pines RB4 al RB7 y RB0 como entradas

porta=0

portb=0

;**************



;**************



on interrupt goto accion

intcon=%10011000     ; habilita la interrupcion por RB0

option_reg.6=1      ; para activarla por el flanco de subida (para RB0)



'main:

' VACIO. Para tener la certeza de detectar el impacto del balín sin

' que ninguna rutina demore esto.

'goto main



;***************

main:

porta=0

portb=0

goto main

;***************



disable             ; deshabilita las interrupciones en el handler

accion:

if portb.0=1 then porta.0=1

; high porta.0=1

;pause 100

;low porta.0=0



INTCON.7=0       ; Todas las interrupciones desactivadas momentáneamente.

; para que se diferencie del puerto RB



if portb.4=1 then porta.1=1



if portb.5=1 then porta.2=1



if portb.6=1 then porta.3=1



if portb.7=1 then portb.2=1



pause 100   ' tiempo necesario para que el HT12E detecte el pulso del PIC.

intcon=%10011000

resume

enable

end
```


----------



## Gudino Roberto duberlin (Sep 13, 2018)

Si vas a usar interrupciones, olvidate de utilizar delays.


----------



## terminator (Sep 15, 2018)

Gracias a todos por su invalorable ayuda. Pero ya no voy a ahondar más en el tema de las interrupciones múltiples. He leído por ahí, que en pic basic pro son muy difíciles de hacer, Ahora me voy a avocar a (ya teniendo mínimo 4 interrupciones) hacer lo siguiente. Suponiendo que cada interrupción tenga un valor, por ejemplo del 1 al 4; entonces, lo que quiero hacer, mediante un programa en pic basic pro que después de varias detecciones por parte de estas interrupciones, ME DE LA SUMATORIA TOTAL. Espero algun tip para realizar este proyecto. Gracias.


----------



## Scooter (Sep 15, 2018)

¿Cual es la duda? No entiendo.

sumatoria = sumatoria+1

Ese es el código de todas las rutinas de atención a interrupción

la variable ha de ser accesible por todas; lo mas lógico es que sea global
Luego mira si hay que hacer algo mas, en Arduino hay que declararla como volatile, aunque yo casi nunca lo hago y siempre me ha ido bien.


----------



## terminator (Sep 15, 2018)

Scooter dijo:


> ¿Cual es la duda? No entiendo.
> 
> sumatoria = sumatoria+1
> 
> ...



Gracias por la respuesta amigo Scooter, tal vez tu lo veas sencillo, pero yo tengo problemas,jajaja. La ideas es, por ejemplo, tengo cuatro pulsadores, a los cuales les puse un valor de 1 al 4; entonces se activa DOS veces el pulsador 1 (1+1) y luego TRES veces el pulsador 4 (4+4+4) y yo quisiera representar esta suma total; o sea, (1+1+4+4+4=14) el valor 14 en dos display de 7 segmentos. Esa es la idea. Gracias.


----------



## Scooter (Sep 15, 2018)

¿En serio?

Rutina del pulsador 1
suma = suma +1

Rutina del pulsador 2
suma = suma+2

Rutina del pulsador 3
suma = suma +3

Rutina del pulsador 4
suma = suma +4

Rutina del pulsador 5
suma = suma+5

Rutina del pulsador 6
suma = suma +6

etc


----------



## Gudino Roberto duberlin (Sep 15, 2018)

Hola, añadiendo a Scooter.
Y vuelvo a repetir, *NO* hace falta usar interrupciones para detectar pulsadores!
Y no sé cuántas veces más deberé repetirla.
El secreto está en cómo dinamizas el programa para que sea ágil. Y el problema se resume en usar delays por todos lados.
Coincido con scooter son un mal, que sólo son aplicables en dónde el programa corre sin condiciones.


----------



## terminator (Sep 15, 2018)

Gudino Roberto duberlin dijo:


> Hola, añadiendo a Scooter.
> Y vuelvo a repetir, *NO* hace falta usar interrupciones para detectar pulsadores!
> Y no sé cuántas veces más deberé repetirla.
> El secreto está en cómo dinamizas el programa para que sea ágil. Y el problema se resume en usar delays por todos lados.
> Coincido con scooter son un mal, que sólo son aplicables en dónde el programa corre sin condiciones.


Muchas gracias por tu respuesta amigo Gudino. Lo tomaré en cuenta.


Scooter dijo:


> ¿En serio?
> 
> Rutina del pulsador 1
> suma = suma +1
> ...



Gracias amigo Scooter, voy a intentar hacer. Saludos.


----------

