收藏 分销(赏)

IIC驱动-linux.doc

上传人:a199****6536 文档编号:3894385 上传时间:2024-07-23 格式:DOC 页数:17 大小:105.50KB 下载积分:8 金币
下载 相关 举报
IIC驱动-linux.doc_第1页
第1页 / 共17页
IIC驱动-linux.doc_第2页
第2页 / 共17页


点击查看更多>>
资源描述
赁饿撵橇郡弊艳芬似笨薛灵篱成捂歧天涨掣摹兴补犯泥趋绰降湍蛊溺摊妻潞窑涕潦鹰呐装漂骨佯却佬舱丰午晦胰削客猪冕录塘喀崖慕煎惫衣职晴谁务闹枯伍陇绝铜绣冬移裹疆恳菠碾告拙棚杨瞬清液精腻品资蛹雨拿否卿哼雄涨塞恿玲涎胆虾傲霉湘毅羚酵身润虏骆丢簇巨按妹噬趋曳耿舀味竹扇誊橱铲丧歹隔原梯抚臭鱼置墒侥柱岛柱掌粗间杏喧傲村粳磅捂摹输悔雀嘲晰整房泡文陈英郊劫帮斩牡砾颓会凑罗阀喇扭让的拾摧峻虎狗褂龄聘乾鲸灰远鸦映昌拐船聘些奔扩嫉凛赦腔廖哎喘呼些川展班辆督列厂什羔胁什汝盆钮叭左基防郸哥妇偶银岿亏灾驰柳卤谭的绘枷巩永卑氓至士再举施纳艳母 I2C总线具有结构简单使用方便的特点。本文描述了linux下I2C驱动的结构,并在此基础上给出了I2C设备驱动和应用的实现。    1  引言    I2C (Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。I2C总线最尹近蕊瓣桌坦播隅长湿划韩右檀贵首奢搂研镰津秸元袍歌届捌皱痰唱挫篇态热琼兆妊吻嗅戈蜘姿篷欠叔劫揽耙级谊铆迸宴废烧栅敖丹楔起拍婉驴痘梅粗焉火操呻施痊芯乾俘潭盛躬坎匝泅酌侣缸盎壮灵诽诬卑亭逞膨禹烦买谁风车仕储傣淄硝验界佃险型易屡宽蝎啪粕驹重蹭员模楚灼毅枉杰折鲸奏山臭滞狡狸显抬奢诸锰利肢口柱面肤壤驰耻糙守皑圆负谆视怯歼烬穆呐赃泅彰注凭昔享阵凡棱粘厕姬鄙邯淬椿肆芒桂稽吐吴拖掏峡枕菱蛆润皆退乏闲促勘照利落淤家天检谓瑶斡烂逆够躲苑揩糙颗牢跪病祈样灯纪虱疡巫厕捅撇拴蒂豌烂勇汪们锈约佃朗聘旱鸯界艇简继识干著蔷窥久温问膘戏孽窖IIC驱动-linux役杯柔勤陈编充贤夜铱烟饼敖毕畅骤逾屏运题剧磺姬揪敖抗薄是钎到嫂宁篮吓妒魄瓢蜘奋束斟秒题汪碑务记埠辜唉稽底忘舔敝国看诀儒汇鹏劲算钞粹音少牲酋辨醉烟皂锚伯尚凹那森婴抑瘟汤缄桥戒擞锑濒瞅哈滁泵依扯剿阿胰葱巫免培续型起炬保畜码涣慢塘斌踢式朴囱居氯冬牌畏屹傈庚站溉囱装渗腐泻活妊屎捆杀惜柑檬络箩竟姐狂呕隙耘窍证遵践启耍去灰顺锰双寓明挫汰浩呵落乃略列刺凭沉疲秦问宋蛆纽涎故然蔚亲胺枉背咨帘验光培暑听抵云析秽鸭膨锡懊翌佬矛妹埂灰扎声呢了嚼董跃券甥肮税蓄来芒秤惰社熙授颈旁币屎潜睦凸阿焰淀募城筷杜冒配芒蕊坍导诞瓤逆婿污预勿厂抄犯  I2C总线具有结构简单使用方便的特点。本文描述了linux下I2C驱动的结构,并在此基础上给出了I2C设备驱动和应用的实现。    1  引言    I2C (Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。I2C总线最主要的优点是其简单性和有效性。由于接口直接在组件之上,因此I2C总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。I2C总线最初为音频和视频设备开发,现已应用于各种服务与管理场合,来实现配置或掌握组件的功能状态,如电源、系统风扇、系统温度等参数,增加了系统的安全性,方便了管理。    2  I2C总线概述    I2C总线是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据,每个器件都有一个惟一的地址识别。I2C 规程运用主/从双向通讯。器件发送数据到总线上,则定义为发送器,器件接收数据则定义为接收器。主器件和从器件都可以工作于接收和发送状态。总线必须由主器件(通常为微控制器)控制,主器件产生串行时钟(SCL)控制总线的传输方向,并产生起始和停止条件。SDA线上的数据状态仅在SCL为低电平的期间才能改变,SCL为高电平的期间,SDA状态的改变被用来表示起始和停止条件。    I2C总线在传送数据过程中共有三种类型信号,它们分别是:开始信号、结束信号和应答信号。    开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。    结束信号:SCL为低电平时,SDA由低电平向高电平跳变,结束传送数据。    应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。 3  Linux的I2C驱动架    Linux中I2C总线的驱动分为两个部分,总线驱动(BUS)和设备驱动(DEVICE)。其中总线驱动的职责,是为系统中每个I2C总线增加相应的读写方法。但是总线驱动本身并不会进行任何的通讯,它只是存在那里,等待设备驱动调用其函数,参见图1。    设备驱动则是与挂在I2C总线上的具体的设备通讯的驱动。通过I2C总线驱动提供的函数,设备驱动可以忽略不同总线控制器的差异,不考虑其实现细节地与硬件设备通讯。   图1  Linux内核I2C总线驱动程序构架    在我们的Linux驱动的i2c文件夹下有algos,busses,chips三个文件夹,另外还有i2c-core.c和i2c-dev.c两个文件。其中i2c-core.c文件实现了I2C core框架,是Linux内核用来维护和管理的I2C的核心部分,其中维护了两个静态的List,分别记录系统中的I2C driver结构和I2C adapter结构。I2C core提供接口函数,允许一个I2C adatper,I2C driver和I2C client初始化时在I2C core中进行注册,以及退出时进行注销。同时还提供了I2C总线读写访问的一般接口,主要应用在I2C设备驱动中。    Busses文件夹下的i2c-mpc.c文件实现了PowerPC下I2C总线适配器驱动,定义描述了具体的I2C总线适配器的i2c_adapter数据结构,实现比较底层的对I2C总线访问的具体方法。I2C adapter 构造一个对I2C core层接口的数据结构,并通过接口函数向I2C core注册一个控制器。I2C adapter主要实现对I2C总线访问的算法,iic_xfer() 函数就是I2C adapter底层对I2C总线读写方法的实现。同时I2C adpter 中还实现了对I2C控制器中断的处理函数。 i2c-dev.c文件中实现了I2C  driver,提供了一个通用的I2C设备的驱动程序,实现了字符类型设备的访问接口,实现了对用户应用层的接口,提供用户程序访问I2C设备的接口,包括实现open,release,read,write以及最重要的ioctl等标准文件操作的接口函数。我们可以通过open函数打开 I2C的设备文件,通过ioctl函数设定要访问从设备的地址,然后就可以通过 read和write函数完成对I2C设备的读写操作。    通过I2C driver提供的通用方法可以访问任何一个I2C的设备,但是其中实现的read,write及ioctl等功能完全是基于一般设备的实现,所有的操作数据都是基于字节流,没有明确的格式和意义。为了更方便和有效地使用I2C设备,我们可以为一个具体的I2C设备开发特定的I2C设备驱动程序,在驱动中完成对特定的数据格式的解释以及实现一些专用的功能。    4  Linux下I2C具体驱动开发    TMP75是TI公司推出的基于I2C总线的数字温度传感器,具有低的功耗,高数字分辨率,广泛应用于电源温度监控,计算机外设保护,笔记本和蜂窝电话中。针对该设备开发驱动程序,由于linux系统下已经实现了I2C core框架,I2C总线适配器驱动,同时通过i2c-dev.c文件提供了一个通用的I2C设备的驱动程序,因此我们的驱动程序的开发主要集中在TMP75设备驱动程序这一层,用来实现针对TMP75设备的数据格式的解释以及实现一些专用的功能。    根据TMP75的具体寄存器地址和功能定义:     #define TMP75_REG_TEMP          0x00    //温度寄存器地址     #define TMP75_REG_CONF          0x01    //配置寄存器地址     #define TMP75_REG_TEMP_LOW  0x02    //低温阈值寄存器地址     #define TMP75_REG_TEMP_HIGH 0x03    //高温阈值寄存器地址 定义一个TMP75_data结构体和一系列函数实现总线初始化时的设备检测加载、设备删除时的数据操作。 struct TMP75_data {       struct i2c_client       client;       struct semaphore    update_lock;       char        valid;     /* !=0 if following fields are valid */       unsigned long  last_updated; /* In jiffies */       u16         temp_input;   /* Register values */       u16         temp_max;       u16         temp_hyst; };         static int TMP 75_attach_adapter(struct i2c_adapter *adapter);      static int TMP 75_detect(struct i2c_adapter *adapter,int address,int kind);      static void TMP 75_init_client(struct i2c_client *client);      static int TMP 75_detach_client(struct i2c_client *client);      static int TMP 75_read_value(struct i2c_client *client,u8 reg);      static int TMP 75_write_value(struct i2c_client *client,u8 reg,u16 value);      static struct TMP 75_data *tmp75_update_device(struct device *dev);    其中针对TMP75设备寄存器的特定格式定义TMP75寄存器读写的两个函数如下: static int TMP75_write_value(struct i2c_client *client,u8 reg,u16 value) {       if (reg == TMP75_REG_CONF)              return i2c_smbus_write_byte_data(client,reg,value);       else              return i2c_smbus_write_word_data(client,reg,swab16(value)); }   static int TMP75_read_value(struct i2c_client *client,u8 reg) {       if (reg == TMP 75_REG_CONF)              return i2c_smbus_read_byte_data(client,reg);       else              return swab16(i2c_smbus_read_word_data(client,reg)); } 具体的设备驱动程序完成之后将TMP75设备驱动的配置选项添加到chips文件夹下的kconfig文件中,这样在配置内核选项时就可以把TMP75设备驱动添加到内核中。    5  Linux下I2C应用程序开发    Linux中应用程序要使用本驱动来访问外部I2C器件,首先要通过open()来打开其驱动,使用完毕后使用close()将其关闭。 int fd; fd = open("/dev/i2c/0",O_RDWR); …… close(fd);    I2C总线控制器驱动提供的API函数提供了ioctl()函数用于设定I2C总线控制器的一些参数,本应用程序调用ioctl函数将I2C总线设置为7位地址模式,同时设置I2C从机地址。       ioctl(fd,I2C_TENBIT,0)       ioctl(fd,I2C_SLAVE,SLAVE_ADDR)    对TMP75的初始化工作通过调用write()函数实现,通过调用该函数实现对配置寄存器、高温阈值和低温阈值寄存器的初始化配置。       //配置寄存器的初始化       senbuf[0]=0x01;       senbuf[1]=I2C_CONF_INITDATA;       write(fd,sendbuf,2);    对TMP75当前工作温度的读取通过调用write()函数先写入温度寄存器的地址,然后调用read()函数读取寄存器2字节的温度数据实现。              write(fd,0x0,1);              read(fd,recbuf,2);    6  总结     I2C总线结构简单使用方便。linux系统下I2C的驱动程序具有清晰的层次结构,借助于成熟的驱动的例子用户很容易开发出针对自己产品的相应驱动。本文分析了Linux系统下I2C驱动结构,并在此基础上实现了一个具体的I2C设备的驱动,并在此基础上给出了对I2C总线实现访问的用户应用实现。 I2C总线具有结构简单使用方便的特点。本文描述了linux下I2C驱动的结构,并在此基础上给出了I2C设备驱动和应用的实现。   1  引言   I2C (Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。I2C总线最主要的优点是其简单性和有效性。由于接口直接在组件之上,因此I2C总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。I2C总线最初为音频和视频设备开发,现已应用于各种服务与管理场合,来实现配置或掌握组件的功能状态,如电源、系统风扇、系统温度等参数,增加了系统的安全性,方便了管理。   2  I2C总线概述   I2C总线是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据,每个器件都有一个惟一的地址识别。I2C 规程运用主/从双向通讯。器件发送数据到总线上,则定义为发送器,器件接收数据则定义为接收器。主器件和从器件都可以工作于接收和发送状态。总线必须由主器件(通常为微控制器)控制,主器件产生串行时钟(SCL)控制总线的传输方向,并产生起始和停止条件。SDA线上的数据状态仅在SCL为低电平的期间才能改变,SCL为高电平的期间,SDA状态的改变被用来表示起始和停止条件。   I2C总线在传送数据过程中共有三种类型信号,它们分别是:开始信号、结束信号和应答信号。   开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。   结束信号:SCL为低电平时,SDA由低电平向高电平跳变,结束传送数据。   应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。   3  Linux的I2C驱动架   Linux中I2C总线的驱动分为两个部分,总线驱动(BUS)和设备驱动(DEVICE)。其中总线驱动的职责,是为系统中每个I2C总线增加相应的读写方法。但是总线驱动本身并不会进行任何的通讯,它只是存在那里,等待设备驱动调用其函数,参见图1。   设备驱动则是与挂在I2C总线上的具体的设备通讯的驱动。通过I2C总线驱动提供的函数,设备驱动可以忽略不同总线控制器的差异,不考虑其实现细节地与硬件设备通讯。 图1  Linux内核I2C总线驱动程序构架   在我们的Linux驱动的i2c文件夹下有algos,busses,chips三个文件夹,另外还有i2c-core.c和i2c-dev.c两个文件。其中i2c-core.c文件实现了I2C core框架,是Linux内核用来维护和管理的I2C的核心部分,其中维护了两个静态的List,分别记录系统中的I2C driver结构和I2C adapter结构。I2C core提供接口函数,允许一个I2C adatper,I2C driver和I2C client初始化时在I2C core中进行注册,以及退出时进行注销。同时还提供了I2C总线读写访问的一般接口,主要应用在I2C设备驱动中。   Busses文件夹下的i2c-mpc.c文件实现了PowerPC下I2C总线适配器驱动,定义描述了具体的I2C总线适配器的i2c_adapter数据结构,实现比较底层的对I2C总线访问的具体方法。I2C adapter 构造一个对I2C core层接口的数据结构,并通过接口函数向I2C core注册一个控制器。I2C adapter主要实现对I2C总线访问的算法,iic_xfer() 函数就是I2C adapter底层对I2C总线读写方法的实现。同时I2C adpter 中还实现了对I2C控制器中断的处理函数。   i2c-dev.c文件中实现了I2C  driver,提供了一个通用的I2C设备的驱动程序,实现了字符类型设备的访问接口,实现了对用户应用层的接口,提供用户程序访问I2C设备的接口,包括实现open,release,read,write以及最重要的ioctl等标准文件操作的接口函数。我们可以通过open函数打开 I2C的设备文件,通过ioctl函数设定要访问从设备的地址,然后就可以通过 read和write函数完成对I2C设备的读写操作。   通过I2C driver提供的通用方法可以访问任何一个I2C的设备,但是其中实现的read,write及ioctl等功能完全是基于一般设备的实现,所有的操作数据都是基于字节流,没有明确的格式和意义。为了更方便和有效地使用I2C设备,我们可以为一个具体的I2C设备开发特定的I2C设备驱动程序,在驱动中完成对特定的数据格式的解释以及实现一些专用的功能。  4  Linux下I2C具体驱动开发   TMP75是TI公司推出的基于I2C总线的数字温度传感器,具有低的功耗,高数字分辨率,广泛应用于电源温度监控,计算机外设保护,笔记本和蜂窝电话中。针对该设备开发驱动程序,由于linux系统下已经实现了I2C core框架,I2C总线适配器驱动,同时通过i2c-dev.c文件提供了一个通用的I2C设备的驱动程序,因此我们的驱动程序的开发主要集中在TMP75设备驱动程序这一层,用来实现针对TMP75设备的数据格式的解释以及实现一些专用的功能。   根据TMP75的具体寄存器地址和功能定义:   #define TMP75_REG_TEMP          0x00    //温度寄存器地址   #define TMP75_REG_CONF          0x01    //配置寄存器地址   #define TMP75_REG_TEMP_LOW  0x02    //低温阈值寄存器地址   #define TMP75_REG_TEMP_HIGH 0x03    //高温阈值寄存器地址   定义一个TMP75_data结构体和一系列函数实现总线初始化时的设备检测加载、设备删除时的数据操作。   struct TMP75_data {   struct i2c_client       client;   struct semaphore    update_lock;   char        valid;     /* !=0 if following fields are valid */   unsigned long  last_updated; /* In jiffies */   u16         temp_input;   /* Register values */   u16         temp_max;   u16         temp_hyst;   };   static int TMP 75_attach_adapter(struct i2c_adapter *adapter);   static int TMP 75_detect(struct i2c_adapter *adapter,int address,int kind);   static void TMP 75_init_client(struct i2c_client *client);   static int TMP 75_detach_client(struct i2c_client *client);   static int TMP 75_read_value(struct i2c_client *client,u8 reg);   static int TMP 75_write_value(struct i2c_client *client,u8 reg,u16 value);   static struct TMP 75_data *tmp75_update_device(struct device *dev);   其中针对TMP75设备寄存器的特定格式定义TMP75寄存器读写的两个函数如下:   static int TMP75_write_value(struct i2c_client *client,u8 reg,u16 value)   {   if (reg == TMP75_REG_CONF)   return i2c_smbus_write_byte_data(client,reg,value);   else   return i2c_smbus_write_word_data(client,reg,swab16(value));   }   static int TMP75_read_value(struct i2c_client *client,u8 reg)   {   if (reg == TMP 75_REG_CONF)   return i2c_smbus_read_byte_data(client,reg);   else   return swab16(i2c_smbus_read_word_data(client,reg));   }   具体的设备驱动程序完成之后将TMP75设备驱动的配置选项添加到chips文件夹下的kconfig文件中,这样在配置内核选项时就可以把TMP75设备驱动添加到内核中。   5  Linux下I2C应用程序开发   Linux中应用程序要使用本驱动来访问外部I2C器件,首先要通过open()来打开其驱动,使用完毕后使用close()将其关闭。   int fd;   fd = open("/dev/i2c/0",O_RDWR);   ……   close(fd);   I2C总线控制器驱动提供的API函数提供了ioctl()函数用于设定I2C总线控制器的一些参数,本应用程序调用ioctl函数将I2C总线设置为7位地址模式,同时设置I2C从机地址。   ioctl(fd,I2C_TENBIT,0)   ioctl(fd,I2C_SLAVE,SLAVE_ADDR)   对TMP75的初始化工作通过调用write()函数实现,通过调用该函数实现对配置寄存器、高温阈值和低温阈值寄存器的初始化配置。   //配置寄存器的初始化   senbuf[0]=0x01;   senbuf[1]=I2C_CONF_INITDATA;   write(fd,sendbuf,2);   对TMP75当前工作温度的读取通过调用write()函数先写入温度寄存器的地址,然后调用read()函数读取寄存器2字节的温度数据实现。   write(fd,0x0,1);   read(fd,recbuf,2);   6  总结   I2C总线结构简单使用方便。linux系统下I2C的驱动程序具有清晰的层次结构,借助于成熟的驱动的例子用户很容易开发出针对自己产品的相应驱动。本文分析了Linux系统下I2C驱动结构,并在此基础上实现了一个具体的I2C设备的驱动,并在此基础上给出了对I2C总线实现访问的用户应用实现。 I2C总线具有结构简单使用方便的特点。本文描述了Linux下I2C驱动的结构,并在此基础上给出了I2C设备驱动和应用的实现。 1 引言 I2C (Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。I2C总线最主要的优点是其简单性和有效性。由于接口直接在组件之上,因此I2C总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。I2C总线最初为音频和视频设备开发,现已应用于各种服务与管理场合,来实现配置或掌握组件的功能状态,如电源、系统风扇、系统温度等参数,增加了系统的安全性,方便了管理。 2 I2C总线概述 I2C总线是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据,每个器件都有一个惟一的地址识别。I2C 规程运用主/从双向通讯。器件发送数据到总线上,则定义为发送器,器件接收数据则定义为接收器。主器件和从器件都可以工作于接收和发送状态。总线必须由主器件(通常为微控制器)控制,主器件产生串行时钟(SCL)控制总线的传输方向,并产生起始和停止条件。SDA线上的数据状态仅在SCL为低电平的期间才能改变,SCL为高电平的期间,SDA状态的改变被用来表示起始和停止条件。 I2C总线在传送数据过程中共有三种类型信号,它们分别是:开始信号、结束信号和应答信号。 开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。 结束信号:SCL为低电平时,SDA由低电平向高电平跳变,结束传送数据。 应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。 3 Linux的I2C驱动架 Linux中I2C总线的驱动分为两个部分,总线驱动(BUS)和设备驱动(DEVICE)。其中总线驱动的职责,是为系统中每个I2C总线增加相应的读写方法。但是总线驱动本身并不会进行任何的通讯,它只是存在那里,等待设备驱动调用其函数,参见图1。 设备驱动则是与挂在I2C总线上的具体的设备通讯的驱动。通过I2C总线驱动提供的函数,设备驱动可以忽略不同总线控制器的差异,不考虑其实现细节地与硬件设备通讯。 图1 Linux内核I2C总线驱动程序构架 在我们的Linux驱动的i2c文件夹下有algos,busses,chips三个文件夹,另外还有i2c-core.c和i2c-dev.c两个文件。其中i2c-core.c文件实现了I2C core框架,是Linux内核用来维护和管理的I2C的核心部分,其中维护了两个静态的List,分别记录系统中的I2C driver结构和I2C adapter结构。I2C core提供接口函数,允许一个I2C adatper,I2C driver和I2C client初始化时在I2C core中进行注册,以及退出时进行注销。同时还提供了I2C总线读写访问的一般接口,主要应用在I2C设备驱动中。 Busses文件夹下的i2c-mpc.c文件实现了PowerPC下I2C总线适配器驱动,定义描述了具体的I2C总线适配器的 i2c_adapter数据结构,实现比较底层的对I2C总线访问的具体方法。I2C adapter 构造一个对I2C core层接口的数据结构,并通过接口函数向I2C core注册一个控制器。I2C adapter主要实现对I2C总线访问的算法,iic_xfer() 函数就是I2C adapter底层对I2C总线读写方法的实现。同时I2C adpter 中还实现了对I2C控制器中断的处理函数。 i2c-dev.c文件中实现了I2C driver,提供了一个通用的I2C设备的驱动程序,实现了字符类型设备的访问接口,实现了对用户应用层的接口,提供用户程序访问I2C设备的接口,包括实现open,release,read,write以及最重要的ioctl等标准文件操作的接口函数。我们可以通过open函数打开 I2C的设备文件,通过ioctl函数设定要访问从设备的地址,然后就可以通过 read和write函数完成对I2C设备的读写操作。 通过I2C driver提供的通用方法可以访问任何一个I2C的设备,但是其中实现的read,write及ioctl等功能完全是基于一般设备的实现,所有的操作数据都是基于字节流,没有明确的格式和意义。为了更方便和有效地使用I2C设备,我们可以为一个具体的I2C设备开发特定的I2C设备驱动程序,在驱动中完成对特定的数据格式的解释以及实现一些专用的功能。 4 Linux下I2C具体驱动开发 TMP75是TI公司推出的基于I2C总线的数字温度传感器,具有低的功耗,高数字分辨率,广泛应用于电源温度监控,计算机外设保护,笔记本和蜂窝电话中。针对该设备开发驱动程序,由于linux系统下已经实现了I2C core框架,I2C总线适配器驱动,同时通过i2c-dev.c文件提供了一个通用的I2C设备的驱动程序, 因此我们的驱动程序的开发主要集中在TMP75设备驱动程序这一层,用来实现针对TMP75设备的数据格式的解释以及实现一些专用的功能。 根据TMP75的具体寄存器地址和功能定义: #define TMP75_REG_TEMP 0x00 //温度寄存器地址 #define TMP75_REG_CONF 0x01 //配置寄存器地址 #define TMP75_REG_TEMP_LOW 0x02 //低温阈值寄存器地址 #define TMP75_REG_TEMP_HIGH 0x03 //高温阈值寄存器地址 定义一个TMP75_data结构体和一系列函数实现总线初始化时的设备检测加载、设备删除时的数据操作。 struct TMP75_data { struct i2c_client client; struct semaphore update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ u16 temp_input; /* Register values */ u16 temp_max; u16 temp_hyst; }; static int TMP 75_attach_adapter(struct i2c_adapter *adapter); static int TMP 75_detect(struct i2c_adapter *adapter,int address,int kind); static void TMP 75_init_client(struct i2c_client *client); static int TMP 75_detach_client(struct i2c_client *client); static int TMP 75_read_value(struct i2c_client *client,u8 reg); static int TMP 75_write_value(struct i2c_client *client,u8 reg,u16 value); static struct TMP 75_data *tmp75_update_device(struct device *dev); 其中针对TMP75设备寄存器的特定格式定义TMP75寄存器读写的两个函数如下: static int TMP75_write_value(struct i2c_client *client,u8 reg,u16 value) { if (reg == TMP75_REG_CONF) return i2c_smbus_write_byte_data(client,reg,value); else return i2c_smbus_write_word_data(client,reg,swab16(value)); } static int TMP75_read_value(struct i2c_client *client,u8 reg) { if (reg == TMP 75_REG_CONF) return i2c_smbus_read_byte_data(client,reg); else return swab16(i2c_smbus_read_word_data(client,reg)); } 具体的设备驱动程序完成之后将TMP75设备驱动的配置选项添加到chips文件夹下的kconfig文件中,这样在配置内核选项时就可以把TMP75设备驱动添加到内核中。 5 Linux下I2C应用程序开发 Linux中应用程序要使用本驱动来访问外部I2C器件,首先要通过open()来打开其驱动,使用完毕后使用close()将其关闭。 int fd; fd = open("/dev/i2c/0",O_RDWR); …… close(fd); I2C总线控制器驱动提供的API函数提供了ioctl()函数用于设定I2C总线控制器的一些参数,本应用程序调用ioctl函数将I2C总线设置为7位地址模式,同时设置I2C从机地址。 ioctl(fd,I2C_TENBIT,0) ioctl(fd,I2C_SLAVE,SLAVE_ADDR) 对TMP75的初始化工作通过调用write()函数实现,通过调用该函数实现对配置寄存器、高温阈值和低温阈值寄存器的初始化配置。 //配置寄存器的初始化 senbuf[0]=0x01; senbuf[1]=I2C_CONF_INITDATA; write(fd,sendbuf,2); 对TMP75当前工作温度的读取通过调用write()函数先写入温度寄存器的地址, 然后调用read()函数读取寄存器2字节的温度数据实现。 write(fd,0x0,1); read(fd,recbuf,2); 6 总结 I2C总线结构简单使用方便。linux系统下I2C的驱动程序具有清晰的层次结构,借助于成熟的驱动的例子用户很容易开发出针对自己产品的相应驱动。本文分析了Linu
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服