资讯详情

LM75温度传感器驱动

#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/device.h> //#include <linux/sysdev.h> #include <asm/uaccess.h> #include <linux/slab.h> #include <linux/kdev_t.h> #include <linux/i2c.h>  #define DEV_NAME  "myir-stlm75x"  /*********************  * Register define  *  *********************/ #define REG_TEMP 0x0 #define REG_CON  0x1 #define REG_TOS  0x2 #define REG_THYS 0x3  #define MAX_CONV_MS 150 #define SIGN_MASK (0x1 << 15) #define TEMP_SHIFT 7 #define TEMP_MASK (0xFF << TEMP_SHIFT) #define DEGREE_PER_CNT 0.5  struct myir_stlm75x_data {  struct i2c_client *client;  struct class class;  struct mutex mutex;  u16 temp_tos;  u16 temp_thys;  u16 temp_value; };  inline int to_readable_value(u16 _value) {  int value;  if (_value & SIGN_MASK) {   value = -(~((_value & TEMP_MASK) >> TEMP_SHIFT)   1);  } else {   value = ((_value & TEMP_MASK) >> TEMP_SHIFT);  } // printk(KERN_ERR "value to read: %d\n", value);  return value; }  #if 0 inline u16 to_register_value(int/*float*/ degreex2) {  u16 ret;  if (degreex2 > 255) {   degreex2 = 255;  } else if (degreex2 < -255) {   degreex2 = -255;  }  ret = (u16)degreex2;  if (degreex2 >= 0) {   ret = (ret << TEMP_SHIFT) & TEMP_MASK;  } else {   ret = (ret << TEMP_SHIFT) & 0xFFFF;  }  printk(KERN_ERR "value to write: %#X\n", ret);  return ret; } #endif  static int myir_stlm75x_readwrite(struct i2c_client *client,                    u16 wr_len, u8 *wr_buf,                    u16 rd_len, u8 *rd_buf) {     struct i2c_msg wrmsg[2];     int i = 0;     int ret;      if (wr_len) {         wrmsg[i].addr  = client->addr;         wrmsg[i].flags = 0;         wrmsg[i].len = wr_len;         wrmsg[i].buf = wr_buf;         i  ;     }     if (rd_len) {         wrmsg[i].addr  = client->addr;         wrmsg[i].flags = I2C_M_RD;         wrmsg[i].len = rd_len;         wrmsg[i].buf = rd_buf;         i  ;     }      ret = i2c_transfer(client->adapter, wrmsg, i);     if (ret < 0)         return ret;     if (ret != i)         return -EIO;      return 0; }  static int myir_stlm75x_write_word(struct myir_stlm75x_data *pdata,                      u8 addr, u16 value) {     u8 wrbuf[3]={0};      wrbuf[0] = addr;     wrbuf[1] = (value>>8)&0xFF;     wrbuf[2] = value&0xFF;      return myir_stlm75x_readwrite(pdata->client, 3, wrbuf, 0, NULL); }  static int myir_stlm75x_write_byte(struct myir_stlm75x_data *pdata,                      u8 addr, u8 value) {     u8 wrbuf[2]={0};      wrbuf[0] = addr;     wrbuf[1] = value;      return myir_stlm75x_readwrite(pdata->client, 2, wrbuf, 0, NULL); }  static int myir_stlm75x_read_word(struct myir_stlm75x_data *pdata,                     u8 addr) {     u8 wrbuf[2], rdbuf[2]={0};     int error;      wrbuf[0] = addr;      error = myir_stlm75x_readwrite(pdata->client, 1, wrbuf, 2, rdbuf);     if (error)         return error;      return rdbuf[0]<<8|rdbuf[1]; }  static int myir_stlm75x_read_byte(struct myir_stlm75x_data *pdata,                     u8 addr) {     u8 wrbuf[2], rdbuf[2]={0};     int error;      wrbuf[0] = addr;      error = myir_stlm75x_readwrite(pdata->client, 1, wrbuf, 1, rdbuf);     if (error)         return error;      return rdbuf[0]; }  /* class attribute show function. */ static ssize_t myir_stlm75x_show(struct class *cls, struct class_attribute *attr, char *buf) {  struct myir_stlm75x_data *pdata = (struct myir_stlm75x_data *)container_of(cls, struct myir_stlm75x_data, class);  int ret;  int value;  unsigned long start_time;    mutex_lock(&pdata->mutex);    start_time = jiffies;  pdata->temp_value = myir_stlm75x_read_word(pdata, REG_TEMP); // printk(KERN_ERR "pdata->temp_value: %#X", pdata->temp_value);  value = to_readable_value(pdata->temp_value);  ret = sprintf(buf, "%d.%s\n", value/2, value%2?"5":"0");   while (time_before(jiffies, start_time   msecs_to_jiffies(MAX_CONV_MS))) schedule();    mutex_unlock(&pdata->mutex);    return ret; }  /* Attributes declaration: Here I have declared only one attribute attr1 */ static struct class_attribute myir_stlm75x_class_attrs[] = {  __ATTR(value_degree, S_IRUGO | S_IWUSR , myir_stlm75x_show, NULL), //use macro for permission  __ATTR_NULL };  static int myir_stlm75x_probe(struct i2c_client *client,                      const struct i2c_device_id *id) {  int ret = 0;  struct myir_stlm75x_data *pdata = NULL;    printk(KERN_ALERT "%s()\n", __func__);    pdata = kmalloc(sizeof(struct myir_stlm75x_data), GFP_KERNEL);  if(!pdata) {   printk(KERN_ERR "No memory!\n");   return -ENOMEM;  }  memset(pdata, 0, sizeof(struct myir_stlm75x_data));   pdata->client = client;    /* Init class */  mutex_init(&pdata->mutex);  pdata->class.name= DEV_NAME;
	pdata->class.owner = THIS_MODULE;
	pdata->class.class_attrs = myir_stlm75x_class_attrs;
	ret = class_register(&pdata->class);
	if(ret) {
		printk(KERN_ERR "class_register failed!\n");
		goto class_register_fail;
	}
	i2c_set_clientdata(client, pdata);
	
	printk(KERN_ALERT "%s driver initialized successfully!\n", DEV_NAME);
	return 0;

class_register_fail:
	
	return ret;
}

static int myir_stlm75x_remove(struct i2c_client *client)
{
    struct myir_stlm75x_data *pdata = i2c_get_clientdata(client);
	
	class_unregister(&pdata->class);
	kfree(pdata);
	i2c_set_clientdata(client, NULL);
    return 0;
}

static const struct i2c_device_id myir_stlm75x_id[] = {
    { DEV_NAME, 0 },
    { }
};

static struct i2c_driver myir_stlm75x_driver = {
    .driver = {
        .owner	= THIS_MODULE,
        .name	= DEV_NAME,
    },
    .id_table	= myir_stlm75x_id,
    .probe		= myir_stlm75x_probe,
    .remove		= myir_stlm75x_remove,
};

module_i2c_driver(myir_stlm75x_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kevin Su <kevin.su@myirtech.com>");
MODULE_DESCRIPTION("MYIR stlm75x temperature driver.");

标签: con021传感器cnt温度传感器cnt传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台