I2c在应用层读写有两种方式

I2c在应用层读写有两种方式。

1

       ioctl(fd,I2C_TIMEOUT,1);/*超时时间*/
                ioctl(fd,I2C_RETRIES,2);/*重复次数*/
                /***write data to e2prom**/

                e2prom_data.nmsgs=1;
                (e2prom_data.msgs[0]).len=2; //1个 e2prom 写入目标的地址和1个数据 
                (e2prom_data.msgs[0]).addr=0x50;//e2prom 设备地址
                (e2prom_data.msgs[0]).flags=0; //write
                (e2prom_data.msgs[0]).buf=(unsigned char*)malloc(2);
                (e2prom_data.msgs[0]).buf[0]=0x10;// e2prom 写入目标的地址
                (e2prom_data.msgs[0]).buf[1]=0x58;//the data to write

        ret=ioctl(fd,I2C_RDWR,(unsigned long)&e2prom_data);


2

       ioctl(fd,I2C_TIMEOUT,1);/*超时时间*/
                ioctl(fd,I2C_RETRIES,2);/*重复次数*/

        ioctl(fd,I2C_SLAVE,0向0);/*设置地址*/

wirte(fd,&addr,2);//写地址

read(fd,buf,1);//度数据


在内核里写i2c设备驱动的两种方式

dapter方式(LEGACY)”和“Probe方式(new style)”

在2.6.30版本之前使用的是i2c_attach_client()和i2c_detach_client()函数。之后attach被merge到了i2c_new_device中,而detach直接被unresister取代。实际上这两个函数内部都是调用了device_register()和device_unregister()



下面分析一下ov3640 摄像头的驱动

static struct i2c_driver ov3640_i2c_driver = {
.driver = {
.name = "ov3640",
},


.attach_adapter = ov3640_attach_adapter,
.probe = ov3640_probe,
.remove = ov3640_remove,
.command = ov3640_command,
.id_table = ov3640_i2c_id,
};


static __init int ov3640_init(void)
{
printk("ov3640 camera initialized\n");  
return i2c_add_driver(&ov3640_i2c_driver);
}

驱动初始化调用int ov3640_init(void) 。。在这个函数中调用i2c_add_driver(&ov3640_i2c_driver);
调用i2c_add_driver后如果存在adapter适配器就会调用attach函数。在attach在要构造一个client

static int ov3640_attach_adapter(struct i2c_adapter *adapter)
{


int ret = 0;
struct i2c_board_info info;
printk("[ov3640]ov3640_attach_adapter.\n");


memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "ov3640", I2C_NAME_SIZE);
info.addr = ov3640_data.addr;//地址信息包装成结构体i2c_board_info  这个信息最重要
ov3640_data.camera_data.client = i2c_new_device(adapter, &info);
if (!ov3640_data.camera_data.client)
{
printk("failed to abc ov3640 driver\n");
return -ENODEV;
}


if (!ov3640_data.camera_data.client->driver) 
{
i2c_unregister_device(ov3640_data.camera_data.client);
ov3640_data.camera_data.client = NULL;
err("failed to attach ov3640 driver\n");
return -ENODEV;
}


list_add_tail(&ov3640_data.camera_data.client->detected,
     &ov3640_data.camera_data.client->driver->clients);


s3c_fimc_register_camera(&ov3640_data.camera_data);
s3c_fimc_reset_camera(0);


return 0;
}


如果名字一样紧接着就会调用probe函数。。probe函数和第二种方式酒一样了。主要调用i2c_set_clientdata

static int ov3640_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
i2c_set_clientdata(client, &ov3640_data);
//ov3640_start(client);
return 0;
}

到此一个I2C设备就注册成功了。

probe方式




static struct i2c_driver at24_driver = {
.driver = {
.name = "at24",
.owner = THIS_MODULE,
},
.probe = at24_probe,
.remove = __devexit_p(at24_remove),
.id_table = at24_ids,
};


根据器id_table匹配是否调用probe函数。probe函数主要实现同方式一

●    注册i2c_board_info

对于Probe模式,通常在平台代码中要完成i2c_board_info的注册。方法如下:

static struct i2c_board_info __initdata test_i2c_devices[] = {
                {
                        I2C_BOARD_INFO("pca9555", 0x27),//pca9555为芯片名称,0x27为芯片地址
                        .platform_data = &pca9555_data,
                }, {
                        I2C_BOARD_INFO("mt9v022", 0x48),
                        .platform_data = &iclink[0], /* With extender */
                }, {
                        I2C_BOARD_INFO("mt9m001", 0x5d),
                        .platform_data = &iclink[0], /* With extender */
                },
        };
        i2c_register_board_info(0, test_i2c_devices,ARRAY_SIZE(test_i2c_devices)); //注册

i2c_client就是在注册过程中构建的。但有一点需要注意的是i2c_register_board_info并没有EXPORT_SYMBOL给模块使用。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值