Autor Tema: Problema comunicacion i2c  (Leído 1401 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Vaque

  • PIC10
  • *
  • Mensajes: 4
Problema comunicacion i2c
« en: 31 de Octubre de 2013, 10:40:24 »
Buenos días a todos;

Soy nuevo en este foro, estoy en último curso de ing tec industrial de electronica y tengo un problema con un proyecto:

Tengo un ts7500 que es un miniordenador con debian que tiene un micro arm9 en su interior y un sensor distv3 que es un sonar i2c. Quiero comunicar el ts7500 con el distv3. Las líneas i2c (scl y sda) del ts7500 son a 3.3v mientras que las líneas i2c del distv3 son a 5v. Para que conmuten tengo un integrado MAX3370EXK en cada línea (sda y scl) de tal forma que éste es el circuito que tengo:



Con los dos integrados la señal conmuta de 3.3v a 5v y viceversa sin ningún problema de velocidad.
El problema está en que la comunicación es demasiado rápida para el sensor (distv3 en éste caso).
Por ejemplo si escribo desde el ts7500 el byte 0 en el distv3 y quiero leer de ese registro 4 bytes:
La parte de 3.3v: (amarillo=SDA y verde=SCL).


El registro 0x0 del distv3 contiene la información: V3.00.  El primer byte a mandar del distv3 al ts7500 sería V= 0x56=0101 0110; pero lo que se está mandando es 0x2B=0010 1011 que es 0x56 desplazado a la derecha. El primer bit de 0x56 se empieza a mandar en el segundo periodo de SCL del tiempo que tiene que mandar los 8 bits por lo que la información es errónea.
Parte de 5v:


Hay dos resistencias de pullup en la parte de alto voltaje (Rph) (en la parte de bajo voltaje no hacen falta debido a que el ts7500 ya las lleva integradas, en estado de reposo son 3.3v sus líneas i2c) he hecho pruebas cambiándolas hasta un mínimo de 1k y obtengo el mismo resultado.
¿Alguna idea?.

Las hojas características del max3370 y del distv3: MAX3370     distv3

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: Problema comunicacion i2c
« Respuesta #1 en: 03 de Noviembre de 2013, 08:22:02 »
Hola compañero

Creo recordar que la velocidad del bus i2c radica en cambiar el valor
de las resistencias, y otros parametros.

Tendras que trabajar a la velocidad del mas lento o saturaras al mas lento y nunca se entenderan.
puedes probar a dejar un retardo antes de enviar datos o reducir la velocidad de comunicación.

mira este post:

http://www.todopic.com.ar/foros/index.php?;topic=38547.0

y dentro de el este en paginas consultadas el terce enlace

http://ww1.microchip.com/downloads/en/DeviceDoc/i2c.pdf

en la pagina 9 viene lo de la velocidad

ponele un ojo al post.

ya nos contas.

Un saludo.



Desconectado Vaque

  • PIC10
  • *
  • Mensajes: 4
Re: Problema comunicacion i2c
« Respuesta #2 en: 09 de Noviembre de 2013, 16:24:23 »
Muchas gracias por la respuesta, muy interesante.

Todavía no he resuelto el fallo y nose como enfocarlo; he probado a cambiar las resistencias de pullup por muchos valores y la gráfica se repite con los valores de las resistencias de pullup que deja hacer la comunicación (hace ACK cuando manda byte de dirección).

Ahora mismo tengo al TS7500 con arduino conectado en las líneas scl y sda actuando como sensor, se repite el fallo en la lectura (resistencias de pullup de 2k2). Y la velocidad no debería ser un problema (creo) debido a que  el periodo de scl son 17us, si se manda un bit por segundo tenemos 1seg/17us= 58,823kbits/seg.... el modo estandar es hasta 100kbits/seg... luego está el modo rápido de 400kbits/seg y otros modos más rápidos.... es decir que es una comunicación muy lenta.



Solo se me ocurre la opcion de poner un buffer como éste: PCA9515

¿que opinais de todo esto?

Un saludo.

Desconectado Vaque

  • PIC10
  • *
  • Mensajes: 4
Re: Problema comunicacion i2c
« Respuesta #3 en: 21 de Noviembre de 2013, 16:34:56 »
Hola de nuevo!
Estoy intentando bajar la velocidad de la comunicación por software a 11 kbps.
Adjunto un .pdf con lo que planteo para ver si alguien me puede echar una mano porque no se en donde fallo:

PDF CONCEPTO Y RESULTADOS

SI ALGUIEN ME AYUDA LE ESTARE ETERNEMENTE AGRADECIDO.

Un saludo.!

Desconectado Vtronic

  • PIC16
  • ***
  • Mensajes: 121
Re: Problema comunicacion i2c
« Respuesta #4 en: 22 de Noviembre de 2013, 03:24:39 »
Te estas enfocando mucho en la velocidad, también deberías de enfocarte en el protocolo, que librería estas usando para el I2C?

Yo utilizo están en C30 en un pic, toma de ejemplo la secuencia

Lectura con burst mode

Código: [Seleccionar]
void read(int address,char *buffer,unsigned char Length)
{
IdleI2C1(); //wait for bus Idle
StartI2C1(); //Generate Start Condition
while(I2C1CONbits.SEN ); //Wait until start condition is over
MasterWriteI2C1(I2C_SLAVE); //Write Control Byte
while(I2C1STATbits.TBF);
while(I2C1STATbits.ACKSTAT);
IdleI2C1(); //wait for bus Idle
MasterWriteI2C1(address); //Write start address
while(I2C1STATbits.TBF);
while(I2C1STATbits.ACKSTAT);
IdleI2C1(); //wait for bus Idle
RestartI2C1(); //Generate restart condition
while(I2C1CONbits.SEN); //Wait until start condition is over
IdleI2C1(); //wait for bus Idle
MasterWriteI2C1(I2C_SLAVE | 0x01); //Write control byte for read
while(I2C1STATbits.TBF);
while(I2C1STATbits.ACKSTAT);
IdleI2C1(); //wait for bus Idle
while (Length)
{
Length--;
*buffer++=MasterReadI2C1(); //getI2C(); //get a single byte
while(I2C1STATbits.RBF);
while(I2C1STATbits.ACKSTAT);
if(Length)
{
IdleI2C1();
AckI2C1(); //Acknowledge until all read
while (I2C1CONbits.ACKEN );
}
}
IdleI2C1(); //wait for bus Idle
NotAckI2C1(); 
while (I2C1CONbits.ACKEN );
StopI2C1(); //Generate Stop Condition
while(I2C1CONbits.PEN);
}



Escritura


Código: [Seleccionar]
void write(int reg, unsigned char data)
{
  IdleI2C1(); //wait for bus Idle
StartI2C1(); //Generate Start Condition
while(I2C1CONbits.SEN ); //Wait until start condition is over
MasterWriteI2C1(I2C_SLAVE); //Write Control Byte
  while(I2C1STATbits.TBF);
while(I2C1STATbits.ACKSTAT);
IdleI2C1(); //wait for bus Idle

MasterWriteI2C1(reg); //Write Address
  while(I2C1STATbits.TBF);
while(I2C1STATbits.ACKSTAT);
IdleI2C1(); //wait for bus Idle

  MasterWriteI2C1(data);
IdleI2C1();
StopI2C1(); //Initiate Stop Condition
}

int getI2C(void)
{
char temp;
I2C1CONbits.RCEN = 1;//Enable Master receive
while(!I2C1STATbits.RBF);
temp= I2C1RCV;
return temp;
}

Yo tenia un problema con un sensor I2C, este nunca cambiaba los registros después de una lectura y fue problema del protocolo I2C Yo no lo había hecho bien, espero que te sirva, saludos

Desconectado Vaque

  • PIC10
  • *
  • Mensajes: 4
Re: Problema comunicacion i2c
« Respuesta #5 en: 24 de Noviembre de 2013, 12:03:53 »
Hola Vtronic;

No tengo librería para utilizar; intento hacer la comunicación mediante registros que es como el fabricante aconseja. Para ello utilizo los registros TWI propios del nucleo ARM9 que lleva: hojascaracteristicas

Para iniciar la comunicacion utilizo la siguiente función:

Código: [Seleccionar]
void init_TWI() {
  int TWI_CLKDIV=0;

  reg = map_phys(0x71000020,&fd); //reg[registrotwi/sizeof(unsigned)] ya puede ser utilizado
  cavium_enable_TWI();
  reg[0x14/sizeof(unsigned)] = 3; //TWI_ACTDONE_FG y TWI_BUSERR_FG puestos a '0'

Donde cavium_enable_TWI(); es:

Código: [Seleccionar]
inline void cavium_enable_TWI() {
  setbit(&reg[0],31);   //activa TWI
  clrbit(&reg[0],24);             //desactiva TWI data swap: TWI_WR_DAT = PWDATA[31:0] y PRDATA = TWI_RD_DAT[31:0]
 
}

Para escribir utilizo la siguiente función:

Código: [Seleccionar]
/* void write_TWI_data(unsigned adrs,int len,unsigned data):    */
/* Escribe valor de data de len bytes en esclavo adrs mediante I2C */
void write_TWI_data(unsigned adrs,int len,unsigned data) {
  int limit=10000; //limitamos tiempo espera transmision

  clrbit(&reg[0],5);          //
  setbit(&reg[0],4);          //TWI_TRANSFER_CMD=1='01'=Only-Write Operation
  reg[0] = (reg[0] & 0xFFFFFFF3) | (((len - 1) & 3)<<2); //TWI_WRDAT_LEN=len
  reg[0xC/sizeof(unsigned)] = data; //TWI_WR_DATA=data
  reg[0x8/sizeof(unsigned)] = adrs; //TWI_SLAVE_ADDR=adrs
  setbit(&reg[0],6); //comienza escritura TWI_RUN_STAR='1'
 
  printf("Se enviara:%x\n", reg[0xC/sizeof(unsigned)]);
  while(!getbit(&reg[0x14/sizeof(unsigned)],1) && --limit>0); // espera mientras dure la transferencia fin si TWI_ACTDONE_FG='1'
  if (limit <=0) {       // o si timeout
printf("timeout\n");
  }     
  if (getbit(&reg[0x14/sizeof(unsigned)],0)) {           //si TWI_BUSERR_FG='1' ha ocurrido un error
    print_TWI_error();
    exit(1);
  }
  //setbit(&reg[0x14/sizeof(unsigned)],1); //TWI_ACTDONE_FG puesto a '0' para proxima transferencia

Y para leer la siguiente:

Código: [Seleccionar]
/* void read_TWI_data(unsigned adrs,int len):       */
/* Lee len bytes de adrs mediante I2C y los devuelve. */
unsigned read_TWI_data(unsigned adrs,int len) {
  int limit=10000; //limitamos tiempo espera transmision
 
  clrbit(&reg[0],5);       //
  clrbit(&reg[0],4);       //TWI_TRANSFER_CMD=0='00'=Only-Read Operation
  reg[0] = (reg[0] & 0xFFFFFFFC) | ((len - 1) & 3);           //TWI_RDDAT_LEN=len

  setbit(&reg[0],6);       //comienza lectura TWI_RUN_STAR='1'
  while(!getbit(&reg[0x14/sizeof(unsigned)],1) && --limit>0); // espera mientras dure la transferencia fin si TWI_ACTDONE_FG='1'
  if (limit <=0) {       // o si timeout
printf("timeout\n");
  }
  if (getbit(&reg[0x14/sizeof(unsigned)],0)) {       //si TWI_BUSERR_FG='1' ha ocurrido un error
    print_TWI_error();
    exit(1);
  }
 
  //setbit(&reg[0x14/sizeof(unsigned)],1);                //TWI_ACTDONE_FG puesto a '0' para proxima transferencia
  return reg[0x10/sizeof(unsigned)];       //devuelve TWI_RD_DATA
}


De tal forma que lo utilizo de esta manera:

Código: [Seleccionar]
int main(int argc,char *argv[]) {
  unsigned lectura=0, escritura, reg_data, value, direccion;
  int len, len2;
  int i=0;
  unsigned a, b, c, d, dir_antes;
 
 
  init_TWI();
 
 

  write_TWI_data(0x34,1,0x00);
  lectura=read_TWI_data(0x34,4);

  printf("Lectura: 0x%X\n",lectura);

  cavium_disable_TWI();
  return 0;
}