相比于TH06C,TH09C精度更高,温度和湿度都有24位数据(3个字节),需要先发送指定位为1才能开始测数据,相比TH06C麻烦了一点(th06只有16位数据,而且直接读0xe3和0xe5就可以了)。调试OK只要cat /sys/bus/i2c/devices/2-0043/temperature 和 cat /sys/bus/i2c/devices/2-0043/humidity查看数据即可。
下面附上代码
/**
&i2c0 {
th09: th09@43 {
compatible = "th09";
reg = <0x43>;
};
}; //th09
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#define HDC1080_REG_TEMP 0x00
#define HDC1080_REG_HUMIDITY 0x01
#define HDC1080_REG_CONFIG 0x02
#define HDC1080_REG_CONFIG_HEATER_EN BIT(13)
#define COMPATILE_NAME "th09"
struct i2c_demo_priv {
struct i2c_client *client;
};
static const struct i2c_device_id i2c_demo_id[] = {
{ COMPATILE_NAME, 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, i2c_demo_id);
#ifdef CONFIG_OF
static const struct of_device_id i2c_demo_of_table[] = {
{ .compatible = COMPATILE_NAME },
{ }
};
MODULE_DEVICE_TABLE(of, i2c_demo_of_table);
#endif
static int debug_enable = 0;
module_param(debug_enable,int, 0644);
static ssize_t temp_value_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct i2c_demo_priv *priv = dev_get_drvdata(dev);
int err = 0;
char data[6];
char DataBuf[3];
int val, temp;
dev_info(dev, "%s addr=%d\n", __func__, priv->client->addr);
DataBuf[0] = 0x21;
DataBuf[1] = 0x00;
DataBuf[2] = 0x03;
err = i2c_master_send(priv->client, DataBuf, 3);
if(err != 3){
dev_err(dev, "i2c_master_send fail, err=%d\n", err);
}
msleep(130);
data[0] = 0x30;
err = i2c_master_send(priv->client, data, 1);
if(err != 1){
dev_err(dev, "i2c_master_send fail, err=%d\n", err);
}
msleep(20);
memset(data, 0 , sizeof(data));
err = i2c_master_recv(priv->client, data, 6);
if(err != 6){
dev_err(dev, "i2c_master_recv fail, err=%d\n", err);
}
// val = (data[0] << 8) + data[1];
// temp = 17572 * val / 65536 - 4686 - 250;
val = (data[2] << 16) + (data[1] << 8)+ data[0];
if(((val >> 16) & 0x0001) == 1)
{
temp = ((((val & 0xFFFF)*100) / 64) - 27315);
}
else
temp = 0;
dev_info(dev, "val=%d, temp=%d\n", val, temp);
return sprintf(buf, "%d\n",temp);
}
static ssize_t humidity_value_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct i2c_demo_priv *priv = dev_get_drvdata(dev);
int err = 0;
char data[6];
char DataBuf[3];
int val, temp;
dev_info(dev, "%s addr=%d\n", __func__, priv->client->addr);
DataBuf[0] = 0x21;
DataBuf[1] = 0x00;
DataBuf[2] = 0x03;
err = i2c_master_send(priv->client, DataBuf, 3);
if(err != 3){
dev_err(dev, "i2c_master_send3 fail, err=%d\n", err);
}
msleep(130);
data[0] = 0x30;
err = i2c_master_send(priv->client, data, 1);
if(err != 1){
dev_err(dev, "i2c_master_send1 fail, err=%d\n", err);
}
msleep(20);
memset(data, 0 , sizeof(data));
err = i2c_master_recv(priv->client, data, 6);
if(err != 6){
dev_err(dev, "i2c_master_recv fail, err=%d\n", err);
}
// val = (data[0] << 8) + data[1];
// temp = 125 * val / 65536 - 6;
val = (data[5] << 16) + (data[4] << 8) + data[3];
if(((val >> 16) & 0x0001) == 1)
{
temp = (((val & 0xFFFF)*100) / 512);
}
else
temp = 0;
//dev_info(dev, "data[5]=%d, data[4]=%d, data[3]=%d\n", data[5], data[4],data[3]);
dev_info(dev, "val=%d, temp=%d\n", val, temp);
return sprintf(buf, "%d\n",temp);
}
static DEVICE_ATTR(temperature, S_IRUGO, temp_value_show, NULL);
static DEVICE_ATTR(humidity, S_IRUGO, humidity_value_show, NULL);
static int i2c_demo_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device_node *node;
struct i2c_demo_priv *chip;
int ret;
dev_info(&client->dev, "%s enter\n", __func__);
node = client->dev.of_node;
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
chip->client = client;
i2c_set_clientdata(client, chip);
ret = device_create_file(&client->dev, &dev_attr_temperature);
if(ret){
dev_err(&client->dev, "Unable to device_create_file: %d\n", ret);
}
ret = device_create_file(&client->dev, &dev_attr_humidity);
if(ret){
dev_err(&client->dev, "Unable to device_create_file: %d\n", ret);
}
return 0;
}
static int i2c_demo_remove(struct i2c_client *client)
{
//struct i2c_demo_priv *chip = i2c_get_clientdata(client);
dev_info(&client->dev, "%s enter\n", __func__);
return 0;
}
void i2c_demo_shutdown(struct i2c_client *client)
{
// struct i2c_demo_priv *chip = i2c_get_clientdata(client);
dev_info(&client->dev, "%s enter\n", __func__);
}
static struct i2c_driver i2c_demo_driver = {
.driver = {
.name = "i2c_demo",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(i2c_demo_of_table),
},
.probe = i2c_demo_probe,
.remove = i2c_demo_remove,
.id_table = i2c_demo_id,
.shutdown = i2c_demo_shutdown,
};
static int __init i2c_demo_init(void)
{
return i2c_add_driver(&i2c_demo_driver);
}
/* register after i2c postcore initcall and before
* subsys initcalls that may rely on these GPIOs
*/
#if 1
subsys_initcall_sync(i2c_demo_init);
#else
module_init(i2c_demo_init);
#endif
static void __exit i2c_demo_exit(void)
{
i2c_del_driver(&i2c_demo_driver);
}
module_exit(i2c_demo_exit);
MODULE_AUTHOR("tj <tj_wust@163.com>");
MODULE_DESCRIPTION("i2c th09 driver");
MODULE_LICENSE("GPL");