linux-i2c驱动-ap3216c

1.应用程序

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>


int main(int argc, char**argv)
{
	int fd;
	char buf[6];
	int len;
	
	fd = open("/dev/Ap3216c", O_RDWR);
	if (fd == -1)
	{
		printf("can not open /dev/Ap3216c");
		return -1;
	}

	while(1)
	{
		len = read(fd,buf,6);
		printf("App read: ");
		for (len = 0; len < 6; len++)
		{
			printf("%02x ",buf[len]);
		}
		printf("\n");
		sleep(2);
	}
	close(fd);
	return 0;
}

2.i2c-driver程序

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/mod_devicetable.h>
#include <linux/bitops.h>
#include <linux/jiffies.h>
#include <linux/property.h>
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/nvmem-provider.h>
#include <linux/regmap.h>
#include <linux/pm_runtime.h>
#include <linux/gpio/consumer.h>
#include <linux/uaccess.h>
#include <linux/fs.h>



static int major = 0;
static struct i2c_client *Ap3216c_client;
static struct class *Ap3216c_class;


static int Ap3216c_open(struct inode *node, struct file *file)
{
	//printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	i2c_smbus_write_byte_data(Ap3216c_client, 0, 0x4);

	mdelay(250);
	i2c_smbus_write_byte_data(Ap3216c_client, 0, 0x3);
	mdelay(250);
	return 0;
}


static ssize_t Ap3216c_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
{
	int err;
	char kernel_buf[6];
	int val;
	//printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

	if (size != 6)
	{
		return -EINVAL;
	}

	val = i2c_smbus_read_word_data(Ap3216c_client, 0xA); /* read IR */
	kernel_buf[0] = val & 0xff;
	kernel_buf[1] = (val >> 8) & 0xff;

	val = i2c_smbus_read_word_data(Ap3216c_client, 0xC); /* read 光强 */
	kernel_buf[2] = val & 0xff;
	kernel_buf[3] = (val >> 8) & 0xff;

	val = i2c_smbus_read_word_data(Ap3216c_client, 0xE); /* read 距离 */
	kernel_buf[4] = val & 0xff;
	kernel_buf[5] = (val >> 8) & 0xff;

	err = copy_to_user(buf, kernel_buf, size);
	if (err < 0)
	{
		printk("copy_to_user err\n");
		return -1;
	}
	return size;	
}


static const struct of_device_id of_match_ids_Ap3216c[] ={
	{.compatible = "lite-on,Ap3216c", .data = NULL },
	{/* END OF LIST */}
};


static const struct file_operations Ap3216c_ops = {
	.owner = THIS_MODULE,
	.open = Ap3216c_open,
	.read = Ap3216c_read,
};


static int Ap3216c_probe(struct i2c_client * client, const struct i2c_device_id * id)
{
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	Ap3216c_client = client;

	/* 注册字符设备 */
	major = register_chrdev(major, "Ap3216c", &Ap3216c_ops);
	if (major < 0)
	{
		printk("register_chrdev err\n");
		return -1;
	}

	/* 注册类 */
	Ap3216c_class = class_create(THIS_MODULE, "Ap3216c_class");

	/* 注册设备 */
	device_create(Ap3216c_class, NULL, MKDEV(major,0), NULL, "Ap3216c");
	return 0;
}


static int Ap3216c_remove(struct i2c_client * client)
{
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	device_destroy(Ap3216c_class, MKDEV(major,0));
	class_destroy(Ap3216c_class);
	unregister_chrdev(major, "Ap3216c");
	return 0;
}


static const struct i2c_device_id Ap3216c_ids[] = {
	{"Ap3216c", (kernel_ulong_t)NULL },
	{/* END OF LIST */}
};


static struct i2c_driver i2c_Ap3216c_driver = {
	.driver = {
		.name = "Ap3216c",
		.of_match_table = of_match_ids_Ap3216c,
		},
	.probe = Ap3216c_probe,
	.remove = Ap3216c_remove,
	.id_table = Ap3216c_ids,
};


static int __init i2c_driver_Ap3216c_init(void)
{
	printk("%s %s line: %d\n", __FILE__, __FUNCTION__, __LINE__);
	return i2c_add_driver(&i2c_Ap3216c_driver);
}

static void __exit i2c_driver_Ap3216c_exit(void)
{
	i2c_del_driver(&i2c_Ap3216c_driver);
}


module_init(i2c_driver_Ap3216c_init);
module_exit(i2c_driver_Ap3216c_exit);
MODULE_LICENSE("GPL");







3.i2c-client程序

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/mod_devicetable.h>
#include <linux/bitops.h>
#include <linux/jiffies.h>
#include <linux/property.h>
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/nvmem-provider.h>
#include <linux/regmap.h>
#include <linux/pm_runtime.h>
#include <linux/gpio/consumer.h>
#include <linux/uaccess.h>
#include <linux/fs.h>


#if 1
static struct i2c_client *Ap3216c_client;
static int __init i2c_client_Ap3216c_init(void)
{
	struct i2c_adapter* adapter;
	struct i2c_board_info board_info = {
		I2C_BOARD_INFO("Ap3216c", 0x1e),
	};
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

	/* register I2C device */
	adapter = i2c_get_adapter(0);
	Ap3216c_client = i2c_new_device(adapter, &board_info);
	i2c_put_adapter(adapter);
	return 0;
}
#else
static i2c_client *Ap3216c_client;
/* Addresses to scan */
static const unsigned short normal_i2c[] = {
	0x1e, I2C_CLIENT_END
};

static int __init i2c_client_ap3216c_init(void)
{
	struct i2c_adapter *adapter;
	struct i2c_board_info board_info;
	memset(&board_info, 0, sizeof(struct i2c_board_info));
	strscpy(board_info.type, "Ap3216c", sizeof(board_info.type));
	
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	/* register I2C device */
	adapter = i2c_get_adapter(0);
	Ap3216c_client = i2c_new_probed_device(adapter, &board_info,
						   normal_i2c, NULL);
	i2c_put_adapter(adapter);
	return 0;
}

#endif

static void __init i2c_client_Ap3216c_exit(void)
{
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	i2c_unregister_device(Ap3216c_client);
}


module_init(i2c_client_Ap3216c_init);
module_exit(i2c_client_Ap3216c_exit);
MODULE_LICENSE("GPL");


4.Makefile

KERN_DIR = /home/book/100ask_imx6ull-sdk/Linux-4.9.88
all:
	make -C $(KERN_DIR) M=`pwd` modules
	$(CROSS_COMPILE)gcc -o ap3216c_drv_test ap3216c_drv_test.c 
clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order
	rm -rf ap3216c_drv_test

obj-m += ap3216c_drv.o
obj-m += ap3216c_client.o

5.测试结果
在这里插入图片描述

6.文件路径

/home/book/nfs_rootfs/优快云/02_I2C/ap3216c
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值