标题:
ICP10125的驱动程序
[打印本页]
作者:
lxml
时间:
2021-12-9 15:23
标题:
ICP10125的驱动程序
在嵌入式开发板上使用c语言采用IIC获取ICP10125传感器的有效值文件内含相关文档及程序源码
ICP10125.c
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <linux/i2c-dev.h>
#include <i2c/smbus.h>
#include <unistd.h>
#define ICP_I2C_ID 0x63
#define ICP_CMD_READ_ID 0xefc8
#define ICP_CMD_SET_ADDR 0xc595
#define ICP_CMD_READ_OTP 0xc7f7
// Transmit T First
#define ICP_CMD_MEAS_LP 0x609c
#define ICP_CMD_MEAS_N 0x6825
#define ICP_CMD_MEAS_LN 0x70df
#define ICP_CMD_MEAS_ULN 0x7866
// 压力计算常数
typedef struct inv_invpres
{
int file;
u_int32_t min_delay_us;
u_int8_t pressure_en;
u_int8_t temperature_en;
float sensor_constants[4]; // OTP values
float p_Pa_calib[3];
float LUT_lower;
float LUT_upper;
float quadr_factor;
float offst_factor;
} inv_invpres_t;
int file_init()
{
int file = 0;
file = open("/dev/i2c-1", O_RDWR);
if (file < 0)
{
printf("open error\n");
exit(1);
}
if (ioctl(file, I2C_SLAVE, ICP_I2C_ID) < 0)
{
printf("ioctl error\n");
exit(1);
}
return file;
}
void init_base(struct inv_invpres *s, short *otp)
{
int i;
for (i = 0; i < 4; i++)
{
s->sensor_constants[i] = (float)otp[i];
// printf("sensor_constants[%d]:%.2f, ", i, s->sensor_constants[i]);
}
s->p_Pa_calib[0] = 45000.0;
s->p_Pa_calib[1] = 80000.0;
s->p_Pa_calib[2] = 105000.0;
s->LUT_lower = 3.5 * (1 << 20);
s->LUT_upper = 11.5 * (1 << 20);
s->quadr_factor = 1 / 16777216.0;
s->offst_factor = 2048.0;
// printf("\n");
}
int read_otp_from_i2c(struct inv_invpres *s, short *out)
{
unsigned char data_write[10];
unsigned char data_read[10] = {0};
int ret;
int i;
// OTP Read mode
data_write[0] = 0xC5;
data_write[1] = 0x95;
data_write[2] = 0x00;
data_write[3] = 0x66;
data_write[4] = 0x9C;
ret = write(s->file, data_write, 5);
if (ret == 0)
return 1;
// Read OTP values
for (i = 0; i < 4; i++)
{
data_write[0] = 0xC7;
data_write[1] = 0xF7;
ret = write(s->file, data_write, 2);
if (ret == 0)
return 1;
ret = read(s->file, data_read, 3);
if (ret == 0)
return 2;
out[i] = data_read[0] << 8 | data_read[1];
// printf("%02x, %02x, %02x\n", data_read[0], data_read[1], data_read[2]);
}
return 0;
}
int inv_invpres_init(struct inv_invpres *s)
{
short otp[4];
s->file = file_init();
read_otp_from_i2c(s, otp);
init_base(s, otp);
return 0;
}
// p_Pa -- List of 3 values corresponding to applied pressure in Pa
// p_LUT -- List of 3 values corresponding to the measured p_LUT values at the applied pressures.
void calculate_conversion_constants(struct inv_invpres *s, float *p_Pa,
float *p_LUT, float *out)
{
float A, B, C;
C = (p_LUT[0] * p_LUT[1] * (p_Pa[0] - p_Pa[1]) +
p_LUT[1] * p_LUT[2] * (p_Pa[1] - p_Pa[2]) +
p_LUT[2] * p_LUT[0] * (p_Pa[2] - p_Pa[0])) /
(p_LUT[2] * (p_Pa[0] - p_Pa[1]) +
p_LUT[0] * (p_Pa[1] - p_Pa[2]) +
p_LUT[1] * (p_Pa[2] - p_Pa[0]));
A = (p_Pa[0] * p_LUT[0] - p_Pa[1] * p_LUT[1] - (p_Pa[1] - p_Pa[0]) * C) / (p_LUT[0] - p_LUT[1]);
B = (p_Pa[0] - A) * (p_LUT[0] + C);
out[0] = A;
out[1] = B;
out[2] = C;
}
// p_LSB -- Raw pressure data from sensor
// T_LSB -- Raw temperature data from sensor
int inv_invpres_process_data(struct inv_invpres *s, int p_LSB, int T_LSB,
float *pressure, float *temperature)
{
float t;
float s1, s2, s3;
float in[3];
float out[3];
float A, B, C;
t = (float)(T_LSB - 32768);
s1 = s->LUT_lower + (float)(s->sensor_constants[0] * t * t) * s->quadr_factor;
s2 = s->offst_factor * s->sensor_constants[3] + (float)(s->sensor_constants[1] * t * t) * s->quadr_factor;
s3 = s->LUT_upper + (float)(s->sensor_constants[2] * t * t) * s->quadr_factor;
in[0] = s1;
in[1] = s2;
in[2] = s3;
calculate_conversion_constants(s, s->p_Pa_calib, in, out);
A = out[0];
B = out[1];
C = out[2];
*pressure = A + B / (C + p_LSB);
// printf("%.2f, %.2f, %.2f, %d\n", A, B, C, p_LSB);
*temperature = -45.f + 175.f / 65536.f * T_LSB;
return 0;
}
void measure(struct inv_invpres *s, int32_t *raw_t, int32_t *raw_p)
{
u_int8_t buf[2];
u_int8_t res_buf[12];
buf[0] = 0x68;
buf[1] = 0x25;
int ret = write(s->file, buf, 2);
if (ret != 2) {
printf("i2c transaction failed %d\n", ret);
}
while(read(s->file, res_buf, 9) !=9 ) usleep(10*1000);
{
// printf("contains the read byte \n");
// for(int i=0;i<9;i++)
// {
// printf("%02x ",res_buf[i]);
// }
// printf("\n");
}
*raw_t = (res_buf[0]<<8)|res_buf[1];
*raw_p = (res_buf[3]<<16)|(res_buf[4]<<8)|res_buf[6];
}
int main()
{
int32_t raw_t;
int32_t raw_p;
float temperature;
float pressure;
inv_invpres_t obj;
inv_invpres_init(&obj);
measure(&obj, &raw_t, &raw_p);
// printf("raw_t: %02x, raw_p: %02x \n", raw_t, raw_p);
inv_invpres_process_data(&obj, raw_p, raw_t,
&pressure, &temperature);
printf("%.3f,%.3f", temperature, pressure);
return 0;
}
复制代码
51hei.png
(4.61 KB, 下载次数: 78)
下载附件
2021-12-9 17:32 上传
pdf下载:
ICP-101251.2.zip
(1.28 MB, 下载次数: 8)
2021-12-9 15:20 上传
点击文件名下载附件
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1