栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

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

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【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("%sn",data);

	return sizeof(data);
}

static int sht30_release(struct inode *inode, struct file *filp)
{
	    return 0;
}
注册i2c驱动

module_i2c_driver(sht30_drv);

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/941867.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号