驱动开发 使用ioctl读取iic总线si7006温湿度

 

 

#include <linux/init.h>
#include <linux/module.h>
#include<linux/i2c.h>
#include<linux/fs.h>
#include<linux/uaccess.h>
#include<linux/device.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include"si7006.h"
#define CNAME "myled"

int major;
struct class *cls;
struct device *dev;
struct i2c_client *tclient;
struct device_node *node;
struct gpio_desc *gpiono;
//获取温湿度数据的函数

int i2c_read_hum_tem(unsigned char reg)
{
	int ret;
	//读消息的封装
	char r_buf[]={reg};
	unsigned short val;//读的数据
	struct i2c_msg r_msg[]={
		[0]={
			.addr=tclient->addr,
			.flags=0,
			.len=1,
			.buf=r_buf,
		},
		[1]={
			.addr=tclient->addr,
			.flags=1,
			.len=2,
			.buf=(char *)&val,
		},
	};
	//消息的传输
	ret=i2c_transfer(tclient->adapter,r_msg,ARRAY_SIZE(r_msg));
	if(ret!=ARRAY_SIZE(r_msg))
	{
		printk("获取温湿度失败\n");
		return  EAGAIN;
	}
	return val;
}

//匹配后执行probe
int  si7006_open(struct inode *inode,struct file *file)
{
	printk("open\n");
	return 0;
}

ssize_t si7006_read(struct file *file,char *ubuf,size_t size,loff_t *off)
{
	printk("read\n");
	return 0;
}

ssize_t si7006_write(struct file *file,const char *ubuf,size_t size,loff_t *off)
{
	printk("write\n");
	return 0;
}

long si7006_ioctl(struct file *file,unsigned int cmd,unsigned long arg)
{
	int tem,hum;
	int ret;
	switch(cmd)
	{
		case GET_HUM:
			hum=i2c_read_hum_tem(0xe5);
			ret=copy_to_user((void *)arg,(void *)&hum,sizeof(int));
			if(ret)
			{
				printk("copy_to_user error\n");
				return EINVAL;
			}
			break;
		case GET_TEM:
			tem=i2c_read_hum_tem(0xe3);
			ret=copy_to_user((void *)arg,(void *)&tem,sizeof(int));
			if(ret)
			{
				printk("copy_to_user error\n");
				return EINVAL;
			}
			break;
		case LED1_ON:
			gpiod_set_value(gpiono,1);
			break;
		case LED1_OFF:
			gpiod_set_value(gpiono,0);
			break;
	}
	return 0;
}

int si7006_close(struct inode *inode,struct file *file)
{
	printk("close\n");
	return 0;
}

struct file_operations fops={
	.open=si7006_open,
	.read=si7006_read,
	.write=si7006_write,
	.unlocked_ioctl=si7006_ioctl,
	.release=si7006_close,
};

int si7006_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
	tclient=client;
	major=register_chrdev(0,"si7006",&fops);
	if(major<0)
	{
		printk("字符设备驱动注册失败\n");
		return major;
	}
	printk("字符设备驱动注册成功\n");
	//自动创建设备结点
	cls=class_create(THIS_MODULE,"si7006");
	if(IS_ERR(cls))
	{
		printk("向上提交目录失败\n");
		return PTR_ERR(cls);
	}
	printk("向上提交目录成功\n");
	dev=device_create(cls,NULL,MKDEV(major,0),NULL,"si7006");
	if(IS_ERR(dev))
	{
		printk("向上提交设备信息失败\n");
		return PTR_ERR(dev);
	}
	printk("向上提交设备信息成功\n");
	node=of_find_node_by_name(NULL,"myleds");
	if(node==NULL)
	{
		printk("解析设备树失败\n");
		return -EFAULT;
	}
	printk("成功解析到设备树结点\n");
	//获取GPIO编号
	gpiono=gpiod_get_from_of_node(node,"myled1",0,GPIOD_OUT_LOW,NULL);
	if(IS_ERR(gpiono))
	{
		printk("获取gpio编号失败\n");
		return PTR_ERR(gpiono);
	}
	printk("获取gpio编号成功\n");

	return 0;
}


int si7006_remove(struct i2c_client *client)
{
    printk("%s:%d\n",__func__,__LINE__);
	gpiod_set_value(gpiono,0);
	gpiod_put(gpiono);
	device_destroy(cls,MKDEV(major,0));
	class_destroy(cls);
	unregister_chrdev(major,"si7006");
    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="tem_hum_driver",
		.of_match_table=oftable,
	},
};

module_i2c_driver(si7006);
MODULE_LICENSE("GPL");
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include<stdlib.h>
#include <arpa/inet.h>
#include "si7006.h"

int main(int argc, char const *argv[])
{
    int hum,tem;
    float hum1,tem1;
    int ret;
    int fd=open("/dev/si7006",O_RDWR);
    if(fd<0)
    {
        printf("打开设备文件失败\n");
        exit(-1);
    }
    while(1)
    {
        ioctl(fd,GET_TEM,&tem);
        ioctl(fd,GET_HUM,&hum);
        //字节序的转换
        hum=ntohs(hum);
        tem=ntohs(tem);
        //温湿度数据计算
        hum1=125.0*hum/65536-6;
        tem1=175.72*tem/65536-46.85;
		if(tem1>22)
		{
			ioctl(fd,LED1_ON);
		}
		else
		{
			ioctl(fd,LED1_OFF);
		}
        printf("tem:%f  hum:%f\n",tem1,hum1);
        sleep(1);
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值