【Linux驱动开发】基于imx6ul平台的sht30驱动开发

Linux 的i2c系统

Linux 的i2c系统十分庞大,主要由3部分构成,i2c核心,i2c总线驱动,以及i2c设备驱动。

i2c核心

主要提供了i2c总线驱动和设备驱动的注册,注销方法,i2c通信方法(即Algorithm)上层的与具体适配器无关的代码及探测设备、检测设备地址的上层代码等。

i2c总线驱动

​ i2c总线驱动是对i2c硬件体系结构中适配器端的实现,适配器可由CPU控制,甚至可以直接集成在CPU内部。

​ 其主要包含i2c适配器数据结构i2c_adapter、i2c适配器的Algorithm数据结构i2c_algorithm和控制i2c适配器产生通信信号的函数。


在这里插入图片描述

​ 经由i2c总线驱动的代码,我们可以控制i2c适配器以主控方式产生开始位,停止位,等。

​ I2C 总线驱动,或者说 I2C 适配器驱动的主要工作就是初始化 i2c_adapter 结构体变量,然后设置 i2c_algorithm 中的 master_xfer 函数。完成以后通过 i2c_add_numbered_adapter或 i2c_add_adapter 这两个函数向系统注册设置好的 i2c_adapter。

​ 不过一般i2c总线驱动已经由半导体厂商编写好了。

i2c设备驱动

​ 设备一般挂接在受CPU控制的i2c适配器上,由I2c适配器和CPU交换数据。

​ i2c设备驱动主要包含数据结构i2c_driver和i2c_client,我们需要根据具体设备实现其中的成员函数。如

设备树修改

&i2c1 {
     clock-frequency = <100000>;
     pinctrl-names = "default";
     pinctrl-0 = <&pinctrl_i2c1>;
     status = "okay";

    sht30-i2c@44 {
         compatible = "wuhu,sht30";
         reg = <0x44>;
};

驱动编写

i2c_driver

static struct i2c_driver sht30_drv = {
	.probe = sht30_probe,
	.remove = sht30_remove,
	.driver = {
		.name = "hoshino-sht30", 
		.owner = THIS_MODULE,
		.of_match_table = of_sht30_match,
	},
	.id_table = sht30_id,
};

首先i2c_driver 结构体, 在probe 函数中完成分配设备号,注册字符设备,创建类设备等操作。

在remove函数中,注销销毁使用的资源。

接着实现注册cdev时使用到的file_operations

static struct file_operations sht30_fops = {
	.owner = THIS_MODULE,
	.open  = sht30_open,
	.read  = sht30_read,
	.release = sht30_release,
};
static int sht30_init(struct i2c_client *client)
{
	int rv = 0;
	uint16_t data = SOFTRESET;
	unsigned char cmd[2];
	cmd[0] = data >> 8;
	cmd[1] = data;
	
	rv = i2c_master_send(client,cmd,2);
	if(rv<0)
	{
		dev_err(&client->dev,"Send i2c SOFTRESET cmd failure.\n");
		return rv;
	}

	msleep(50);
	return 0;
}

static int sht30_open(struct inode* inode , struct file* filp )
{
	struct sht30_priv * priv = container_of(inode->i_cdev,struct sht30_priv,cdev);
	int rv = 0;

	//Init sht30.
	rv = sht30_init(priv->client);
	if(rv < 0)
	{
		dev_err(priv->dev, "sht30 init failure.\n");
		return rv;
	}

	filp->private_data = priv;
	return 0;

}

static int read_data(struct i2c_client* client ,uint8_t * buf,size_t cnt)
{
	int rv =0;
	uint16_t data = MEAS_NOSTRETCH_MEDREP;
	unsigned char cmd[2];
	cmd[0] = data >> 8;
	cmd[1] = data;

	rv = i2c_master_send(client,cmd,2);
	if(rv < 0)
	{
		dev_err(&client->dev,"sht30 send read cmd failure.\n");
		return -EFAULT;
	}

	msleep(85);

	rv = i2c_master_recv(client,buf, cnt);
	if(rv<6)
	{
		dev_err(&client->dev,"Read data failure.\n");
		return -EFAULT;
	}
	return 0;
}
static ssize_t sht30_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off)
{
	
	struct	sht30_priv * priv = filp->private_data;
	int rv = 0 ;
	uint8_t bufz[6];
	uint8_t data[4];

	if(!priv->client)
	{
		dev_err(priv->dev,"Can't get i2c client.\n");
		return -EFAULT;
	}
	
	rv = read_data(priv->client,bufz,sizeof(bufz));
	if(rv < 0 )
	{
		return -EFAULT;
	}

	data[0] = bufz[1];
	data[1] = bufz[0];
	data[2] = bufz[4];
	data[3] = bufz[3];

	rv = copy_to_user(buf, data, sizeof(data));
	if(rv)
	{
		dev_err(priv->dev, "copy to user error.\n");
		return -EFAULT;
	}

	printk("%s\n",data);

	return sizeof(data);
}

static int sht30_release(struct inode *inode, struct file *filp)
{
	    return 0;
}

注册i2c驱动

module_i2c_driver(sht30_drv);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值