开发者

I2C temperature read from BMP085 reading back 0xffff

I'm interfacing a Rabbit 5760 CPU to a Bosch BMP085 sensor via I2C. Everything is fine except reading the temperature register is reading back 0xffff (see BP_FINISHTEMP case in switch). I can't see why it isn't working. The code is below. Can anyone see what's wrong? The pressure and calibration values read back fine. Thanks if anyone can help.

    // 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);

   开发者_JS百科    // 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; // THIS IS THE PROBLEM U.L IS 0XFFFF HERE ******************************
            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;
}


Perhaps you doesn't read from the chip, you get an error which results in one of the return -1
You should debug this part, or you could change the (error) result values to return 1, return 2 ... return 7 to get the problematic line.

Perhaps this could also a problem of your union of uc[4] and long.
This can work, but it depends of the compiler/platform you use and it isn't a good, safe solution.
Better you use something like

i2c_read_char(byteVal);
value=((uint16_t)byteVal) << 8;
i2c_read_char(byteVal);
value|=byteVal;


Turns out it was bad hardware. A new batch of chips works fine.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜