si7006.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/fs.h>
#include "si7006.h"
#include<linux/cdev.h>
#include<linux/device.h>
#include<linux/uaccess.h>
struct i2c_client *cli;
struct cdev *cdev;
struct class *cls;
struct device *dev;
dev_t devno;
unsigned int count=1;
#if 0
unsigned int major=0;
#else
unsigned int major=500;
#endif
unsigned int minor=0;
int si7006_open(struct inode *node, struct file *file)
{
printk("%s:%s:%d",__FILE__,__func__,__LINE__);
return 0;
}
int si7006_close(struct inode *node, struct file *file)
{
printk("%s:%s:%d",__FILE__,__func__,__LINE__);
return 0;
}
unsigned short i2c_read_hum_tem(unsigned char reg)
{
int ret;
char r_buf[]={reg};
unsigned short val;
struct i2c_msg r_msg[]={
[0]={
.addr=cli->addr,
.flags=0,
.len=1,
.buf=r_buf,
},
[1]={
.addr=cli->addr,
.flags=1,
.len=2,
.buf=(char*)&val,
},
};
ret=i2c_transfer(cli->adapter,r_msg,ARRAY_SIZE(r_msg));
if(ret!=ARRAY_SIZE(r_msg))
{
printk("i2c_transfer 读取温湿度失败\n");
return ret;
}
return val;
}
long si7006_ioctl(struct file *node, unsigned int cmd, unsigned long arg)
{
int tem,hum;
int ret;
switch (cmd)
{
case GET_TEM:
tem=i2c_read_hum_tem(0xE3);
ret=copy_to_user((void *)arg,(void *)&tem,sizeof(int));
if(ret)
{
printk("给用户拷贝数据失败\n");
return -EINVAL;
}
break;
case GET_HUM:
hum=i2c_read_hum_tem(0xE5);
ret=copy_to_user((void *)arg,(void *)&hum,sizeof(int));
if(ret)
{
printk("给用户拷贝数据失败\n");
return -EINVAL;
}
break;
default:
break;
}
return 0;
}
struct file_operations fops={
.open=si7006_open,
.release=si7006_close,
.unlocked_ioctl=si7006_ioctl,
};
int si7006_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int ret,i;
cli=client;
cdev=cdev_alloc();
if(cdev==NULL)
{
printk("cdev alloc memory err\n");
ret = -ENOMEM;
goto ERR1;
}
printk("对象分配成功\n");
cdev_init(cdev,&fops);
if(major==0)
{
ret=alloc_chrdev_region(&devno,minor,count,"my_i2c");
if(ret)
{
printk("动态申请设备号失败\n");
goto ERR2;
}
major = MAJOR(devno);
minor = MINOR(devno);
printk("动态申请设备号成功\n");
}
else
{
ret=register_chrdev_region(MKDEV(major,minor),count,"my_i2c");
if(ret)
{
printk("静态申请设备号失败\n");
goto ERR2;
}
printk("静态申请设备号成功\n");
}
ret=cdev_add(cdev,MKDEV(major,minor),count);
if(ret)
{
printk("字符设备驱动注册失败\n");
goto ERR3;
}
printk("注册字符设备驱动成功\n");
cls = class_create(THIS_MODULE,"home");
if(IS_ERR(cls))
{
printk("创建逻辑节点目录失败\n");
ret=PTR_ERR(cls);
goto ERR4;
}
printk("创建逻辑节点目录成功\n");
for(i=0;i<count;i++)
{
dev = device_create(cls,NULL,MKDEV(major,i),NULL,"si7006");
if(IS_ERR(dev))
{
printk("创建逻辑节点失败\n");
ret = PTR_ERR(dev);
goto ERR5;
}
}
printk("创建逻辑节点成功\n");
return 0;
ERR5:
for(--i;i>=0;i--)
{
device_destroy(cls,MKDEV(major,i));
}
class_destroy(cls);
ERR4:
cdev_del(cdev);
ERR3:
unregister_chrdev_region(MKDEV(major,minor),count);
ERR2:
kfree(cdev);
ERR1:
return ret;
}
int si7006_remove(struct i2c_client *client)
{
int i;
for(i=0;i<count;i++)
{
device_destroy(cls,MKDEV(major,i));
}
class_destroy(cls);
cdev_del(cdev);
unregister_chrdev_region(MKDEV(major,minor),count);
kfree(cdev);
return 0;
}
struct of_device_id oftable[]={
{.compatible="hqyj,si7006"},
{},
};
MODULE_DEVICE_TABLE(of,oftable);
struct i2c_driver si7006={
.probe=si7006_probe,
.remove=si7006_remove,
.driver={
.name="hum and tem_driver",
.of_match_table = oftable,
},
};
module_i2c_driver(si7006);
MODULE_LICENSE("GPL");
si7006.h
#ifndef __SI7006_H__
#define __SI7006_H__
#define GET_TEM _IOR('m',0,int)
#define GET_HUM _IOR('m',1,int)
#endif
读取温度的主函数
#include<stdio.h>
#include<sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "si7006.h"
#include <stdlib.h>
#include <arpa/inet.h>
int main(int argc,char const *argv[])
{
int hum,tem;
float hum1,tem1;
int fd=open("/dev/si7006",O_RDWR);
if(fd<0)
{
perror("open err\n");
exit(-1);
}
printf("打开文件成功\n");
printf("开始读取温湿度\n");
while (1)
{
ioctl(fd,GET_TEM,&tem);
ioctl(fd,GET_HUM,&hum);
tem=ntohs(tem);
hum=ntohs(hum);
tem1= 175.72*tem/65536-46.85;
hum1= 125*hum/65536-6;
printf("tem=%f hum=%f\n",tem1,hum1);
}
return 0;
}