雖然Linux中有了自己的I2C模組,但是對於一些外設需要通過I2C來設定寄存器,Linux中的I2C模組就不那麼靈活了,這裡主要說明了如何利用已有的匯流排驅動自己編寫裝置驅動來實現I2C的通訊。
I2C通訊的主要手段是使用i2c_client這個結構體,只要獲得了與i2c控制器對應的i2c_client結構體指標,就能夠操縱I2C匯流排。獲得這個結構體的方法是使用兩個函數:
i2c_get_adapter(int index); 和 i2c_new_device(i2c_adapter* ,i2c_board_info*);
這兩個函數都是i定義在/drivers/i2c/i2c-core.c中的,目的是在不知道板載註冊的I2C模組的情況下獲得I2C控制器指標。使用方法參看這篇部落格,說得很好:
http://blog.csdn.net/yuanlulu/article/details/6557901
美中不足的是這篇部落格沒有給出樣本,這裡給出一個樣本說明這兩個東西怎麼使用:
struct i2c_dev_t {struct cdev dev;};/*Global Variables*/static struct i2c_dev_t* global_devp;static dev_t i2cdev_no;static struct i2c_board_info i2c_info = {I2C_BOARD_INFO("myi2c",0xa0>>1),};static struct i2c_client* my_I2C_Client;
static int __init i2c_dev_init(void){int ret = 0;int err = 0;struct i2c_adapter* myI2cAdapter;printk("i2c_dev_init is called!");/*Register cdev*/if( alloc_chrdev_region(&i2cdev_no,0,1,"i2cEEPROM")){printk("%s failed register dev_t",__func__);return -1;}global_devp = kmalloc(sizeof(struct i2c_dev_t),GFP_KERNEL);if(global_devp == 0){/*申請失敗*/unregister_chrdev_region(i2cdev_no,1);return -1;}memset(global_devp,0,sizeof(struct i2c_dev_t));global_devp->dev.owner = THIS_MODULE;cdev_init(&global_devp->dev,&i2cdev_fopt);err = cdev_add(&global_devp->dev,i2cdev_no,1);if(err){printk("%s failed add cdev",__func__);return -1;}//Get property i2c_clientmyI2cAdapter = i2c_get_adapter(0);my_I2C_Client = i2c_new_device(myI2cAdapter,&i2c_info);if(my_I2C_Client == 0){printk("%s failed create i2c client",__func__);return -1;}i2c_put_adapter(myI2cAdapter);printk("%s succeed!",__func__);printk("clinet addr is %x",my_I2C_Client->addr);return 0;}static void __exit i2c_dev_exit(void){cdev_del(&global_devp->dev);kfree(global_devp);unregister_chrdev_region(i2cdev_no,1);i2c_unregister_device(my_I2C_Client);}
i2c_board_info給出了外設地址(低七位為外設地址,因為在i2c_xfer裡面會把這個地址左移一位添加操作字),這樣就不用使用ioctl來設定外設地址了,在exit裡面注意要登出已經註冊的i2c裝置。
感覺這樣做比較簡單,就沒有i2c_driver什麼事情了~只把系統給的模組調入就行。