HP203B气压温度传感器驱动

废话不多说,直接上代码。

设备树代码如下,需要注意的是在设备中描述的I2C器件地址是7位的,不是8位的,否则I2C子系统初始化时会提示找不到设备。

i2c3: i2c@50008c00 {
	compatible = "xxx-i2c3";
	reg = <0x50008c00 0x800>;
	#address-cells = <1>;
	#size-cells = <0>;
	interrupts = ;
	i2c_speed = <100000>;

	hb203b@77{
		compatible = "hp203b";
		reg = <0x77>;
	};		
	
};

驱动程序:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include    

#define HP20X_READ_P            0x30  //read_p command
#define HP20X_READ_A            0x31  //read_a command
#define HP20X_READ_T            0x32  //read_t command
#define HP20X_READ_PT           0x10  //read_pt command
#define HP20X_READ_AT           0x11  //read_at command
#define HP20X_READ_CAL		    0X28	//RE-CAL ANALOG

struct hp203b
{
    struct device *device; 
    int init;
    struct mutex lock;
    struct i2c_client *client; 
} ;

#define HP203B_IOCTL_DOWN(dev)     mutex_lock(&dev->lock)
#define HP203B_IOCTL_UP(dev)       mutex_unlock(&dev->lock)

#define HP203B_CHECK_INIT(dev)                              \
                    do{                                     \
                        if(!dev->init) {                    \
                            HP203B_IOCTL_DOWN(dev);         \
                            hp203b_reset(dev->client);      \
                            HP203B_IOCTL_UP(dev);           \
                            msleep(3);                      \
                            dev->init = 1;                  \
                         }                                  \
                    }while(0)
                    
static unsigned char hp203b_write_cmd(struct i2c_client *client,const unsigned char cmd)
{ 
	unsigned char txbuf[1] = {cmd};
	struct i2c_msg msg[1] = {
		[0] = {
			.addr = client->addr,
			.flags= 0,
			.len = sizeof(txbuf),
			.buf = txbuf,
		},
	};
	if(i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) < 0)
    {
        printk(KERN_EMERG"hp203b_write_cmd fail\n");
        return 0xFF;
    }
    return 0;
}
/*
static unsigned char hp203b_write_reg(struct i2c_client *client,const unsigned char reg,const unsigned char val)
{ 
	unsigned char txbuf[2] = {reg | 0x80, val};
	struct i2c_msg msg[1] = {
		[0] = {
			.addr = client->addr,
			.flags= 0,
			.len = sizeof(txbuf),
			.buf = txbuf,
		},
	};
	if(i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) < 0)
    {
        printk(KERN_EMERG"hp203b_write_reg fail\n");
        return 0xFF;
    }
    return 0;
}

static unsigned char hp203b_read_reg(struct i2c_client *client, const unsigned char reg)
{
	unsigned char txbuf[1] = {reg | 0x80};
	unsigned char rxbuf[1] = {0};

	struct i2c_msg msg[2] = {
		[0] = {
			.addr = client->addr,
			.flags = 0,
			.len = sizeof(txbuf),
			.buf = txbuf,
		},
		[1] = {
			.addr = client->addr,
			.flags = I2C_M_RD,
			.len = sizeof(rxbuf),
			.buf = rxbuf,
		},
	};

	if(i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) < 0)
    {
        printk(KERN_EMERG"hp203b_read_reg fail\n");
        return 0;
    }
	return rxbuf[0];
}
*/

static int hp203b_read_3byte_data(struct i2c_client *client, unsigned char cmd)
{
	unsigned char txbuf[1] = {cmd};
	unsigned char rxbuf[3] = {0};
    int data;
	struct i2c_msg msg[2] = {
		[0] = {
			.addr = client->addr,
			.flags = 0,
			.len = sizeof(txbuf),
			.buf = txbuf,
		},
		[1] = {
			.addr = client->addr,
			.flags = I2C_M_RD,
			.len = sizeof(rxbuf),
			.buf = rxbuf,
		},
	};

	if(i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) < 0)
    {
        printk(KERN_EMERG"hp203b_read_3byte_data fail\n");
        return -1;
    }

    data = ((rxbuf[0] << 16) | (rxbuf[1] << 8) | rxbuf[2]) & 0xfffff;
    if(data & 0x80000)
        data |= 0xfff00000;            //补码处理    

    return data;
    // return data / 100;
}

static unsigned char hp203b_reset(struct i2c_client *client)
{
    return hp203b_write_cmd(client, 0x06);
}

static unsigned char hp203b_set_osr_channel(struct i2c_client *client, unsigned char osr, unsigned channel)
{
    unsigned char cmd = 0;

    cmd = 0x40 | ((osr & 0x07) << 3) | (channel & 0x03);

    return hp203b_write_cmd(client, cmd);
}

static int hp203b_read_pressure(struct i2c_client *client)
{
    return hp203b_read_3byte_data(client, HP20X_READ_P);
}

static int hp203b_read_altitude(struct i2c_client *client)
{
    return hp203b_read_3byte_data(client, HP20X_READ_A);
}

static int hp203b_read_temperature(struct i2c_client *client)
{
    return hp203b_read_3byte_data(client, HP20X_READ_T);
}

static ssize_t hp203b_pressure_show(struct device *dev,
			   struct device_attribute *attr, char *buf)
{
	struct hp203b *hp203b = dev_get_drvdata(dev);
	int data = 0;
	
    HP203B_CHECK_INIT(hp203b);
    HP203B_IOCTL_DOWN(hp203b);
    hp203b_set_osr_channel(hp203b->client, 0, 0);
    msleep(135);    
	data = hp203b_read_pressure(hp203b->client);
    HP203B_IOCTL_UP(hp203b);
    
	return sprintf(buf, "%d\n", data);
}

static ssize_t hp203b_altitude_show(struct device *dev,
			   struct device_attribute *attr, char *buf)
{
	struct hp203b *hp203b = dev_get_drvdata(dev);
	int data = 0;

    
    HP203B_CHECK_INIT(hp203b);
    HP203B_IOCTL_DOWN(hp203b);
    hp203b_set_osr_channel(hp203b->client, 0, 0);
    msleep(135);
	data = hp203b_read_altitude(hp203b->client);
    HP203B_IOCTL_UP(hp203b);
    
	return sprintf(buf, "%d\n", data);

}

static ssize_t hp203b_temperature_show(struct device *dev,
			   struct device_attribute *attr, char *buf)
{
	struct hp203b *hp203b = dev_get_drvdata(dev);
	int data = 0;

    HP203B_CHECK_INIT(hp203b);
    HP203B_IOCTL_DOWN(hp203b);
    hp203b_set_osr_channel(hp203b->client, 0, 0);
    msleep(135);
	data = hp203b_read_temperature(hp203b->client);
    HP203B_IOCTL_UP(hp203b);
    
	return sprintf(buf, "%d\n", data);
}

/* sysfs attributes */
static SENSOR_DEVICE_ATTR_RO(pressure, hp203b_pressure, 0);
static SENSOR_DEVICE_ATTR_RO(altitude, hp203b_altitude, 0);
static SENSOR_DEVICE_ATTR_RO(temperature, hp203b_temperature, 0);

static struct attribute *hp203b_attrs[] = {
	&sensor_dev_attr_pressure.dev_attr.attr,
	&sensor_dev_attr_altitude.dev_attr.attr,
	&sensor_dev_attr_temperature.dev_attr.attr,
	NULL
};

ATTRIBUTE_GROUPS(hp203b);

static int hp203b_probe(struct i2c_client *client)
{
	struct device *dev = &client->dev;
	struct device *hwmon_dev;
	struct hp203b *hp203b;

	printk(KERN_EMERG"hp203b_probe\n");

	hp203b = devm_kzalloc(dev, sizeof(*hp203b), GFP_KERNEL);
	if (!hp203b)
		return -ENOMEM;

	hp203b->client = client;

	mutex_init(&hp203b->lock);

	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
							   hp203b, hp203b_groups);
	return PTR_ERR_OR_ZERO(hwmon_dev);
}

static const struct i2c_device_id hp203b_id[] = {
    { "hp203b", 0 },
    {},
};
MODULE_DEVICE_TABLE(i2c, hp203b_id);

static struct i2c_driver hp203b_driver = {
    .driver = {
        .owner = THIS_MODULE,
        .name = "hp203b",
    },
    .probe_new = hp203b_probe,
    .id_table = hp203b_id,
};

module_i2c_driver(hp203b_driver);

#define VERSION_LEN   16
static char ver[VERSION_LEN];
module_param_string(version, ver, VERSION_LEN, S_IRUGO);
MODULE_PARM_DESC(version,"1.5.5");
MODULE_VERSION("1.5.5");
MODULE_AUTHOR("Dokin");
MODULE_DESCRIPTION("hp203b driver");
MODULE_LICENSE("GPL");

测试结果如下,注意结果要除以100才是最后真实的值。

cat /sys/devices/platform/50007800.i2c/i2c-1/1-0077/hwmon/hwmon3/temperature
3049

cat /sys/devices/platform/50007800.i2c/i2c-1/1-0077/hwmon/hwmon3/pressure 
102830

cat /sys/devices/platform/50007800.i2c/i2c-1/1-0077/hwmon/hwmon3/altitude 
-12475

你可能感兴趣的:(Linux驱动,HP203B,Linux,I2C驱动,气压计温度计)