Interrupción en PIC con PCF8574 I2C

Hola a todos:

Estoy haciendo pruebas para comunicar un Pic con un expansor de entradas PCF8574 por I2C. En el pic uso los pines RB3 y RC7 como pines I2C (para dejar libre RB0 y RB1 para interrupciones) y el problema que tengo es que si conecto la interrupción a RB0, no salta.
Con el ICD he probado a poner RB0 a masa, y sigue leyendo un "1" en esa entrada, por lo que nunca cambia y por eso no genera la interrupcion.
Pongo el código que utilizo a ver si alguien ve algo que ocasione esto:
Código:
#include <18F2455.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN      //~~~ 20MHZ OSCILLATOR CONFIGS ~~~//
#use delay(clock=48000000)
#use i2c(MASTER,SCL=PIN_B3,SDA=PIN_C7,SLOW,FORCE_HW,RESTART_WDT)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)

#byte PORTA=0xF80
#byte PORTB=0xF81
#byte INTCON=0xFF2

int bucle,dato,temp;


#int_EXT
void EXT_isr()
{	i2c_start();
	i2c_write(0x40+1);
	dato=i2c_read(0);
	i2c_stop();
	output_toggle(PIN_A1);

}
///////////////////////////////////////////
//programa principal
///////////////////////////////////////////
void main(void) 
{	delay_ms(10);						
	set_tris_A(0b00000000);
	set_tris_B(0b11111111);
	port_B_pullups(TRUE);
	PORTA=dato=0;
	bucle=0b11110101;
	temp=PORTB;
	INTCON=0;
	enable_interrupts(INT_EXT);
	ext_int_edge(0,H_TO_L);
	enable_interrupts(global);
	output_toggle(PIN_A1);
	while(TRUE)
	{
 	}  
      
}

Si conecto la interrupción a RB2/EXT2, funciona correctamente, y lo dicho, con el debugger, si pongo el pin RB0 a masa, sigue leyendo "1".

Aver si alguien me puede dar una pista.
Saludos y gracias.
 
Hola, yo configure como entrada un PCF8574, pero cuando leo el dato por I2C obtengo la suma de los pines ejemplo basico

Código:
int indig
indig =  I2C_recibe(0x4F);
printf(lcd_putc, "dato %02u", ~indig );

no escribi lo de I2C_recibe (); porque es una funcion que lee por I2C no viene al caso lo que si el dato se lee en elñ PCF8574, despues lo muesto por LCD y niego el dato, y muestra ejemplo 1,2,4,8,16,32,64,18 si entra por un pin solamente pero me da la suma si entran por dos, hay alguna manera que pueda leer solo un pin pór ma que esten los otros activos? despues leo el otro activo y asi, no quiero la suma. Como se puede hacer? me ayudan con eso?
 
Pero como es? Suponiendo que tengo una entrada en el pin 2 y 5 como los diferenció? No quiero suma quiero que me diga tenés una entrada en el pin 2 y en el pin 5 . Como se hace?

 
Prueba con algo así de sencillo:
PHP:
int8 dato = leer_pcf8574(dir_pcf);

for(int8 b=0;b<8;++b)
{
     if(bit_test(dato,b))
         // Hacer algo si es 1.
     else
         // Hacer algo si es 0.
}
 
Voy a probarlo hoy a la tarde, a ver que sucede, si con esto puedo distinguir pines esta buenisimo cuando entran por más de uno. Lo que busco es como un equivalente de un input_b(PIN_B2) como ejemplo por más que tenga otros pines en 1 o 0 yo quiero elegir un pin del PCF8574 y ver que hay y luego ver otro y asi. Asíque voy a probar eso

 
Funciona Perfecto D@rkbytes, puedo elegir una de las entradas y ver como cambia, ahora una consulta yo hice el ejemplo con un pic cualquiera no importa alguno, un dipswitch de 8 y el pcf8574 en proteus, funciona todo pero cuando pongo a cero el pin P7 del PCF en el simulador, la salida de INT que siempre esta a alto y pasa a Bajo ante una interrupcion, queda en BAJO fijo, luego lo saco de cero y lo vuelvo a poner y se normaliza en Alto la salida INT del PCF, eso es un error del Simulador NO? no sea cosa que me pase eso en la vida real sino me muero. Me esplico no? solo en el PIN P7 del pcf me pasa eso.

Ejemplo. P7 en Alto ------ salida INT en ALTO
pongo P7 a BAJO ------ SALIDA INT a BAJO
pongo P7 a ALTO ------- SALIDA INT a BAJO
PONGO P7 a BAJO ------ SALIDA INT a ALTO
PONGO P7 a ALTO ------- SALIDA INT a ALTO

que sucede que si queda INT en bajo, nunca el micro va a detectar los cambios de los otros pines, ahora con los otros pines siempre queda en alto y por lo tanto funciona bien, Por eso pregunto si es error del Programa Proteus o la vida real me va a pasar eso?
 
Última edición:
En proteus funciona todo, pero cuando pongo a cero el pin P7 del PCF en el simulador, la salida de INT que siempre está a alto y pasa a Bajo ante una interrupción, queda en BAJO fijo, luego lo saco de cero y lo vuelvo a poner y se normaliza en alto la salida INT del PCF.
¿Eso es un error del Simulador NO?
No es un error del simulador.
La salida INT del PCF8574 va de alto a bajo cuando se produce un cambio de estado en su puerto E/S.
Este nivel bajo se mantiene hasta que se dé una orden de lectura o escritura.
¿Qué sucede que si queda INT en bajo? Nunca el micro va a detectar los cambios de los otros pines.
Ahora, con los otros pines siempre queda en alto y por lo tanto funciona bien, por eso pregunto si es error del Programa Proteus o en la vida real me va a pasar eso.
Mientras realices una lectura para restablecer el estado de reset, no tendrás problemas.

Lee la hoja de datos, ahí encontrarás la información correspondiente.
 
SI entiendo lo que decis pero tiene que ser error del programa porque sino con los demas pines lo haria y no sucede eso es algo que no comprendo de alto a bajo es perfecto lo que no es perfecto que se leyo y quede bajo. Cuando vos lees el I2C de un PCF y en dato da el resultado por ejemplo 129 es porque entro por el P7 y por el P0, por lo tanto 1 + 128.
Ahora como vos me enseñaste bit_test(dato,b), anda perfecto ponemos 0 en B y te dice que hay entrada y luego 7 en B y muestra la ultima entrada, pero INT me queda en Bajo cuando tendria que quedar alto, por eso la pregunta si es error del simulador?. pero Repito solo con P7 cualquier otro esta perfecto. Me llamo la atencion eso y no es la primera vez que lo veo esto con los PCF probando en el simulador. Lo que pasa que siempre lo utilice de salida nunca en entrada Y ahora me encontre con esto.
Ahi te adjunto el archivo el soft mas el proteus, deja que inicialice el programa una vez que aparezca la hora en el display move el dipswich solo va a leer el o y el 7 osea los dos de las puntas y fijate por favor. Si queres leer otro pin anda a la parte Int externa del programa principal y cambia a otro pin a leer , esto esta a modo de prueba no va ser asi pero salto eso justo.

Resetting and reactivating the interrupt circuit is achieved
when data on the port is changed to the original setting or
data is read from or written to the port which has generated
the interrupt.


esta es la parte que hay que tocar para variar la entrada por si queres ver otra repito esta a modo prueba esto.
Código:
#INT_EXT1
void  EXT1_isr(void) 
{
   unsigned int8 indig, dato;
   indig=i2c_recibe(addrs_pcf[0]); delay_ms(2);

  lcd_gotoxy(1,3);
  
  printf(lcd_putc,"DIR %02u    %02u       ", bit_test(indig,1),bit_test(indig,7));
}
 

Adjuntos

  • Rev3 2017.zip
    516.9 KB · Visitas: 13
Última edición:
Al parecer se te está pasando algo sobre lo que comenté.
Te adjunto un ejemplo de lectura del PCF8574 por interrupción.

PD:
Te recomiendo que no te bases en los eventos visuales de la simulación. ;)
 

Adjuntos

  • 18F46K22 Leer PCF8574.rar
    49.9 KB · Visitas: 26
Última edición:
Tienes dos opciones...

  1. Cambia la memoria 24C04, por una 24LC04
  2. Establecer "SLOW" para el bus de datos.
De esas dos opciones, te recomiendo la primera.

Ahora hay algo mas por qué preocuparse.
CCS C Compiler dijo:
>>> Warning 216 "maincontroller.c" Line 295(1,2): Interrupts disabled during call to prevent re-entrancy: (@I2C_WRITEU_2)
>>> Warning 216 "maincontroller.c" Line 295(1,2): Interrupts disabled during call to prevent re-entrancy: (@delay_ms1)
>>> Warning 216 "maincontroller.c" Line 295(1,2): Interrupts disabled during call to prevent re-entrancy: (lcd_send_nibble)
>>> Warning 216 "maincontroller.c" Line 295(1,2): Interrupts disabled during call to prevent re-entrancy: (lcd_send_byte)
>>> Warning 216 "maincontroller.c" Line 295(1,2): Interrupts disabled during call to prevent re-entrancy: (@I2C_READU_2)
>>> Warning 216 "maincontroller.c" Line 295(1,2): Interrupts disabled during call to prevent re-entrancy: (lcd_putc)
>>> Warning 216 "maincontroller.c" Line 295(1,2): Interrupts disabled during call to prevent re-entrancy: (lcd_gotoxy)
>>> Warning 216 "maincontroller.c" Line 295(1,2): Interrupts disabled during call to prevent re-entrancy: (@PRINTF_U_832)
>>> Warning 216 "maincontroller.c" Line 295(1,2): Interrupts disabled during call to prevent re-entrancy: (@PSTRINGCN_832)
Todas esas advertencias se deben a que usas los servicios de interrupción para ejecutar escrituras en pantalla y llamadas a funciones que contienen retardos.

Si usaras banderas, así como en el ejemplo que subí, puedes ejecutar las rutinas en el main cuando se activen.
Así liberas al sistema de posibles conflictos y lo mantienes mas atento a las interrupciones.
 
Buen dato decís que esos mensajes desaparecen usando banderas? Lo voy a probar. Yo hago esto por vocación aclaro porque no soy profesional, pero si me gusta aprender hacer bien las cosas por eso molestó a cada rato

 
Hola, anduvo perfecto como digiste, pero viste el circuito hay un MCP23017 el último voy a configurarlo como puerto a entrada y B salida así sacó el PCF8574 y colocó un integrado menos, como salida el MCP es fácil ahora voy a probarlo como entrada un puerto voy a ir probando y escribiendo los inconvenientes.

 
Atrás
Arriba