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, "°C", sizeof g_Temperature);
}
else {
sprint_fixedpoint(g_Temperature, CelciusToF(t), 1);
strlcat(g_Temperature, "°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.
精彩评论