Problema con Interrupción Externa

Hola, estoy trabajando con el PIC16F873, estaba probando un simple programita para manejar adecuadamente el tema de las interrupciones. En el proyecto mayor que voy a hacer, requiero de varias de ellas, y de distinta naturaleza.

la cosa es que estaba probando con este sencillo programa:

#include <stdio.h>
#include <stdlib.h>
#use delay(clock=4000000)
#fuses NOWDT
#USE STANDARD_IO (C)
#byte portb=0x06
#byte trisb=0b11110001


#int_ext
algo(void)
{
output_c(0b00000010);
delay_ms(1000);
return 0;
}
#int_RB
RB_isr()
{
output_b(input_b());
clear_interrupt(int_RB);
output_b(0x00);
output_c(0b00000001);
delay_ms(1000);
disable_interrupts(global);
return 0;
}


void main()
{
portb=0;
enable_interrupts(int_ext);
ext_int_edge(l_to_h);
enable_interrupts(int_RB);
enable_interrupts(global);
while(true)
{
output_c(0x00);
enable_interrupts(global);
}
}


Básicamente, utilizo dos pulsadores para prender 2 Leds en el puerto C. El que está conectado a la interrupción por RB0 funciona bien. El problema se genera cuando intento ejecutar la interrupción por cambios en el puerto b(B4-B7). La cosa es así: simulándolo en Proteus, el programa ingresa a la rutina de interrupción, pero nunca regresa o sale de ella, por más que reseteo los registros, las entradas, o deshabilito las interrupciones, como pueden ver.

Una vez pulsado el botón, nada más del programa responde. ¿Cómo puedo hacer para solucionar esto?, ¿ Por qué no regresa de la interrupción al programa principal?

Muchas Gracias
 
Cuando entras a RB_isr() hay que leer todos los registros que cambiaron para limpiar la interrupcion --> Lo mas sencillo es hacer es "movf portb" (en ASM) o input_b() (en C)

Peeeeero en C está el detalle que si input_b() no se asigna a algo, el compilador te elimina la instrucción al optimizar el código.
Haciendo pulsador = input_b() ; no habría drama salvo que pulsador sea una variable local y tampoco la uses para nada, en ese caso algunos compiladores la podrian eliminar.

En tu programa, haciendo
Código:
#int_RB
RB_isr()
{
    int8 pulsador ;
    pulsador = input_b();
    output_c(0b00000001);
    delay_ms(1000);
}
o definir un macro en asm que sabemos que el compilador no va a tocar.
Código:
#define clearRB #ASM \ movf portb \ #ENDASM

#int_RB
RB_isr()
{
    clearRB ;
    output_c(0b00000001);
    delay_ms(1000);
}

El truco que usaste: output_b(input_b()) ; habría funcionado si no fuera porque cada vez que accedés a portb para lectura o escritura te cambia primero trisb, y al salir de la interrupcion te queda programado como salida .

Para usarlo tendrías que haber declarado:
Código:
#USE FAST_IO(B)
y en main() agregar:
Código:
set_tris_b( 0b11110001 )
En general, salvo que un puerto sea bidireccional, conviene declarar #USE FAST_IO(x) para que no genere instrucciones inútiles.



La línea
Código:
#byte trisb = 0b11110001
es un error, porque en lugar de asignar a trisb 0b11110001 estás ubicando a trisb en la dirección 0xF1
 
buenas me pasa lo siguiente, estoy aprendiendo a programar en C para un pic16f877A y tengo problemas con la interruciones, no se como usarlas ayer esta intentando con un tutorial pero el programa se encicla y nunca regresa con la int de cambio RB4:RB7 y la int externa nunca me funciono.


tambien me gustaria saber como hacer y llamar sub funciones en C
 
buenas estoy haciendo un programa en ccs compiler de una alarma que cuando unos sensores detecten algo se activen unas cargas. ya tengo cuatro sensores conectados en RB4,RB5,RB6,RB7 estos serán sensados por la interrupción de estos bits, y activen las cargas ya mencionadas. pero también quiero colocar un botón para apagar las cargas en cuanto uno regrese a la habitación donde este instalada la alarma, el problema es que la interrupción RB_ISR no me deja hacer esto si bien sensa mis entradas y activa las cargas y sale de esa interrupción y continua con el programa, la interrupción RB0 no me funciona, hice una subrutina aparte para poder apagar las cargas sin usar el RB0 pero aun así tengo problemas con el RB_ISR. No se que pueda hacer, les dejo mi programa para que lo revisen.


Código:
#include "F:\PCW_CCS_LENGUAJE C_PIC\ALARMA.h"

//////////////////////////////
//INTERRUPCION POR RB
/////////////////////////////

#int_RB
void  RB_isr(void) 
{
 delay_ms(20);
 output_B(input_B());
 output_high(SIRENA); 
 output_high(CIRCULINA);
 output_high(LUCES);
}

////////////////////////////////
//INTERRUPCION POR RB0
///////////////////////////////


//#int_EXT
void  EXT_isr(void) 
{
 delay_ms(20);
 output_low(SIRENA); 
 output_low(CIRCULINA);
 output_low(LUCES);
}


//////////////////////////////
//PROGRAMA PRINCIPAL
/////////////////////////////

void main()
{

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_RB);
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);

   // TODO: USER CODE!!


while(TRUE){
output_toggle(LED);   // USO ESTE LED PARA VERIFICAR SI EL PROGRAMA SALE DE LA SUBRUTINA O SE QUEDA ENGANCHADA 
delay_ms(200);

/////////////////////////////////////////////////////////////////
//RUTINA PARA APAGAR CARGAS EN VEZ DE USAR RB0
/////////////////////////////////////////////////////////////////

//if(input(PIN_B0)==0)
//{
 //delay_ms(20);
 //output_low(SIRENA); 
 //output_low(CIRCULINA);
 //output_low(LUCES);
//}
////////////////////////////////////////////
///////////////////////////////////////////

}
     
}
 

Adjuntos

  • ALARMA.jpg
    ALARMA.jpg
    141.7 KB · Visitas: 12
Última edición por un moderador:
Atrás
Arriba