(AYUDA) PIC-16f84 Interrupcion de una Interrupcion

hola amigos me encuentro haciendo un programita en assembler para un pic 16f84a, en estos momentos aun no he comprado el pic asi que estoy simulando en proteus... el problema es que el programa hace uso de la interrupcion por el pin RB0/INT ya hice la subrutina de interrupcion en la cual contemplo la posibilidad de que en plena rutina se vuelva a pulsar el switch del RB0 para que ocurra una nueva interrupcion antes de haber finalizado (con retfie) la primera...

el proteus no me acepta esto, simula hasta la primera interrupcion y se queda en un bucle (que yo programe) y se supone que al volver a pulsar el RB0 debe interrumpir ese bucle finalizando la interrupcion pero a la segunda no hace nada. y se queda obviamente en el bucle (tuve que desactivar el WDT...)

todo el asunto se trata de un contador de 00 a 99 con dos display, y una especie de pause que va en el RB0 asi que al pulsarlo se debe quedar parpadeando en el numero que iba, y al volver a pulsar debe continuar donde quedó.

asi que si me pueden orientar en el sentido de si es o no posible lo que trato de hacer con las interrupciones.

PD: antes de ir al bucle limpie la bandera INTF, si necesitan visualizar el codigo me dicen para colgarlo.
 
Cuando una interrupcion ocurre, Se desactivan todas las interrupciones (se pone en cero el bit GIE (GlobalInterruptEnable)), y se carga en el contador de programa el vector de interrupciones, se ejecuta la interrupcion y luego cuando se hace un llamado a retfie, se vuelven a activar las interrupciones.
Por esta razon no es posible tener una interrupcion dentro de otra.

La solucion que se me ocurre seria quitarle un poco de trabajo a la interrupcion, que cada vez que se pulse el boton cambie de estado un registro, y ya la rutina encargada de contar, decide si avanza o no dependiendo del estado del registro.

saludos!
 
Última edición:
Hssta donde recuerdo las INTS no son ANIDABLES (una dentro de la otra) se te vuelve loco el STACK o PILA, aparte de los procesos que uno hace como programador el mP tambien hace otros cuando se atienden las INTs, lo mejor no hacerlo, chauuuuuuuuuuuu
 
Hssta donde recuerdo las INTS no son ANIDABLES (una dentro de la otra) se te vuelve loco el STACK o PILA, aparte de los procesos que uno hace como programador el mP tambien hace otros cuando se atienden las INTs, lo mejor no hacerlo, chauuuuuuuuuuuu

NO! Siempre que no hagas stack overflow está bien. La idea de tener un stack es para permitir eso, si no sería imposible hacer subrutinas que llamen a otras subrutinas...

En los PICs ni idea, pero en otras plataformas están permitidas las interrupciones anidadas...
 
El problema es el BIT GIE, cuando se genera la primer interrupción automáticamente se pone a cero, precisamente para evitar que se genere otra interrupción, y es hasta que encuentra el retfie que se pone de nuevo a uno, para habilitar de nuevo las interrupciones. Por eso la segunda interrupción no se activa.

Puedes intentar poner a uno el bit GIE al inicio de la rutina de interrupción para habilitarlas y permitir otra interrupción antes que termine la primera.

Es interesante nunca se me había ocurrido eso de las interrupciones anidadas, no se si funcione, como ya te dijeron hay que tener cuidado con la pila, para que el programa no se salga de control...

Avísanos si funciona...
 
Es imposible hacerlo, miralo de este modo para salir de la INT usas retfie, si estan anidadas de cual estas saliendo?? no se sabe! saldrias de la misma, una cosa es una subrutina anidada en otra , porque para salir de ella propiamente usas return y listo sales si y solo si de ella no en general, amen de una nota de Microchip que hablaba de usar BCF Intcon, GIE cuando se entraba a una INT (supuestamente lo hace automaticamente) y ellos recomendaban hacerlo por soft, lo mismo que al salir hacerlo lo contrario, ademas recuerda que para que sea efectiva la entrada a la INT debes hacer respaldo de W, Status, y REGs comunes que uses, si anidas tendrias que respaldar cada uno al entrar y al final cual sabes cual es?? ademas recuerdas que pasa con el PC (contador de programa) al entrar a una INT? toma la direccion 0x004. por eso si anidas te la psaras entrando ala rutina de atencionde INTs y no sabras cual fue la que te llevo alla, por eso a mi modo de ver IMPOSIBLE sin causar daños colaterales (parezco director de Hoyivud), chauuuuuu
 
Última edición:
El problema es el BIT GIE, cuando se genera la primer interrupción automáticamente se pone a cero, precisamente para evitar que se genere otra interrupción, y es hasta que encuentra el retfie que se pone de nuevo a uno, para habilitar de nuevo las interrupciones. Por eso la segunda interrupción no se activa.

Puedes intentar poner a uno el bit GIE al inicio de la rutina de interrupción para habilitarlas y permitir otra interrupción antes que termine la primera.

Es interesante nunca se me había ocurrido eso de las interrupciones anidadas, no se si funcione, como ya te dijeron hay que tener cuidado con la pila, para que el programa no se salga de control...

Avísanos si funciona...

Bueno eso del BIT GIE lo explica todo... lo que se me ocurre probar ahora es usar el flag de la interrupcion para verificar si se pulsó el switch del RB0 o tambien simplemente chequear el pin RB0 de cualquier forma deberia servir para el proposito... Muchas Gracias!


Es imposible hacerlo, miralo de este modo para salir de la INT usas retfie, si estan anidadas de cual estas saliendo?? no se sabe! saldrias de la misma, una cosa es una subrutina anidada en otra , porque para salir de ella propiamente usas return y listo sales si y solo si de ella no en general, amen de una nota de Microchip que hablaba de usar BCF Intcon, GIE cuando se entraba a una INT (supuestamente lo hace automaticamente) y ellos recomendaban hacerlo por soft, lo mismo que al salir hacerlo lo contrario, ademas recuerda que para que sea efectiva la entrada a la INT debes hacer respaldo de W, Status, y REGs comunes que uses, si anidas tendrias que respaldar cada uno al entrar y al final cual sabes cual es?? ademas recuerdas que pasa con el PC (contador de programa) al entrar a una INT? toma la direccion 0x004. por eso si anidas te la psaras entrando ala rutina de atencionde INTs y no sabras cual fue la que te llevo alla, por eso a mi modo de ver IMPOSIBLE sin causar daños colaterales (parezco director de Hoyivud), chauuuuuu

ok eso deja todo el asunto muy claro!!! jejeje... gracias tambien! cuando logre el objetivo lo posteo por aca, pero por ahora tengo otras tareas de la universidad... Hasta pronto.
 
Puedes utilizar otro Pic mas sofisticado que tiene prioridades. Unas interrupciones tienes mas prioridad sobre otras y se pueden abortar. Ahora mismo me pillar frio, pero mirate alguno de la serie 18
Y nunca te queden dentro de una interrupción mucho tiempo ni hagas bucles muy complejos que no sabes si te va a salir. O si no te puede quedar colgado. Haz un Flag que pongas a 1 y sal de la interrupción y en el bucle infinito controlas si este flag esta a 1 y haces lo que tengas que hacer. Despues cuando se produzca otra interrupción vuelves a entrar y pones el flag a 0 y sales, cuando este a 0 no haces nada. Otro metodo un poco chupuza
 
Última edición:
Hola tengo un problema con las interrupciones de TIMER1 y TIMER2. Lo extraño es que si funciona en el proteus, he construido mi propia señal pwm, ya que el simulador no hacia lo esperando cuando usaba funciones como set_pwmx_duty. El programa basicamente incrementa y decrementa el ancho de pulso con las teclas 'u' y 'd' respectivamente, entre otras cosas. Cuando programo el pic solo me responde * por el hyperterminal cuando en realidad deberia mostrar los voltajes sensados.

aqui les va el programa :

#include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#device adc=10
#use delay (clock=20000000)
#use rs232(baud=9600, XMIT = PIN_C6, RCV = PIN_C7, BITS=8)

//declaracion de puertos
#byte PORTA=0x05
#byte TRISA=0x85
#byte PORTC=0x07
#byte TRISC=0x87
#byte PORTD=0x08
#byte TRISD=0x88
#byte PORTB=0x06
#byte TRISB=0x86

#define R_SHUNT 0.01

char valor;
unsigned int16 q,pwmcounter = 0,pwmduty = 0;
float v1,v2,ISH;
char flag_current = 0, flag_voltage = 0;
char flag_AD = 0;

#int_rda
void serial_isr(void)
{
valor = getc();
//printf("%c",valor);
switch(valor)
{
case '1': //Voltajes
flag_current = 0;
flag_voltage = 1;
break;

case '2'://Corriente
flag_current = 1;
flag_voltage = 0;
break;

case 'u':
pwmduty ++;
break;

case 'd':
pwmduty --;
break;

case '3':
flag_current = 0;
flag_voltage = 0;
break;

default:
break;
}
}

#int_timer1 //Frecuencia de muestreo de 100Hz
void timer1_isr(void)
{
if(pwmduty > 0)output_high(pin_c2);
flag_AD = 1;
set_timer1(59286);
}

#int_timer2 //Frecuencia de 20Khz
void timer2_isr(void)
{
if(input(pin_c2)==1){pwmcounter++;}
if(pwmcounter == pwmduty){pwmcounter = 0;output_low(pin_c2);}
set_timer2(249);
}

void PORT_init(void)
{
TRISA=0xFF;
TRISB=0xFF;
TRISC=0x80;
TRISD=0x00;
PORTC=0x00;
PORTD=0x00;
}

void TIMER1_init(void)
{
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
set_timer1(59286);
}


void PWM_init()
{
//setup_ccp1(ccp_pwm);
setup_timer_2(T2_DIV_BY_1,249,1);
//set_pwm1_duty(125);

}

void MCU_Init(void)
{
Port_init();
TIMER1_init();
PWM_init();
setup_adc(ADC_CLOCK_DIV_32);
setup_adc_ports(ALL_ANALOG);
}


void main()
{
MCU_Init();
enable_interrupts(global);
enable_interrupts(int_rda);
enable_interrupts(int_timer1);
enable_interrupts(int_timer2);

printf("\f****Sensor de Corriente***\n");
printf("\r1. Voltajes\n");
printf("\r2. Corriente\n");
printf("\r3. Nivel DC(PWM)\n");

while(TRUE)
{
if(flag_AD == 1)
{
flag_AD = 0;

set_adc_channel(0);
delay_us(20);
q = read_adc();
v1 = 5.0*q/1024.0;

set_adc_channel(1);
delay_us(20);
q = read_adc();
v2 = 5.0*q/1024.0;

ISH = (v1 - v2)/R_SHUNT;

if(flag_current == 1){printf("\fCorriente: %.4fA",ISH);}
if(flag_voltage == 1){printf("\fVoltajes: %.4fV,%.4fV",v1,v2);}
}
}
}
 
Última edición:
Atrás
Arriba