我是i2c编程的新手,我正在尝试从Bosch BPM085(datasheet)读取压力和温度值。我计算的温度值似乎是正确的,但hPa压力值不是我预期的。 实际上我得到了~996 hPa但是我应该在我的位置获得大约1017 hPa的东西。 作为平台,我正在使用支持I2C的Raspberry Pi。与I2C的通信通过/ dev / i2c-0完成。
传感器的接线方式如数据表第10页所述,但未连接XCLR和EOC。
到目前为止我认识到了:
有人可以在下面的代码中看到失败吗? i2c通信是否正确实现(如第14页的数据表中所述)?
这是我的代码:(因为我不是C开发人员请考虑一下; - )
#define BMP085_I2C_ADDR (0xEE>>1) //i2c addr of the sensor
#define BMP085_PROM_START_ADDR 0xaa //start addr of calibration coefficients
#define BMP085_PROM_DATA_LEN 22 //length of calibration coefficients
#define BMP085_CTRL_MEAS_REG 0xF4
#define BMP085_T_MEASURE 0x2E // temperature measurement
#define BMP085_P_MEASURE 0x34 // pressure measurement
#define BMP085_ADC_OUT_MSB_REG 0xF6
#define BMP085_ADC_OUT_LSB_REG 0xF7
#define BMP085_ADC_OUT_XLSB_REG 0xF8
typedef struct {
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;
} bmp085_calibration_data_t;
int file;
char buf[10] = {0};
bmp085_calibration_data_t calibrationData;
long T = 0l; // TEMPERATURE VALUE
long P = 0l; // PRESSURE VALUE
void bmp085_init(char *filename) {
if((file = open(filename, O_RDWR)) < 0) {
perror("failed to open the i2c bus.\n");
exit(1);
}
if(ioctl(file, I2C_SLAVE, BMP085_I2C_ADDR) < 0) {
perror("failed to acquire bus access and / or talk to slave.\n");
exit(1);
}
buf[0] = BMP085_PROM_START_ADDR;
writeToBus(file, buf, 1);
unsigned char data[BMP085_PROM_DATA_LEN];
if (read(file,data,BMP085_PROM_DATA_LEN) != BMP085_PROM_DATA_LEN) {
perror("Failed to read from the i2c bus.\n");
exit(1);
} else {
calibrationData.ac1 = (data[0] <<8) | data[1];
calibrationData.ac2 = (data[2] <<8) | data[3];
calibrationData.ac3 = (data[4] <<8) | data[5];
calibrationData.ac4 = (data[6] <<8) | data[7];
calibrationData.ac5 = (data[8] <<8) | data[9];
calibrationData.ac6 = (data[10] <<8) | data[11];
calibrationData.b1 = (data[12] <<8) | data[13];
calibrationData.b2 = (data[14] <<8) | data[15];
calibrationData.mb = (data[16] <<8) | data[17];
calibrationData.mc = (data[18] <<8) | data[19];
calibrationData.md = (data[20] <<8) | data[21];
}
}
// oss is the oversampling setting. in my case set to 0.
void read_sensor(short oss) {
long ut, up, X1, X2, X3, B3, B5, B6;
unsigned long B4, B7;
///////////// read uncompensated temperature /////////////
buf[0] = BMP085_CTRL_MEAS_REG;
buf[1] = BMP085_T_MEASURE;
writeToBus(file, buf, 2);
usleep(5000); // wait 5ms
buf[0] = BMP085_ADC_OUT_MSB_REG;
writeToBus(file, buf, 1);
char uncompTemp[2];
readFromBus(file, uncompTemp, 2);
ut = (uncompTemp[0]<<8) | uncompTemp[1];
///////////// calculate temperature /////////////
X1 = (((long) ut - (long) calibrationData.ac6) * (long) calibrationData.ac5) >> 15;
X2 = ((long) calibrationData.mc << 11) / (X1 + calibrationData.md);
B5 = X1 + X2;
T = ((B5 + 8) >> 4);
///////////// read uncompensated pressure //////////////
buf[0] = BMP085_CTRL_MEAS_REG;
buf[1] = BMP085_P_MEASURE + (oss<<6);
writeToBus(file, buf, 2);
usleep((2 + (3 << oss)) * 1000); // wait
char upBuf[3];
buf[0] = BMP085_ADC_OUT_MSB_REG;
writeToBus(file, buf, 1);
readFromBus(file, upBuf, 3);
up = (((unsigned long)upBuf[0]<<16) | ((unsigned long)upBuf[1]<<8) | (unsigned long)upBuf[2]) >> (8-oss);
//printf("up: %li\n", up);
///////////// calculate pressure /////////////
B6 = B5 - 4000;
X1 = (B6 * B6) >> 12;
X1 *= calibrationData.b2;
X1 >>=11;
X2 = calibrationData.ac2 * B6;
X2 >>=11;
X3 = X1 + X2;
B3 = (((((long)calibrationData.ac1 )*4 + X3) <<oss) + 2) >> 2;
X1 = (calibrationData.ac3 * B6) >> 13;
X2 = (calibrationData.b1 * ((B6 * B6) >> 12)) >> 16;
X3 = ((X1 + X2) + 2) >> 2;
B4 = (calibrationData.ac4 * (unsigned long)(X3 + 32768)) >> 15;
B7 = ((unsigned long)(up - B3) * (50000 >> oss));
if(B7 < 0x80000000) {
P = (B7 << 1) / B4;
} else {
P = (B7 / B4) << 1;
}
X1 = (P >> 8);
X1 *= X1;
X1 = (X1 * 3038) >> 16;
X2 = (-7357 * P) >> 16;
P += (X1 + X2 + 3791) >> 4;
}
void writeToBus(int file, char* data, int len) {
if(write(file, data, len) != len) {
perror("could not write data to bus\n");
exit(1);
}
}
void readFromBus(int file, char* data, int len) {
if(read(file, data, len) != len) {
perror("could not read from bus\n");
exit(1);
}
}