国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Linux驅(qū)動(dòng)開(kāi)發(fā)12 IIC驅(qū)動(dòng)

這篇具有很好參考價(jià)值的文章主要介紹了Linux驅(qū)動(dòng)開(kāi)發(fā)12 IIC驅(qū)動(dòng)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

IIC總線驅(qū)動(dòng)+IIC設(shè)備驅(qū)動(dòng)(驅(qū)動(dòng)分割分離分層思想)? ? ?

我們不需要寫適配器,只需要寫設(shè)備驅(qū)動(dòng)??

????????I2C 是很常用的一個(gè)串行通信接口,用于連接各種外設(shè)、傳感器等器件,在裸機(jī)篇已經(jīng)對(duì)
I.MX6U I2C 接口做了詳細(xì)的講解。本章我們來(lái)學(xué)習(xí)一下如何在 Linux 下開(kāi)發(fā) I2C 接口器件驅(qū)動(dòng),重點(diǎn)是學(xué)習(xí) Linux 下的 I2C 驅(qū)動(dòng)框架,按照指定的框架去編寫 I2C 設(shè)備驅(qū)動(dòng)。
Linux驅(qū)動(dòng)開(kāi)發(fā)12 IIC驅(qū)動(dòng)

????????I2C 總線驅(qū)動(dòng)重點(diǎn)是 I2C 適配器(也就是 SOC I2C 接口控制器)驅(qū)動(dòng),這里要用到 兩個(gè)重要的數(shù)據(jù)結(jié)構(gòu):i2c_adapter i2c_algorithm,Linux 內(nèi)核將 SOC I2C 適配器(控制器) 抽象成i2c_adapter,i2c_adapter 結(jié)構(gòu)體定義在 include/linux/i2c.h 文件中。

????????Linux驅(qū)動(dòng)開(kāi)發(fā)12 IIC驅(qū)動(dòng)

?=========================================================================

I2C 設(shè)備驅(qū)動(dòng)重點(diǎn)關(guān)注兩個(gè)數(shù)據(jù)結(jié)構(gòu): i2c_client 和 i2c_driver ,根據(jù)總線、設(shè)備和驅(qū)動(dòng)模型,
I2C 總線上一小節(jié)已經(jīng)講了。還剩下設(shè)備和驅(qū)動(dòng), i2c_client 就是描述設(shè)備信息的, i2c_driver 描述驅(qū)動(dòng)內(nèi)容,類似于 platform_driver 。
Linux驅(qū)動(dòng)開(kāi)發(fā)12 IIC驅(qū)動(dòng)

Linux驅(qū)動(dòng)開(kāi)發(fā)12 IIC驅(qū)動(dòng)

1、對(duì)于我們 I2C 設(shè)備驅(qū)動(dòng)編寫人來(lái)說(shuō),重點(diǎn)工作就是構(gòu)建 i2c_driver,構(gòu)建完成以后需要向 Linux 內(nèi)核注冊(cè)這個(gè) i2c_driver。i2c_driver 注冊(cè)函數(shù)為 int i2c_register_driver

另外 i2c_add_driver 也常常用于注冊(cè) i2c_driver , i2c_add_driver 是一個(gè)宏,定義如下:
示例代碼 61.1.2.3 i2c_add_driver 宏
587 #define i2c_add_driver ( driver ) \
588 i2c_register_driver ( THIS_MODULE , driver )
i2c_add_driver 就是對(duì) i2c_register_driver 做了一個(gè)簡(jiǎn)單的封裝,只有一個(gè)參數(shù),就是要注冊(cè)
i2c_driver
2、注銷 I2C 設(shè)備驅(qū)動(dòng)的時(shí)候需要將前面注冊(cè)的 i2c_driver 從 Linux 內(nèi)核中注銷掉,需要用到i2c_del_driver 函數(shù),此函數(shù)原型如下:
void i2c_del_driver(struct i2c_driver *driver)
函數(shù)參數(shù)和返回值含義如下:
driver :要注銷的 i2c_driver
返回值: 無(wú)
=========================================================================
Linux驅(qū)動(dòng)開(kāi)發(fā)12 IIC驅(qū)動(dòng)
在IIC1 上 接了 AP3216C
修改設(shè)備樹(shù),我們不能在imx6ull.dtsi中修改,只能在imx6ull-alientek-emmc.dts中修改,
從下列代碼中可以看出i2c1下添加了ap3216。i2c2下添加了codec等一系列設(shè)備
Linux驅(qū)動(dòng)開(kāi)發(fā)12 IIC驅(qū)動(dòng)

?

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

	ap3216c@1e {
		compatible = "alientek,ap3216c";
		reg = <0x1e>;
	};
};

&i2c2 {
	clock_frequency = <100000>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_i2c2>;
	status = "okay";

	codec: wm8960@1a {
		compatible = "wlf,wm8960";
		reg = <0x1a>;
		clocks = <&clks IMX6UL_CLK_SAI2>;
		clock-names = "mclk";
		wlf,shared-lrclk;
	};

	ov5640: ov5640@3c {
		compatible = "ovti,ov5640";
		reg = <0x3c>;
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_csi1>;
		clocks = <&clks IMX6UL_CLK_CSI>;
		clock-names = "csi_mclk";
		pwn-gpios = <&gpio_spi 6 1>;
		rst-gpios = <&gpio_spi 5 0>;
		csi_id = <0>;
		mclk = <24000000>;
		mclk_source = <0>;
		status = "disabled";
		port {
			ov5640_ep: endpoint {
				remote-endpoint = <&csi1_ep>;
			};
		};
	};

	/* zuozhongkai FT5406/FT5426 */
	ft5426: ft5426@38 {
		compatible = "edt,edt-ft5426","edt,edt-ft5406";
		reg = <0x38>;
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_tsc
					&pinctrl_tsc_reset >; 
		interrupt-parent = <&gpio1>; 
		interrupts = <9 0>; 
		reset-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;  
		interrupt-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; 
		status = "okay";
	};

	gt9147:gt9147@14 {
		compatible = "goodix,gt9147", "goodix,gt9xx";
		reg = <0x14>;
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_tsc
					&pinctrl_tsc_reset >; 
		interrupt-parent = <&gpio1>; 
		interrupts = <9 0>; 
		reset-gpios  = <&gpio5 9 GPIO_ACTIVE_LOW>;
		interrupt-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; 
		status = "disable";  /* 如果需要改為okay */
	};

	/* zuozhongkai sill902x,如果需要HDMI就將status改為okay即可  */
	/*
	sii902x: sii902x@39 {
        compatible = "SiI,sii902x";
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_sii902x>;
        interrupt-parent = <&gpio1>;
        interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
		irq-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
        mode_str = "1280x720M@60";
        bits-per-pixel = <16>;
        resets = <&sii902x_reset>;
        reg = <0x39>;
        status = "disable"; 
    };*/
};

Linux驅(qū)動(dòng)開(kāi)發(fā)12 IIC驅(qū)動(dòng)

Linux驅(qū)動(dòng)開(kāi)發(fā)12 IIC驅(qū)動(dòng)?Linux驅(qū)動(dòng)開(kāi)發(fā)12 IIC驅(qū)動(dòng)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-457079.html

查問(wèn)題,?;厮荩梢钥吹竭M(jìn)入了ap3216c_open,然后在i2c_transfer中出問(wèn)題了

#ifndef AP3216C_H

#define AP3216C_H

/***************************************************************

Copyright ? ALIENTEK Co., Ltd. 1998-2029. All rights reserved.

文件名		: ap3216creg.h

作者	  	: 左忠凱

版本	   	: V1.0

描述	   	: AP3216C寄存器地址描述頭文件

其他	   	: 無(wú)

論壇 	   	: www.openedv.com

日志	   	: 初版V1.0 2019/9/2 左忠凱創(chuàng)建

***************************************************************/



// 這個(gè)頭文件用來(lái)存放ap3216c的寄存器信息

#define AP3216C_ADDR    	0X1E	/* AP3216C器件地址  */



/* AP3316C寄存器 */

#define AP3216C_SYSTEMCONG	0x00	/* 配置寄存器       */

#define AP3216C_INTSTATUS	0X01	/* 中斷狀態(tài)寄存器   */

#define AP3216C_INTCLEAR	0X02	/* 中斷清除寄存器   */

#define AP3216C_IRDATALOW	0x0A	/* IR數(shù)據(jù)低字節(jié)     */

#define AP3216C_IRDATAHIGH	0x0B	/* IR數(shù)據(jù)高字節(jié)     */

#define AP3216C_ALSDATALOW	0x0C	/* ALS數(shù)據(jù)低字節(jié)    */

#define AP3216C_ALSDATAHIGH	0X0D	/* ALS數(shù)據(jù)高字節(jié)    */

#define AP3216C_PSDATALOW	0X0E	/* PS數(shù)據(jù)低字節(jié)     */

#define AP3216C_PSDATAHIGH	0X0F	/* PS數(shù)據(jù)高字節(jié)     */



#endif



#include <linux/types.h>

#include <linux/kernel.h>

#include <linux/delay.h>

#include <linux/ide.h>

#include <linux/init.h>

#include <linux/module.h>

#include <linux/errno.h>

#include <linux/gpio.h>

#include <linux/cdev.h>

#include <linux/device.h>

#include <linux/of_gpio.h>

#include <linux/semaphore.h>

#include <linux/timer.h>

#include <linux/i2c.h>

#include <asm/mach/map.h>

#include <asm/uaccess.h>

#include <asm/io.h>

#include "ap3216creg.h"

/***************************************************************

Copyright ? ALIENTEK Co., Ltd. 1998-2029. All rights reserved.

文件名		: ap3216c.c

作者	  	: 左忠凱

版本	   	: V1.0

描述	   	: AP3216C驅(qū)動(dòng)程序

其他	   	: 無(wú)

論壇 	   	: www.openedv.com

日志	   	: 初版V1.0 2019/9/2 左忠凱創(chuàng)建

***************************************************************/

#define AP3216C_CNT	1

#define AP3216C_NAME	"ap3216c"



struct ap3216c_dev {

	dev_t devid;			/* 設(shè)備號(hào) 	 */

	struct cdev cdev;		/* cdev 	*/

	struct class *class;	/* 類 		*/

	struct device *device;	/* 設(shè)備 	 */

	struct device_node	*nd; /* 設(shè)備節(jié)點(diǎn) */

	int major;			/* 主設(shè)備號(hào) */

	void *private_data;	/* 私有數(shù)據(jù) */

	unsigned short ir, als, ps;		/* 三個(gè)光傳感器數(shù)據(jù) 注意這里數(shù)據(jù)類型short*/

};



static struct ap3216c_dev ap3216cdev;



/*

 * @description	: 從ap3216c讀取多個(gè)寄存器數(shù)據(jù)

 * @param - dev:  ap3216c設(shè)備

 * @param - reg:  要讀取的寄存器首地址

 * @param - val:  讀取到的數(shù)據(jù)

 * @param - len:  要讀取的數(shù)據(jù)長(zhǎng)度

 * @return 		: 操作結(jié)果

 * 

 * 讀取AP3216C的N個(gè)寄存器值

 */

//讀 read 寫 write函數(shù)是IIC的難點(diǎn)和重點(diǎn)//

static int ap3216c_read_regs(struct ap3216c_dev *dev, u8 reg, void *val, int len)

{

	int ret;

	struct i2c_msg msg[2];

	// 從私有變量中獲取一系列數(shù)據(jù)

	struct i2c_client *client = (struct i2c_client *)dev->private_data;



	/* msg[0]為發(fā)送要讀取的首地址 */

	msg[0].addr = client->addr;			/* 從機(jī)地址 也就是ap3216c地址 */

	msg[0].flags = 0;								/* 標(biāo)記為要發(fā)送的數(shù)據(jù) */

	msg[0].buf = &reg;							/* 要發(fā)送的數(shù)據(jù)馬也就是寄存器地址 */

	msg[0].len = 1;									/* 要發(fā)送的寄存器地址長(zhǎng)度為1*/



	/* msg[1]讀取數(shù)據(jù) */

	msg[1].addr = client->addr;			/* 從機(jī)地址 也就是ap3216c地址 */

	msg[1].flags = I2C_M_RD;				/* 標(biāo)記為讀數(shù)據(jù)*/

	msg[1].buf = val;								/* 讀取數(shù)據(jù)緩沖區(qū),接收到的從機(jī)發(fā)送的數(shù)據(jù) */

	msg[1].len = len;								/* 要讀取的寄存器長(zhǎng)度*/



  // i2c_transfer 即能向寄存器里面寫數(shù)據(jù),也能向寄存器里面讀 

	//  從哪讀要告訴他

	ret = i2c_transfer(client->adapter, msg, 2);

	if(ret == 2) {

		ret = 0;

	} else {

		printk("i2c rd failed=%d reg=%06x len=%d\n",ret, reg, len);

		ret = -EREMOTEIO;

	}

	return ret;

}



/*

 * @description	: 向ap3216c多個(gè)寄存器寫入數(shù)據(jù)

 * @param - dev:  ap3216c設(shè)備

 * @param - reg:  要寫入的寄存器首地址

 * @param - val:  要寫入的數(shù)據(jù)緩沖區(qū)

 * @param - len:  要寫入的數(shù)據(jù)長(zhǎng)度

 * @return 	  :   操作結(jié)果

 * 

 * 向AP3216C寫N個(gè)寄存器的數(shù)據(jù)

 */

static s32 ap3216c_write_regs(struct ap3216c_dev *dev, u8 reg, u8 *buf, u8 len)

{

	u8 b[256];

	struct i2c_msg msg;

	struct i2c_client *client = (struct i2c_client *)dev->private_data;

	

	b[0] = reg;					/* 寄存器首地址 */

	memcpy(&b[1],buf,len);		/* 將要寫入的數(shù)據(jù) 拷貝 到數(shù)組b里面 */

		

	msg.addr = client->addr;	/* 從機(jī)地址 也就是ap3216c地址 */

	msg.flags = 0;				/* 表示為要發(fā)送的數(shù)據(jù) */

	msg.buf = b;				/* 要發(fā)送的數(shù)據(jù),寄存器地址 + 實(shí)際數(shù)據(jù) */

	msg.len = len + 1;			/* 要寫入的數(shù)據(jù)長(zhǎng)度 寄存器地址長(zhǎng)度 + 實(shí)際的數(shù)據(jù)長(zhǎng)度*/



	return i2c_transfer(client->adapter, &msg, 1);

}



/*

 * @description	: 讀取ap3216c指定寄存器值,讀取一個(gè)寄存器

 * @param - dev:  ap3216c設(shè)備

 * @param - reg:  要讀取的寄存器

 * @return 	  :   讀取到的寄存器值

 * 

 * 讀取AP3216C的 1 個(gè)寄存器值

 */

static unsigned char ap3216c_read_reg(struct ap3216c_dev *dev, u8 reg)

{

	u8 data = 0;



	// 直接調(diào)用寫的函數(shù),長(zhǎng)度為 1

	ap3216c_read_regs(dev, reg, &data, 1);

	return data;



#if 0

	struct i2c_client *client = (struct i2c_client *)dev->private_data;

	return i2c_smbus_read_byte_data(client, reg);

#endif

}



/*

 * @description	: 向ap3216c指定寄存器寫入指定的值,寫一個(gè)寄存器

 * @param - dev:  ap3216c設(shè)備

 * @param - reg:  要寫的寄存器

 * @param - data: 要寫入的值

 * @return   :    無(wú)

 */

static void ap3216c_write_reg(struct ap3216c_dev *dev, u8 reg, u8 data)

{

	u8 buf = 0;

	buf = data;

	ap3216c_write_regs(dev, reg, &buf, 1);

}



/*

 * @description	: 讀取AP3216C的數(shù)據(jù),讀取原始數(shù)據(jù),包括ALS,PS和IR, 注意!

 *				: 如果同時(shí)打開(kāi)ALS,IR+PS的話兩次數(shù)據(jù)讀取的時(shí)間間隔要大于112.5ms

 * @param - ir	: ir數(shù)據(jù)

 * @param - ps 	: ps數(shù)據(jù)

 * @param - ps 	: als數(shù)據(jù) 

 * @return 		: 無(wú)。

 */

void ap3216c_readdata(struct ap3216c_dev *dev)

{

	unsigned char i =0;

    unsigned char buf[6];

	

	/* 循環(huán)讀取所有傳感器數(shù)據(jù) */

    for(i = 0; i < 6; i++)	

    {

        buf[i] = ap3216c_read_reg(dev, AP3216C_IRDATALOW + i);	

    }



    if(buf[0] & 0X80) 	/* IR_OF位為1,則數(shù)據(jù)無(wú)效 */

		dev->ir = 0;

		//從buf[0] 數(shù)組里面取 位 

	else 				/* 讀取IR傳感器的數(shù)據(jù)   		*/

		dev->ir = ((unsigned short)buf[1] << 2) | (buf[0] & 0X03); 			

	

		dev->als = ((unsigned short)buf[3] << 8) | buf[2];	/* 讀取ALS傳感器的數(shù)據(jù) 			 */  

	

    if(buf[4] & 0x40)	/* IR_OF位為1,則數(shù)據(jù)無(wú)效 			*/

		dev->ps = 0;    													

	else 				/* 讀取PS傳感器的數(shù)據(jù)    */

		dev->ps = ((unsigned short)(buf[5] & 0X3F) << 4) | (buf[4] & 0X0F); 

}



//

///之下是IIC驅(qū)動(dòng)框架搭建,之上時(shí)AP3216C寄存器數(shù)據(jù)讀寫函數(shù)編寫/

//

/*

 * @description		: 打開(kāi)設(shè)備

 * @param - inode 	: 傳遞給驅(qū)動(dòng)的inode

 * @param - filp 	: 設(shè)備文件,file結(jié)構(gòu)體有個(gè)叫做private_data的成員變量

 * 					  一般在open的時(shí)候?qū)rivate_data指向設(shè)備結(jié)構(gòu)體。

 * @return 			: 0 成功;其他 失敗

 */

static int ap3216c_open(struct inode *inode, struct file *filp)

{

	filp->private_data = &ap3216cdev;



	/* 初始化AP3216C */

	ap3216c_write_reg(&ap3216cdev, AP3216C_SYSTEMCONG, 0x04);		/* 復(fù)位AP3216C 			*/

	mdelay(50);														/* AP3216C復(fù)位最少10ms 	*/

	ap3216c_write_reg(&ap3216cdev, AP3216C_SYSTEMCONG, 0X03);		/* 開(kāi)啟ALS、PS+IR 		*/

	return 0;

}



/*

 * @description		: 從設(shè)備讀取數(shù)據(jù) 

 * @param - filp 	: 要打開(kāi)的設(shè)備文件(文件描述符)

 * @param - buf 	: 返回給用戶空間的數(shù)據(jù)緩沖區(qū)

 * @param - cnt 	: 要讀取的數(shù)據(jù)長(zhǎng)度

 * @param - offt 	: 相對(duì)于文件首地址的偏移

 * @return 			: 讀取的字節(jié)數(shù),如果為負(fù)值,表示讀取失敗

 */

static ssize_t ap3216c_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off)

{

	short data[3];

	long err = 0;



	struct ap3216c_dev *dev = (struct ap3216c_dev *)filp->private_data;

	/* 向應(yīng)用返回AP3216C的原始數(shù)據(jù)  往里填數(shù)據(jù)*/

	ap3216c_readdata(dev);



	data[0] = dev->ir;

	data[1] = dev->als;

	data[2] = dev->ps;

	err = copy_to_user(buf, data, sizeof(data));

	return 0;

}



/*

 * @description		: 關(guān)閉/釋放設(shè)備

 * @param - filp 	: 要關(guān)閉的設(shè)備文件(文件描述符)

 * @return 			: 0 成功;其他 失敗

 */

static int ap3216c_release(struct inode *inode, struct file *filp)

{

	return 0;

}



/* AP3216C操作函數(shù) */

static const struct file_operations ap3216c_ops = {

	.owner = THIS_MODULE,

	.open = ap3216c_open,

	.read = ap3216c_read,

	.release = ap3216c_release,

};



 /*

  * @description     : i2c驅(qū)動(dòng)的probe函數(shù),當(dāng)驅(qū)動(dòng)與

  *                    設(shè)備匹配以后此函數(shù)就會(huì)執(zhí)行

  * @param - client  : i2c設(shè)備

  * @param - id      : i2c設(shè)備ID

  * @return          : 0,成功;其他負(fù)值,失敗

	*  

								probe函數(shù)

  */

static int ap3216c_probe(struct i2c_client *client, const struct i2c_device_id *id)

{

	/* 搭建一套完整的字符設(shè)備驅(qū)動(dòng)  */

	/* 1、構(gòu)建設(shè)備號(hào) */

	if (ap3216cdev.major) {

		ap3216cdev.devid = MKDEV(ap3216cdev.major, 0);

		register_chrdev_region(ap3216cdev.devid, AP3216C_CNT, AP3216C_NAME);

	} else {

		alloc_chrdev_region(&ap3216cdev.devid, 0, AP3216C_CNT, AP3216C_NAME);

		ap3216cdev.major = MAJOR(ap3216cdev.devid);

	}



	/* 2、注冊(cè)設(shè)備 */

	cdev_init(&ap3216cdev.cdev, &ap3216c_ops);

	cdev_add(&ap3216cdev.cdev, ap3216cdev.devid, AP3216C_CNT);



	/* 3、創(chuàng)建類 */

	ap3216cdev.class = class_create(THIS_MODULE, AP3216C_NAME);

	if (IS_ERR(ap3216cdev.class)) {

		return PTR_ERR(ap3216cdev.class);

	}



	/* 4、創(chuàng)建設(shè)備 */

	ap3216cdev.device = device_create(ap3216cdev.class, NULL, ap3216cdev.devid, NULL, AP3216C_NAME);

	if (IS_ERR(ap3216cdev.device)) {

		return PTR_ERR(ap3216cdev.device);

	}



	// 讓私有數(shù)據(jù)ap3216cdev 獲得client

	ap3216cdev.private_data = client;



	return 0;

}



/*

 * @description     : i2c驅(qū)動(dòng)的remove函數(shù),移除i2c驅(qū)動(dòng)的時(shí)候此函數(shù)會(huì)執(zhí)行

 * @param - client 	: i2c設(shè)備

 * @return          : 0,成功;其他負(fù)值,失敗

 */

static int ap3216c_remove(struct i2c_client *client)

{

	/* 刪除設(shè)備 */

	cdev_del(&ap3216cdev.cdev);

	unregister_chrdev_region(ap3216cdev.devid, AP3216C_CNT);



	/* 注銷掉類和設(shè)備 */

	device_destroy(ap3216cdev.class, ap3216cdev.devid);

	class_destroy(ap3216cdev.class);

	return 0;

}





/* 兩種匹配表 probe函數(shù)調(diào)用時(shí)候判斷兩個(gè)都成立才行,后面的不為空就行 */

/* 傳統(tǒng)匹配方式ID列表 */

static const struct i2c_device_id ap3216c_id[] = {

	{"alientek,ap3216c", 0},  

	{}

};



/* 設(shè)備樹(shù)匹配列表 */

static const struct of_device_id ap3216c_of_match[] = {

	{ .compatible = "alientek,ap3216c" },

	{ /* Sentinel */ }

};



/* i2c驅(qū)動(dòng)結(jié)構(gòu)體

		定義一個(gè)probe函數(shù),一個(gè)remove函數(shù)

 */	

/********************I2C驅(qū)動(dòng)的重中之重*************************/

static struct i2c_driver ap3216c_driver = {

	.probe = ap3216c_probe,

	.remove = ap3216c_remove,

	.driver = {

			.owner = THIS_MODULE,

		   	.name = "ap3216c",

		   	.of_match_table = ap3216c_of_match, 

		   },

	.id_table = ap3216c_id,

};

		   

/*

 * @description	: 驅(qū)動(dòng)入口函數(shù)

 * @param 		: 無(wú)

 * @return 		: 無(wú)

 */

static int __init ap3216c_init(void)

{

	int ret = 0;



	//注冊(cè)i2c_driver

	ret = i2c_add_driver(&ap3216c_driver);

	return ret;

}



/*

 * @description	: 驅(qū)動(dòng)出口函數(shù)

 * @param 		: 無(wú)

 * @return 		: 無(wú)

 */

static void __exit ap3216c_exit(void)

{

	//注銷i2c_driver

	i2c_del_driver(&ap3216c_driver);

}



/* module_i2c_driver(ap3216c_driver) */



module_init(ap3216c_init);

module_exit(ap3216c_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("zuozhongkai");







#include "stdio.h"

#include "unistd.h"

#include "sys/types.h"

#include "sys/stat.h"

#include "sys/ioctl.h"

#include "fcntl.h"

#include "stdlib.h"

#include "string.h"

#include <poll.h>

#include <sys/select.h>

#include <sys/time.h>

#include <signal.h>

#include <fcntl.h>

/***************************************************************

Copyright ? ALIENTEK Co., Ltd. 1998-2029. All rights reserved.

文件名		: ap3216cApp.c

作者	  	: 左忠凱

版本	   	: V1.0

描述	   	: ap3216c設(shè)備測(cè)試APP。

其他	   	: 無(wú)

使用方法	 :./ap3216cApp /dev/ap3216c

論壇 	   	: www.openedv.com

日志	   	: 初版V1.0 2019/9/20 左忠凱創(chuàng)建

***************************************************************/



/*

 * @description		: main主程序

 * @param - argc 	: argv數(shù)組元素個(gè)數(shù)

 * @param - argv 	: 具體參數(shù)

 * @return 			: 0 成功;其他 失敗

 */

int main(int argc, char *argv[])

{

	int fd;

	char *filename;

	unsigned short databuf[3];

	unsigned short ir, als, ps;

	int ret = 0;



	if (argc != 2) {

		printf("Error Usage!\r\n");

		return -1;

	}



	filename = argv[1];

	fd = open(filename, O_RDWR);

	if(fd < 0) {

		printf("can't open file %s\r\n", filename);

		return -1;

	}



	

	// 老規(guī)矩,這上面的部分都是模板,下面才是這個(gè)app真正寫的

	// 循環(huán)讀取

	while (1) {

		// 讀取數(shù)據(jù)

		ret = read(fd, databuf, sizeof(databuf));

		// 判斷數(shù)據(jù) 光強(qiáng)度(ALS)、接近距離(PS)和紅外線強(qiáng)度(IR)

		if(ret == 0) { 			/* 數(shù)據(jù)讀取成功 */

			ir =  databuf[0]; 	/* ir傳感器數(shù)據(jù) */

			als = databuf[1]; 	/* als傳感器數(shù)據(jù) */

			ps =  databuf[2]; 	/* ps傳感器數(shù)據(jù) */

			printf("ir = %d, als = %d, ps = %d\r\n", ir, als, ps);

		}

		usleep(200000); /*100ms */

	}

	close(fd);	/* 關(guān)閉文件 */	

	return 0;

}



到了這里,關(guān)于Linux驅(qū)動(dòng)開(kāi)發(fā)12 IIC驅(qū)動(dòng)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 4、Linux驅(qū)動(dòng)開(kāi)發(fā):設(shè)備-設(shè)備號(hào)&設(shè)備號(hào)注冊(cè)

    4、Linux驅(qū)動(dòng)開(kāi)發(fā):設(shè)備-設(shè)備號(hào)&設(shè)備號(hào)注冊(cè)

    ??點(diǎn)擊這里查看所有博文 ??隨著自己工作的進(jìn)行,接觸到的技術(shù)棧也越來(lái)越多。給我一個(gè)很直觀的感受就是,某一項(xiàng)技術(shù)/經(jīng)驗(yàn)在剛開(kāi)始接觸的時(shí)候都記得很清楚。往往過(guò)了幾個(gè)月都會(huì)忘記的差不多了,只有經(jīng)常會(huì)用到的東西才有可能真正記下來(lái)。存在很多在特殊情況下有

    2024年02月15日
    瀏覽(44)
  • Linux驅(qū)動(dòng)開(kāi)發(fā)實(shí)戰(zhàn)(一)——設(shè)備驅(qū)動(dòng)模型

    Linux驅(qū)動(dòng)開(kāi)發(fā)實(shí)戰(zhàn)(一)——設(shè)備驅(qū)動(dòng)模型

    在早期的Linux內(nèi)核中并沒(méi)有為設(shè)備驅(qū)動(dòng)提供統(tǒng)一的設(shè)備模型。隨著內(nèi)核的不斷擴(kuò)大及系統(tǒng)更加復(fù)雜,編寫一個(gè)驅(qū)動(dòng)程序越來(lái)越困難,所以在Linux2.6內(nèi)核中添加了一個(gè)統(tǒng)一的設(shè)備模型。這樣,寫設(shè)備驅(qū)動(dòng)程序就稍微容易一些了。本章將對(duì)設(shè)備模型進(jìn)行詳細(xì)的介紹。 設(shè)備驅(qū)動(dòng)模型

    2024年02月16日
    瀏覽(26)
  • Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā) - 虛擬時(shí)鐘Clock驅(qū)動(dòng)示例

    Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā) - 虛擬時(shí)鐘Clock驅(qū)動(dòng)示例

    By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜歡的盆友歡迎點(diǎn)贊和訂閱! 你的喜歡就是我寫作的動(dòng)力! 很多設(shè)備里面系統(tǒng)時(shí)鐘架構(gòu)極其復(fù)雜,讓學(xué)習(xí)Clock驅(qū)動(dòng)的盆友頭大。這里我參考S3C2440的clock驅(qū)動(dòng)寫了一個(gè)virtual clock,即虛擬時(shí)鐘驅(qū)動(dòng),分別包含clock的provider和

    2023年04月21日
    瀏覽(27)
  • Linux -- 字符設(shè)備驅(qū)動(dòng)--LED的驅(qū)動(dòng)開(kāi)發(fā)(初級(jí)框架)

    Linux -- 字符設(shè)備驅(qū)動(dòng)--LED的驅(qū)動(dòng)開(kāi)發(fā)(初級(jí)框架)

    看原理圖確定引腳,確定引腳輸出什么電平才能點(diǎn)亮 / 熄滅 LED 看主芯片手冊(cè),確定寄存器操作方法:哪些寄存器?哪些位?地址是? 編寫驅(qū)動(dòng):先寫框架,再寫硬件操作的代碼 注意 :在芯片手冊(cè)中確定的寄存器地址被稱為 物理地址 ,在 Linux 內(nèi)核中無(wú)法直接使用。 需要使

    2024年04月28日
    瀏覽(27)
  • 嵌入式Linux驅(qū)動(dòng)開(kāi)發(fā) 04:基于設(shè)備樹(shù)的驅(qū)動(dòng)開(kāi)發(fā)

    嵌入式Linux驅(qū)動(dòng)開(kāi)發(fā) 04:基于設(shè)備樹(shù)的驅(qū)動(dòng)開(kāi)發(fā)

    前面文章 《嵌入式Linux驅(qū)動(dòng)開(kāi)發(fā) 03:平臺(tái)(platform)總線驅(qū)動(dòng)模型》 引入了資源和驅(qū)動(dòng)分離的概念,這篇文章將在前面基礎(chǔ)上更進(jìn)一步,引入設(shè)備樹(shù)的概念。 在平臺(tái)總線驅(qū)動(dòng)模型中資源和驅(qū)動(dòng)已經(jīng)從邏輯上和代碼組織上進(jìn)行了分離,但每次調(diào)整資源還是會(huì)涉及到內(nèi)核,所以現(xiàn)

    2024年02月16日
    瀏覽(27)
  • 正點(diǎn)原子嵌入式linux驅(qū)動(dòng)開(kāi)發(fā)——Linux 網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)

    正點(diǎn)原子嵌入式linux驅(qū)動(dòng)開(kāi)發(fā)——Linux 網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)

    網(wǎng)絡(luò)驅(qū)動(dòng)是linux里面驅(qū)動(dòng)三巨頭之一 ,linux下的網(wǎng)絡(luò)功能非常強(qiáng)大,嵌入式linux中也常常用到網(wǎng)絡(luò)功能。前面已經(jīng)講過(guò)了字符設(shè)備驅(qū)動(dòng)和塊設(shè)備驅(qū)動(dòng),本章就來(lái)學(xué)習(xí)一下linux里面的 網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng) 。 本次筆記中討論的都是有線網(wǎng)絡(luò)! 提起網(wǎng)絡(luò),一般想到的硬件就是“網(wǎng)卡”。在

    2024年01月17日
    瀏覽(25)
  • 嵌入式Linux系統(tǒng)中的設(shè)備驅(qū)動(dòng)開(kāi)發(fā):從設(shè)備樹(shù)到驅(qū)動(dòng)實(shí)現(xiàn)

    嵌入式Linux系統(tǒng)中的設(shè)備驅(qū)動(dòng)開(kāi)發(fā):從設(shè)備樹(shù)到驅(qū)動(dòng)實(shí)現(xiàn)

    大家好,今天給大家介紹 嵌入式Linux系統(tǒng)中的設(shè)備驅(qū)動(dòng)開(kāi)發(fā):從設(shè)備樹(shù)到驅(qū)動(dòng)實(shí)現(xiàn) ,文章末尾附有分享大家一個(gè)資料包,差不多150多G。里面學(xué)習(xí)內(nèi)容、面經(jīng)、項(xiàng)目都比較新也比較全! 可進(jìn)群免費(fèi)領(lǐng)取。 在嵌入式Linux系統(tǒng)中,設(shè)備驅(qū)動(dòng)是連接硬件設(shè)備和操作系統(tǒng)之間的橋梁。

    2024年02月19日
    瀏覽(25)
  • 【Linux驅(qū)動(dòng)開(kāi)發(fā)】設(shè)備樹(shù)詳解(三)設(shè)備樹(shù)Kernel解析

    【Linux驅(qū)動(dòng)開(kāi)發(fā)】設(shè)備樹(shù)詳解(三)設(shè)備樹(shù)Kernel解析

    ? ? 活動(dòng)地址:CSDN21天學(xué)習(xí)挑戰(zhàn)賽 【Linux驅(qū)動(dòng)開(kāi)發(fā)】設(shè)備樹(shù)詳解(一)設(shè)備樹(shù)基礎(chǔ)介紹 【Linux驅(qū)動(dòng)開(kāi)發(fā)】設(shè)備樹(shù)詳解(二)設(shè)備樹(shù)語(yǔ)法詳解 【Linux驅(qū)動(dòng)開(kāi)發(fā)】設(shè)備樹(shù)詳解(三)設(shè)備樹(shù)Kernel解析 ? 個(gè)人主頁(yè):董哥聊技術(shù) 我是董哥,嵌入式領(lǐng)域新星創(chuàng)作者 創(chuàng)作理念:專注分享

    2023年04月24日
    瀏覽(14)
  • 深入探討Linux驅(qū)動(dòng)開(kāi)發(fā):Linux設(shè)備樹(shù)

    深入探討Linux驅(qū)動(dòng)開(kāi)發(fā):Linux設(shè)備樹(shù)

    設(shè)備樹(shù)(Device Tree,簡(jiǎn)稱 DT)是一種在嵌入式系統(tǒng)中描述硬件設(shè)備的一種數(shù)據(jù)結(jié)構(gòu)和編程語(yǔ)言。它用于將硬件設(shè)備的配置信息以樹(shù)形結(jié)構(gòu)的方式進(jìn)行描述,以便操作系統(tǒng)(如 Linux)可以根據(jù)這些信息正確地識(shí)別、配置和管理硬件設(shè)備。 設(shè)備樹(shù)最初被引入到 Linux 內(nèi)核中,用于解

    2023年04月27日
    瀏覽(24)
  • Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)學(xué)習(xí)筆記(等待隊(duì)列,鎖,字符驅(qū)動(dòng)程序,設(shè)備樹(shù),i2C...)

    container_of函數(shù)可以通過(guò)結(jié)構(gòu)體的成員變量檢索出整個(gè)結(jié)構(gòu)體 函數(shù)原型: 內(nèi)核開(kāi)發(fā)者只實(shí)現(xiàn)了循環(huán)雙鏈表,因?yàn)檫@個(gè)結(jié)構(gòu)能夠?qū)崿F(xiàn)FIFO和LIFO,并且內(nèi)核開(kāi)發(fā)者要保持最少代碼。 為了支持鏈表,代碼中要添加的頭文件是linux/list.h。內(nèi)核中鏈表實(shí)現(xiàn)核心部分的數(shù)據(jù)結(jié)構(gòu) 是struct li

    2024年01月22日
    瀏覽(19)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包