TODOPIC
FORO TÉCNICO => Foro Técnico => Mensaje iniciado por: Vaque 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:
(https://dl.dropboxusercontent.com/u/62787533/ctoduda.jpg)
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).
(https://dl.dropboxusercontent.com/u/62787533/parte3.3vescribebienleemalCOMENTADA.jpg)
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:
(https://dl.dropboxusercontent.com/u/62787533/parte5vescribebienleemal.JPG)
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 (http://datasheets.maximintegrated.com/en/ds/MAX3370-MAX3371.pdf) distv3 (http://www.mindsensors.com/index.php?module=documents&JAS_DocumentManager_op=downloadFile&JAS_File_id=963)
-
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.
-
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.
(https://dl.dropboxusercontent.com/u/62787533/dudilla.JPG)
Solo se me ocurre la opcion de poner un buffer como éste: PCA9515 (http://www.nxp.com/documents/data_sheet/PCA9515.pdf)
¿que opinais de todo esto?
Un saludo.
-
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 (https://drive.google.com/file/d/0B7g5gXD4NZP7YmhWekF5WFhiSTA/edit?usp=sharing)
SI ALGUIEN ME AYUDA LE ESTARE ETERNEMENTE AGRADECIDO.
Un saludo.!
-
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
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
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
-
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 (https://drive.google.com/file/d/0B7g5gXD4NZP7aHBCWnVLbUk2VUE/edit?usp=sharing)
Para iniciar la comunicacion utilizo la siguiente función:
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:
inline void cavium_enable_TWI() {
setbit(®[0],31); //activa TWI
clrbit(®[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:
/* 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(®[0],5); //
setbit(®[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(®[0],6); //comienza escritura TWI_RUN_STAR='1'
printf("Se enviara:%x\n", reg[0xC/sizeof(unsigned)]);
while(!getbit(®[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(®[0x14/sizeof(unsigned)],0)) { //si TWI_BUSERR_FG='1' ha ocurrido un error
print_TWI_error();
exit(1);
}
//setbit(®[0x14/sizeof(unsigned)],1); //TWI_ACTDONE_FG puesto a '0' para proxima transferencia
Y para leer la siguiente:
/* 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(®[0],5); //
clrbit(®[0],4); //TWI_TRANSFER_CMD=0='00'=Only-Read Operation
reg[0] = (reg[0] & 0xFFFFFFFC) | ((len - 1) & 3); //TWI_RDDAT_LEN=len
setbit(®[0],6); //comienza lectura TWI_RUN_STAR='1'
while(!getbit(®[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(®[0x14/sizeof(unsigned)],0)) { //si TWI_BUSERR_FG='1' ha ocurrido un error
print_TWI_error();
exit(1);
}
//setbit(®[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:
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;
}