linux源码gpio模拟i2c,linux内核gpio模拟i2c实例.doc

41528d3028836879cd698677c3999917.giflinux内核gpio模拟i2c实例.doc

linux内核GPIO模拟I2C实例2010-10-11作者:cvip302814来源:cvip302814的blog前言:在许多情况下,我们并没有足够的I2C总线,本文主在介绍如何利用Linux内核中的i2c-gpio模块,利用2条GPIO线模拟i2c总线,并挂载设备。思路:先通过对i2c-gpio所定义的结构体初始化(包括初始化i2c的2条线,频率,timeout等)并将i2c-gpio模块编译进内核,实现用GPIO_X,GPIO_Y2条GPIO线注册新的i2c总线。此时这个模块对i2c设备是透明的,及挂在这2条GPIO线的i2c设备可以直接使用Linux内核通用的i2c设备注册,传输和注销等方法。步骤:首先确认在注册i2c-gpio模块前,所要用到的2条GPIO口是没有被系统其它地方所调用的。在每个系统平台启动时,都会打开一系列的设备,他们通常实现在arch/目录下相应的平台子目录中的例如setup.c,devices.c文件中,在这里我们进行i2c总线的注册以及设备的挂载。i2c-gpio定义的结构在include/linux/i2c-gpio.h中:/***structi2c_gpio_plat_data-Plat-dependentdatafori2c-gpio*@sda_pin:GPIOpinIDtouseforSDA*@scl_pin:GPIOpinIDtouseforSCL*@udelay:signaltoggledelay.SCLfrequencyis(500/udelay)kHz*@timeout:clockstretchingtimeoutinjiffies.Iftheslavekeeps*SCLlowforlongerthanthis,thetransferwilltimeout.*@sda_is_open_drain:SDAisconfiguredasopendrain,i.e.thepin*isn tactivelydrivenhighwhensettingtheoutputvaluehigh.*gpio_get_value()mustreturntheactualpinstateevenifthe*pinisconfiguredasanoutput.*@scl_is_open_drain:SCLissetupasopendrain.Samerequirements*asforsda_is_open_drainapply.*@scl_is_output_only:SCLoutputdriverscannotbeturnedoff.*/structi2c_gpio_plat_data{unsignedintsda_pin;unsignedintscl_pin;intudelay;inttimeout;unsignedintsda_is_open_drain:1;unsignedintscl_is_open_drain:1;unsignedintscl_is_output_only:1;};其中sda_pin和scl_pin分别是i2c总线的数据线和时钟线,在i2c-gpio中会通过gpio_request函数对这2个口进行申请,udelay和timeout如果不设初值,i2c-gpio中会自动将其设为默认值。if(pdata->udelay)bit_data->udelay=pdata->udelay;elseif(pdata->scl_is_output_only)bit_data->udelay=50;/*10kHz*/elsebit_data->udelay=5;/*100kHz*/if(pdata->timeout)bit_data->timeout=pdata->timeout;elsebit_data->timeout=HZ/10;/*100ms*/初始化这个结构体后再将其装入plat_device结构体,方便注册:staticstructplat_devicei2c_device={.name=“device-name“,.id=your-id,.dev={.plat_data=注册i2c-gpio设备将i2c设备挂入我们注册的总线:plat_device_register(staticstructi2c_board_infoi2c_device[]={{I2C_BOARD_INFO(“name“,i2c_device_addr),}};i2c_register_board_info(your-id,i2c_device,ARRAY_SIZE(i2c_device));此时我们就可以在i2c设备的驱动程序中通过遍历所在i2c总线,得到其所在的地址i2c_device_addr。在i2c驱动中,需要注册一个i2c_driver的结构体,例如:staticconststructi2c_device_idlis35de_id[]={{“lis35de“,0},{}};staticstructi2c_driverst_lis35de_driver={.probe=st_lis35de_probe,.remove=st_lis35de_remove,.suspend=st_lis35de_suspend,.resume=st_lis35de_resume,.id_table=lis35de_id,.driver={.name=“lis35de“,},};staticint__initst_lis35de_init(void){printk(KERN_INFO“st_lis35de_init\n“);returni2c_add_driver(}在init时用i2c_add_driver(&st_lis35de_driver),此时将会对所在i2c总线进行遍历并得到该设备的适配器等信息,主要目的即是使驱动得到自己的i2c_client,在这个i2c_client中,已经有了该i2c设备的地址等信息,我们在驱动中定义一个新的i2c_client全局变量,把得到的这个i2c_client传给这个全局变量,从而可以继续后面的i2c操作。此时我们就可以使用通用的i2c读写操作了。总结:直接用GPIO口模拟I2C时序和利用内核模块i2c-gpio虚拟i2c总线的区别:1.用GPIO口模拟I2C时序不需要在系统启动时注册I2C总线,只需要在I2C设备驱动中单独实现。用i2c-gpio模块虚拟i2c总线需要在系统启动时注册新的I2C总线,并将i2c设备挂载到新的i2c总线,涉及的范围较广。2.用GPIO口模拟I2C时序,代码操作较繁琐,且不方便挂载多个i2c设备。用i2c-gpio模块可以完全模拟i2c总线,可以挂载多个设备。3.在i2c读写操作时,用GPIO口模拟I2C时序需要每次根据读/写操作发送器件地址/*读操作:*/staticinti2c_RxData(char*rxData,intlength){str

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值