Go Down

Topic: Problema I2C: me lee uno y dos bytes pero no tres. (Read 479 times) previous topic - next topic

Vaque

Hola;
Soy nuevo por aquí. Estoy trabajando con un arduino UNO como sensor y un TS7500  como maestro en un protocolo I2C.

Tengo el siguiente código para el arduino:
Code: [Select]

#include <Wire.h>

uint8_t SensorVersion[2]  =    "V";
uint8_t SensorName[4]     =    {0x40, 0x3A, 0x09, 0x12};
uint8_t SensorType[4]     =    {0x32, 0x26, 0x11, 0x33};


byte x[4]={0,0,0,0};//contiene el valor llegado


void setup() {
    Serial.begin(9600);
    Serial.println("Inicio");
    Wire.begin(1);
    Wire.onReceive(receiveEvent); //rutinas para cuando llegue algo
    Wire.onRequest(requestEvent);
}

void loop() {
     
}

void receiveEvent(int len) {
     for (int i=0; i<len; i++)
     {
          if (i<5)
          {
               x[i] = Wire.read();
          }
          else
          {
               Wire.read();
          }
     }
}

void requestEvent() {
   
    Wire.write(SensorName,3);
 
}



El TS7500 lleva un debian empotrado; quiero saber si veis algún fallo al código... me da la sensación de que Wire.write tiene un buffer de solo 2 bytes por cada vez.

Un saludo.


fm

Le estas transmitiendo 3 bytes en vez de 4 SensorName, tiene 4 bytes no 3 como envias con el write. Tal vez sea eso?
   

Vaque

Con 4 tampoco funciona. Solo funciona con 2 y con 1.
A ver si mañana limpio un poco el código del TS y lo cuelgo aquí.

Gracias ;)

Vaque

Lo prometido es deuda; éste es el código que utilizo como maestro con el debian (lleva un procesador arm9-> registros utilizados desde la página 145 de éste link, donde pone TWI: https://www.embeddedarm.com/documentation/third-party/ECONA-CNS21XX-HRM-v.1.8.pdf)

Code: [Select]

void *map_phys(off_t addr,int *fd) {
  off_t page;
  unsigned char *start;

  if (*fd == -1)      //si fd no es -1, ya estaba abierto
    *fd = open("/dev/mem", O_RDWR|O_SYNC);   //apertura en modo escritura y lectura syncrono para que sea efectivo cualquier cambio
  if (*fd == -1) {
    perror("open(/dev/mem):");              //no se abrio correctamente
    return 0;
  }
  page = addr & 0xfffff000;      //las paginas son multiplos de 0x1000 primera pagina= 0x0000; segunda= 0x1000; tercera=0x3000...
     //ubica dispositivo en memoria de tamaño una pagina, lectura y escritura, compartido.
  start = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, *fd, page);
               //start empieza en direccion inicial de la pagina
  if (start == MAP_FAILED) {
    perror("mmap:");      //no ubico correctamente
    return 0;
  }
  start = start + (addr & 0xfff);            //star ahora en direccion de la pagina + offset = direccion del registro proyectado
  return start;
}

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]
 
}

inline void cavium_disable_TWI(){
  clrbit(&reg[0],31); //desactiva TWI
}

void init_TWI() {
  reg = map_phys(0x71000020,&fd); //reg[registrotwi/sizeof(unsigned)] ya puede ser utilizado
  cavium_enable_TWI();
  TWI_clock_frequency(42724);//280448 default
  reg[0x14/sizeof(unsigned)] = 3; //TWI_ACTDONE_FG y TWI_BUSERR_FG puestos a '0'
}
/* 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);
  }
}


/* 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);
  }
  return reg[0x10/sizeof(unsigned)];       //devuelve TWI_RD_DATA
}



int main(int argc,char *argv[]) {
  unsigned lectura;


  init_TWI();
        write_TWI_data(2,1,9); //debe mandar 0x09 a la direccion esclavo 0x1
//usleep(100000);
lectura=read_TWI_data(2,3); //debe leer 3 bytes del arduino solo consigo que lea uno o dos pero no 3
printf("lectura despues=0x%X\n",lectura);
cavium_disable_TWI();
  }



Si a alguien se le ocurre algo que lo diga pleaseeeeee. No da error de nada, simplemente lectura se queda con valores indebidos si intento leer más de 2 bytes del arduino (Wire.write(SensorName,>2));

Un saludo.

Go Up