头文件 head.h
#ifndef __HEAD_H__
#define __HEAD_H__
#define GET_HUM _IOR('m', 1, int)
#define GET_TEM _IOR('m', 0, int)
#endif
应用程序 si7006.c
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include "head.h"
int main(int argc, char const *argv[])
{
char buf[128]={0};
unsigned short hum,tem;
float hum1,tem1;
int fd = open("/dev/si7006",O_RDWR);
if(fd < 0)
{
printf("打开设备文件失败\n");
exit(-1);
}
while(1)
{
//读取温湿度数据
ioctl(fd,GET_HUM,&hum);
ioctl(fd,GET_TEM,&tem);
//进行字节序转换
hum = ntohs(hum);
tem = ntohs(tem);
//数据转换
hum1 = (float)hum*125/65536-6;
tem1 = (float)tem*175.72/65536-46.85;
printf("hum = %f tem = %f\n",hum1,tem1);
sleep(1);
}
close(fd);
return 0;
}
驱动程序 iic.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/fs.h>
#include <linux/device.h>
#include "head.h"
struct i2c_client *client1;
unsigned int major;
struct class *cls;
struct device *dev;
//封装读取温湿度数据的函数
short read_hum_tem_value(char reg)
{
short value; //保存读到的温湿度数据
char r_buf[] = {reg};
//消息结构体的封装
struct i2c_msg r_msg[] = {
[0] = {
.addr = client1->addr,
.flags = 0,
.len = sizeof(r_buf),
.buf = r_buf,
},
[1] = {
.addr =client1->addr,
.flags = 1,
.len = 2,
.buf = (char *)&value,
},
};
//发送消息
int ret = i2c_transfer(client1->adapter,r_msg,2);
if(ret != 2)
{
printk("消息传输失败\n");
return -1;
}
return value;
}
int mycdev_open(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
short hum,tem;
int ret;
switch ((cmd))
{
case GET_HUM:
hum = read_hum_tem_value(0xE5);
ret = copy_to_user((void *)arg,&hum,2);
if(ret)
{
printk("coyp_to_user err %d\n",__LINE__);
}
break;
case GET_TEM:
tem = read_hum_tem_value(0xE5);
ret = copy_to_user((void *)arg,&tem,2);
if(ret)
{
printk("coyp_to_user err %d\n",__LINE__);
}
break;
}
return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
//定义操作方法结构体变量并复制
struct file_operations fops = {
.open = mycdev_open,
.unlocked_ioctl = mycdev_ioctl,
.release = mycdev_close,
};
//给对象分配空间并且初始化
int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
client1 = client;
int ret;
//float hum1,tem1;
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
//字符设备驱动的注册
major = register_chrdev(0,"si7006",&fops);
if(major < 0)
{
printk("字符设备驱动注册失败\n");
ret = major;
goto out1;
}
printk("字符设备驱动注册成功\n");
//向上提交目录
cls = class_create(THIS_MODULE,"si7006");
if(IS_ERR(cls))
{
printk("向上提交目录失败\n");
ret = -PTR_ERR(cls);
goto out2;
}
printk("向上提交目录成功\n");
//向上提交设备节点信息
dev = device_create(cls,NULL,MKDEV(major,0),NULL,"si7006");
if(IS_ERR(dev))
{
printk("向上提交设备节点失败\n");
ret = -PTR_ERR(dev);
goto out3;
}
printk("向上提交设备节点成功\n");
return 0;
out3:
class_destroy(cls);
out2:
unregister_chrdev(major,"si7006");
out1:
return ret;
}
int i2c_remove(struct i2c_client *client)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
//设备信息的注销
device_destroy(cls,MKDEV(major,0));
//设备节点的销毁
class_destroy(cls);
//驱动的注销
unregister_chrdev(major,"si7006");
return 0;
}
//定义设备树匹配的表
struct of_device_id oftable[]={
{.compatible="hqyj,si7006",},
{},
};
struct i2c_driver i2c_drv={
.probe=i2c_probe,
.remove=i2c_remove,
.driver={
.name="si7006",
.of_match_table=oftable,
},
};
module_i2c_driver(i2c_drv);
MODULE_LICENSE("GPL");
效果演示