#include<18f46k22.h>
#fuses HSH,NOPLLEN,PRIMARY_ON,NOWDT,PUT,NOBROWNOUT,NOPBADEN,MCLR,PROTECT,NOLVP,NOSTVREN,NODEBUG
#use delay(crystal=20000000)
//****************Directivas de perifericos*******************************************
#use i2c(MASTER,SCL=PIN_C3,SDA=PIN_C4,SLOW=100000,FORCE_HW,STREAM=i2c_maestro)
i2c_start(i2c_maestro); //Inicio comunicacion
delay_ms(1);
i2c_write(i2c_maestro,0x99); //Escribo direccion del esclavo
delay_ms(1);
i2c_write(i2c_maestro,0); //Escribo la posicion que quiero leer del esclavo
delay_ms(1);
i2c_start(i2c_maestro); //Reinicio el protocolo
delay_ms(1);
i2c_write(i2c_maestro,0x9A); //Escribo direccion del esclavo + 1 (para lectura)
delay_ms(1);
dato=i2c_read(i2c_maestro,0); //Leo la posicion previamente enviada
i2c_stop(); //Detengo la comunicacion
delay_ms(200);
#include<16f88.h>
#fuses MCLR,XT,NOWDT,NOPUT,NOBROWNOUT,NOLVP,NODEBUG,NOFCMEN,NOIESO,PROTECT
#use delay(crystal=4000000)
//****************Directivas de perifericos*******************************************
#use i2c(SLAVE,SCL=PIN_B4,SDA=PIN_B1,ADDRESS=0x99,SLOW=100000,FORCE_HW,STREAM=sensor)
//Interrupcion por recepcion de I2C
#INT_SSP
void recepcion_i2c(void)
{
unsigned int8 incoming, state;
output_high(PIN_A1);
state = i2c_isr_state(sensor);
if(state < 0x80) //Master is sending data
{
if(state == 0)
{
}
if(state == 1) //First received byte is address
{
incoming = i2c_read(sensor);
address = incoming;
//fprintf(uart_maestro,"direccion: %u\n",address); //solo para debug
}
else if(state >= 2 && state != 0x80)
{ //Received byte is data
incoming=i2c_read(sensor);
buffer[address] = incoming;
//fprintf(uart_maestro,"dato recibido: %u\n",buffer[address]);
}
}
if(state >= 0x80) //Master is requesting data
{
i2c_write_slave(sensor,buffer[address]);
}
}
Te agradezco DominusDRR
Ese retardo lo coloque ya que leyendo aqui mismo, otro compañero lo uso en una situacion identica para hacerlo funcionar, con situacion identica me refiero a tener el Maestro a 20Mhz, y el Esclavo a 4Mhz
Aunque he probado tambien sin esos delays, y la situacion es la misma, a pesar de que entra a la interrupcion, solo puedo leer un 0xFF en el maestro
Ya antes hice escritura en un PIC como esclavo dentro del bus I2C, pero nunca lectura, y ahi es donde estoy fallando
El analizador logico, o un buen osciloscopio, ya se los pedi a Santa jajaja aunque no creo que me los traiga :D :D..... :(
Leere la informacion que me compartes, muchas gracias
Saludos y sigo en ello
Buscare una opcion asi, el que colocas creo que ya no esta a la venta, al menos en las paginas de vendedores que menciona
Muchas gracias
Saludos
Fuera de stock :( :( :(
Correcto, intentare conseguir uno para depurar paso a paso que sucede
muchas gracias DominusDRR
Correcto, intentare conseguir uno para depurar paso a paso que sucede
muchas gracias DominusDRR
¿Y simulando y depurando en Proteus?
Me imagino que si tiene un analizador de I2C incluido
Pues con buenas y malas noticias
La buena es que ahora se que sucede con la comunicacion, he simulado en Proteus, y no se obtiene nunca el reconocimiento (ack), por ello la interrupcion salta pero no obtiene respuesta confirmatoria del esclavo, por ello, no hace nada de nada.
Para comprobar que lo estaba haciendo correcto en proteus, he simulado tambien, un programa que tengo mas que probado (esta operando en varias maquinas) y en ese, si que obtengo la respuesta del esclavo sin problema.
Ahora el tema sera, porque no reconoce su direccion el esclavo.
Adjunto imagen de la simulacion, donde se aprecia en el paquete que devuelve, el NACK
Seguimos avanzando.
- Tienes que ingresar para ver archivos adjuntos -
Pues con buenas y malas noticias
La buena es que ahora se que sucede con la comunicacion, he simulado en Proteus, y no se obtiene nunca el reconocimiento (ack), por ello la interrupcion salta pero no obtiene respuesta confirmatoria del esclavo, por ello, no hace nada de nada.
Para comprobar que lo estaba haciendo correcto en proteus, he simulado tambien, un programa que tengo mas que probado (esta operando en varias maquinas) y en ese, si que obtengo la respuesta del esclavo sin problema.
Ahora el tema sera, porque no reconoce su direccion el esclavo.
Adjunto imagen de la simulacion, donde se aprecia en el paquete que devuelve, el NACK
Seguimos avanzando.
- Tienes que ingresar para ver archivos adjuntos -
Pregunta
¿No deberías hacer esto en el lado del esclavo?Código: C
if(state==0) //Address match received with R/W bit clear, perform i2c_read( ) to read the I2C address. { i2c_read(); }
es correcto retire los delays, y modifique la rutina de recepcion en la interrupcion del esclavo, y cambie de frecuencia a 8 Mhz y ahi, al menos en la simulacion trabaja ya como deberia
la condicion que regresa i2c_read, por default genera el ACK, y si lo hace bien con las modificaciones mencionadas
ya solo me falta probar en fisico
saludos
//Interrupcion por recepcion de I2C
#INT_SSP
void recepcion_i2c(void)
{
dato=i2c_read(sensor);
if(dato==0x50)
{
dato=' ';
}
else if(dato=='A')
{
output_high(PIN_A1);
}
}
i2c_start(i2c_maestro); //Inicio comunicacion
ack2=i2c_write(i2c_maestro,0x50); //Escribo direccion del esclavo
if(ack2==0) //Si el bit de reconocimiento es valido
{
i2c_write(i2c_maestro,'A'); //Escribo el caracter a enviar al esclavo
}
i2c_stop();
#use i2c(SLAVE,SCL=PIN_B4,SDA=PIN_B1,ADDRESS=0x50,SLOW=100000,STREAM=sensor)//Interrupcion por recepcion de I2C
#INT_SSP
void recepcion_i2c(void)
{
state=i2c_isr_state(sensor);
if(state<0x80)
{
dato=i2c_read();
if(dato==0x50)
{
dato=' ';
escritura=1;
}
else if(escritura==1)
{
address=dato;
dato=' ';
escritura=0;
}
if(dato==0x51)
{
dato=' ';
lectura=1;
}
}
else if(state>=0x80)
{
i2c_write_slave(buffer[address]);
dato=' ';
lectura=0;
}
}
#use i2c(MASTER,SCL=PIN_C3,SDA=PIN_C4,SLOW=100000,FORCE_HW,STREAM=i2c_maestro) i2c_start(i2c_maestro); //Inicio comunicacion
ack2=i2c_write(i2c_maestro,0x50); //Escribo direccion del esclavo
if(ack2==0)
{
i2c_write(i2c_maestro,0); //Escribo la posicion quw quiero leer del esclavo
}
i2c_start(i2c_maestro); //Reinicio el protocolo
ack2=i2c_write(i2c_maestro,0x51); //Escribo direccion del esclavo + 1 (para lectura)
if(ack2==0)
{
dato=i2c_read(i2c_maestro,0); //Leo la posicion previamente enviada
}
i2c_stop(); //Detengo la comunicacion
SOLUCIONADO :-/
Me ha costado un poco, pero como he aprendido, he combinado lo que ya sabia hacer, con lo aprendido, se los comparto.
En el esclavo, he puesto lo siguiente:
La directiva de configuracion del I2C para el esclavo queda asiCódigo: [Seleccionar]#use i2c(SLAVE,SCL=PIN_B4,SDA=PIN_B1,ADDRESS=0x50,SLOW=100000,STREAM=sensor)
y el codigo en la rutina de interrupcion la he echo de la siguiente maneraCódigo: [Seleccionar]//Interrupcion por recepcion de I2C
#INT_SSP
void recepcion_i2c(void)
{
state=i2c_isr_state(sensor);
if(state<0x80)
{
dato=i2c_read();
if(dato==0x50)
{
dato=' ';
escritura=1;
}
else if(escritura==1)
{
address=dato;
dato=' ';
escritura=0;
}
if(dato==0x51)
{
dato=' ';
lectura=1;
}
}
else if(state>=0x80)
{
i2c_write_slave(buffer[address]);
dato=' ';
lectura=0;
}
}
En el maestro, la directiba para el I2C queda asiCódigo: [Seleccionar]#use i2c(MASTER,SCL=PIN_C3,SDA=PIN_C4,SLOW=100000,FORCE_HW,STREAM=i2c_maestro)
y la solicitud de datos o lectura la hago asi:Código: [Seleccionar]i2c_start(i2c_maestro); //Inicio comunicacion
ack2=i2c_write(i2c_maestro,0x50); //Escribo direccion del esclavo
if(ack2==0)
{
i2c_write(i2c_maestro,0); //Escribo la posicion quw quiero leer del esclavo
}
i2c_start(i2c_maestro); //Reinicio el protocolo
ack2=i2c_write(i2c_maestro,0x51); //Escribo direccion del esclavo + 1 (para lectura)
if(ack2==0)
{
dato=i2c_read(i2c_maestro,0); //Leo la posicion previamente enviada
}
i2c_stop(); //Detengo la comunicacion
Los PIC quedan operando uno a 20Mhz (maestro 18F46K22) y otro a 16Mhz (esclavo 16F88)
Lo he probado en fisico, y funciona bien :-)
Ojala a alguien le sirva esta experiencia, si algo no esta claro, con gusto lo aclaramos
Saludos y muchas gracias compañeros
P.D.: Si algun moderador me hiciera favor de agregar en el titulo del post el [SOLUCIONADO] se lo agradecere mucho
Que tal Dominus, te enlisto los dos cambios que resolvieron el problema
1.- En principio la direccion que configure en el esclavo no la tomaba (0x99), nunca respondia, la cambie (0x50) y empezo a responder
2.- Cambie la rutina de recepcion en el esclavo, la que muestro, porque no enviaba el dato correcto, me mandaba un 0x00 siempre
en general son los dos cambios importantes que hice, aunado a esto, probe el cambio de cristales a diferentes frecuencias, cambie la estructura de la directiva de I2C, los delays, la frecuencia del bus, etc etc
Pero en realidad, con los dos primeros puntos trabaja sin problema.
Saludos