Lectura atrás 0xffff para la temperatura del sensor de temperatura / presión I2C BMP085

2

Estoy conectando una CPU Rabbit 5760 a una sensor Bosch BMP085 a través de I2C. Todo está bien, excepto que leer el registro de temperatura está leyendo 0xffff (vea el caso BP_FINISHTEMP en el interruptor). No puedo ver por qué no está funcionando. El código está abajo. ¿Alguien puede ver lo que está mal? Los valores de presión y calibración leen bien. Gracias si alguien puede ayudar.

// baro.lib, Barometer related functions

/*** BeginHeader InitBarometer, ReadBarometer */
int InitBarometer(void);
int ReadBarometer(void); // has 4 phases

/*** EndHeader */

// this all comes from the barometer data sheet
struct s_baroparams {
    short ac1;
    short ac2;
    short ac3;
    unsigned short ac4;
    unsigned short ac5;
    unsigned short ac6;
    short b1;
    short b2;
    short mb;
    short mc;
    short md;
} baroparams;
enum {BP_FAIL,BP_STARTTEMP,BP_FINISHTEMP,BP_STARTPRESSURE,BP_FINISHPRESSURE}  

BarometerPhase;
unsigned long LastBarometerStartTime;
long baro_ut;
long baro_up;

// Returns TRUE if successful, else FALSE
int InitBarometer(void) {
    char *ptmp;
   char hi,lo;
    int i;

    assert(Stack_Low());

    BarometerPhase = BP_FAIL;
    // OLD CODE THAT USED TO USE PORT B FOR I2C
    // cannot use i2c_init because it assumes port D
    // so these lines sorta replace it
    // PB1,PB3,PB5 are SCL, SDA, and XCLR on the barometer
    // we want pb1 and pb3 to be low inputs to let the pullups work, and pb5 to be low, output, then high output

// These pins assigned to portD for the HS4, used to be port B
    /*
    WrPortI(PDDR,&PDDRShadow,0); // all low to start
    WrPortI(PDDDR,&PDDDRShadow,(1<<5)); // all inputs except pd5
    WrPortI(PDDR,&PDDRShadow,PDDRShadow|(1<<5)); // now pd5 is high
    */

    // pull baro. sensor out of reset by setting XLR high (XLR is port D bit 1).
    // This assumes we'll want it out of reset before initting the I2C interface,
    // VERIFY THIS
    BitWrPortI(PDDDR,&PDDDRShadow,1,1);
    BitWrPortI(PDDR,&PDDRShadow,1,1);

i2c_init();

   // i2c_clocks_per_us = (int)(19200L*32*freq_divider/1000000L);

   // evil evil hack here
   ptmp = (char *)&baroparams.ac1;
   for (i=0;i<11;i++) {    // 11 is number of 2-byte values in baroparams above
    // start condition
       if (i2c_start_tx()) {
        return FALSE;
       }
       // send ef
       if (i2c_write_char(0xee))
        return FALSE;
       if (i2c_write_char(0xaa+i*2))
        return FALSE;
       if (i2c_start_tx()) {
        return FALSE;
       }
       if (i2c_write_char(0xef))
        return FALSE;
       if (i2c_read_char(&hi))
        return FALSE;
       i2c_send_ack();
       if (i2c_read_char(&lo))
        return FALSE;
       i2c_send_nak();
       // stop condition
       i2c_stop_tx();
      *ptmp++ = lo;
      *ptmp++ = hi;
}
BarometerPhase = BP_STARTTEMP;
   LastBarometerStartTime = 0;

   return TRUE;
}

// Return -1 if failed, 0 if success
int ReadBarometer()    {
    unsigned long dt;
//   unsigned char hi,lo,xlo;
   union { long l; unsigned char uc[4]; } u;
   long x1,x2,x3,b3,b5,b6,b7,t,p;
   unsigned long b4;
   long b6x;

    assert(Stack_Low());

   switch (BarometerPhase) {
    case BP_FAIL:
          return -1;
    case BP_STARTTEMP:
           if (i2c_start_tx()) {
            return -1;
           }
          if (i2c_write_char(0xee))
            return -1;
          if (i2c_write_char(0xf4))
            return -1;
          if (i2c_write_char(0x2e))
             return -1;
          i2c_stop_tx();
         BarometerPhase = BP_FINISHTEMP;
         LastBarometerStartTime = MS_TIMER;
         break;
    case BP_FINISHTEMP:
          u.l = 0;
        dt = MS_TIMER - LastBarometerStartTime;
         if (dt < 6) break;

         if (i2c_start_tx()) {
            return -1;
           }
          if (i2c_write_char(0xee))
            return -1;
          if (i2c_write_char(0xf6))
            return -1;
           if (i2c_start_tx()) {
            return -1;
           }
          if (i2c_write_char(0xef))
            return -1;
          if (i2c_read_char(&u.uc[1]))
            return -1;
          i2c_send_ack();
          if (i2c_read_char(&u.uc[0]))
            return -1;
          i2c_send_nak();
          i2c_stop_tx();
        baro_ut = u.l;
        BarometerPhase = BP_STARTPRESSURE;
         break;
    case BP_STARTPRESSURE:
           if (i2c_start_tx()) {
            return -1;
           }
          if (i2c_write_char(0xee))
            return -1;
          if (i2c_write_char(0xf4))
            return -1;
          if (i2c_write_char(0x34+(BARO_OSS<<6)))
            return -1;
          i2c_stop_tx();
         BarometerPhase = BP_FINISHPRESSURE;
         LastBarometerStartTime = MS_TIMER;
         break;
      case BP_FINISHPRESSURE:
        u.l = 0;
        dt = MS_TIMER - LastBarometerStartTime;
         if (dt < BARO_TIME) break;
           if (i2c_start_tx()) {
            return -1;
           }
          if (i2c_write_char(0xee))
            return -1;
          if (i2c_write_char(0xf6))
            return -1;
           if (i2c_start_tx()) {
            return -1;
           }
          if (i2c_write_char(0xef))
            return -1;
          if (i2c_read_char(&u.uc[2]))
            return -1;
          i2c_send_ack();
          if (i2c_read_char(&u.uc[1]))
            return -1;
          i2c_send_ack();
          if (i2c_read_char(&u.uc[0]))
            return -1;
          i2c_send_nak();
          i2c_stop_tx();
         baro_up = u.l >> (8-BARO_OSS);

        // need lots of work here
        x1 = ((baro_ut-baroparams.ac6)*baroparams.ac5) >> 15;
          x2 = (((long)baroparams.mc)<<11)/(x1+baroparams.md);
          b5 = x1+x2;
          t = (b5+8)>>4;
    //          sprintf(g_Temperature,"%ld",t);
        // append units
        gf_Temperature = t / 10.0;
        if (gConfiguration.tempUnits == Celcius) {
            sprint_fixedpoint(g_Temperature,t,1);
            strlcat(g_Temperature, "&deg;C", sizeof g_Temperature);
        }
        else {
            sprint_fixedpoint(g_Temperature, CelciusToF(t), 1);
            strlcat(g_Temperature, "&deg;F", sizeof g_Temperature);
        }
        b6 = b5 - 4000;
        b6x = (b6*b6)>>12;
         x1 = (baroparams.b2*b6x)>>11;
         x2 = (baroparams.ac2*b6)>>11;
        x3 = x1 + x2;
         b3 = ((((long)baroparams.ac1*4+x3)<<BARO_OSS)+2)/4;

         x1 = (baroparams.ac3*b6)>>13;
         x2 = (baroparams.b1*b6x)>>16;
         x3 = ((x1+x2)+2)>>2;
         b4 = baroparams.ac4*(unsigned long)(x3+32768)>>15;
         b7 = ((unsigned long)baro_up-b3)*(50000>>BARO_OSS);
         if (b7 < 0x80000000)
             p = (b7*2)/b4;
         else
             p = (b7/b4)*2;
         x1 = (p>>8)*(p>>8);
         x1 = (x1*3038)>>16;
         x2 = (-7357*p)>>16;
         p = p + ((x1+x2+3791)>>4);

        gf_Pressure = p / 100.0;
        // append units
        if (gConfiguration.baroUnits == Millibars) {
            sprint_fixedpoint(g_Pressure,p,2);
            strlcat(g_Pressure, " millibars", sizeof g_Pressure);
        }
        else {
            sprint_fixedpoint(g_Pressure, millibarsToInHg(p), 2);
            strlcat(g_Pressure, " inHg", sizeof g_Pressure);
        }
        BarometerPhase = BP_STARTTEMP;
    break;
}

return 0;
}

Sensor Bosch BMP085 hoja de datos

    
pregunta fred basset

2 respuestas

4

Esto comenzó como un comentario, pero en realidad es una respuesta:

Parece que tienes mucho más código del necesario para depurar una función básica de hardware. Primero debe intentar asegurarse de que sabe cómo operar el IC correctamente. Pedir a las personas que vaguen y depuren código que agrega capas a la funcionalidad básica es una manera mucho más difícil de hacer las cosas. Entonces -

Simplifique lo que está haciendo al mínimo para que esté

  • probando la funcionalidad del hardware

  • y su comprensión de ello.

Una vez que esté seguro de esto, debe agregar capas de complejidad.

Es bastante probable que esté haciendo algo mal en el procesamiento en lugar de la entrada de datos básicos. Su código debe abordar la mínima interacción de hardware posible para obtener las señales centrales.

    
respondido por el Russell McMahon
1

¿Ha intentado conectar un analizador de bus al I2C? El hecho de que el microprocesador esté diciendo que está leyendo 0xFFFF no significa que eso sea lo que está en el bus I2C. Si un sensor no está transmitiendo datos al bus, obtendrá todos los 1 debido a las resistencias de pull-up.

El uso de un analizador de bus le ayudaría a determinar si el 0xFFFF proviene del Rabbit o del BMP085. También es posible que el 0xFFFF sea algún tipo de código de error del BMP085.

    
respondido por el mjh2007

Lea otras preguntas en las etiquetas