HP203B气压温度传感器驱动

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

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

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

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

驱动程序:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/jiffies.h>
#include <linux/delay.h>   

#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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
HP203B是一种基于单片机的设备,单片机驱动是指使用单片机控制HP203B设备的功能和操作。 HP203B是一种数字压力传感器模块,可以测量大气压力和温度。单片机驱动是将单片机与HP203B模块连接起来,并通过编程实现对模块的控制和数据处理。 首先,需要将HP203B模块与单片机进行连接。可以通过引脚连接或者串口通信等方式实现。然后,在单片机的程序中编写相关的驱动代码。 驱动代码的编写包括初始化模块、发送指令以及接收和解析数据等操作。首先,需要对HP203B模块进行初始化,设置模块的工作模式和相应的参数。然后,可以通过发送指令的方式要求模块进行测量操作,例如测量大气压力和温度。 接着,单片机通过接收模块返回的数据,将数据进行解析和处理。可以通过读取相应的寄存器或者通过串口通信接收数据。解析数据后,可以根据需要进行单位转换、计算等操作,以得到最终的压力和温度数值。 最后,根据单片机的需求进行相应的处理和应用。例如,可以将测得的数据显示在LCD屏幕上,或者发送到其他设备进行处理和存储等。 总结来说,HP203B单片机驱动是通过编写相关的代码,实现单片机与HP203B模块的连接和控制,以获取并处理模块的测量数据。这样,我们可以利用单片机的高效性能和灵活性,实现对HP203B设备的灵活应用和控制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dokin丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值