积分规则 网站地图 帮助中心    
嵌入式软件 单 片 机 DSP 存储器 传感控制 光电显示
嵌入式硬件 CPLD/FPGA SOPC AD/DA 接口电路 模拟设计
I C设计 通信产品 汽车电子 电源产品 消费电子 数控系统
工业控制 军工/航天 安防产品 医疗电子 计算机外设 测试测量
供应 I C
求购 公司库

  IC 求购 销售 公司 论文 DATASHEET 参考设计 论坛
当前位置: 电子技术 >> 嵌入式软件 >> LINUX
  相关分类: LINUX | WINCE | UC/OS | Bootloader | 下载 | VXWORKS | 网络协议 | JAVA | 汇编 | 驱动设计 | Symbian | XP Embedded | Nucleus | 新产品 | 相关文章 | 综合技术 |
Linux下I2C设备驱动开发和实现
 
作者:商凯 周轶男   来源:计算机与信息技术    点击数:385   更新时间:2008-5-19
您可以添加到网摘 让更多人关注此文章:

        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总线驱动提供的函数,设备驱动可以忽略不同总线控制器的差异,不考虑其实现细节地与硬件设备通讯。


Linux内核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总线实现访问的用户应用实现。


[1] [2]  下一页



相关文章
· Linux液晶屏驱动开发[50]
· Linux系统在嵌入式DVR中的应用[31]
· 基于嵌入式Linux的移动终端的软件设计[44]
· 英特尔收购Opened Hand 发力Linux[49]
· 基于嵌入式Linux环境下MiniGUI的研究与移植[44]
热门评论排行
·VHDL设计中电路简化问题的
·江苏嵌入式Linux教育培训
·锐极LINUX驱动培训班定于
·基于实时操作系统μC/OS-
·ARM处理器应用开发4步骤

文章评论
    没有任何评论
*只显示最新10条评论。评论内容只代表网友观点,与本站立场无关。更多评论
发表评论
  * 请先[登陆]再进行评论,谢谢。
评分: 1分 2分 3分 4分 5分
内容: *
发帖须知:
一.所发文章必须遵守《互联网电子公告服务管理规定》;
二.严禁发布供求代理信息,公司介绍,产品信息等广告宣传信息;
三.严禁恶意重复发帖;
四.严禁对个人,实体,民族,国家等进行漫骂,污蔑,诽谤。
 
热点新闻 [更多]
 
各种冲值卡批发销售!独家特价!
特价销售GPS车载导航系统!
数字电视批发销售!你想不到的价格!
品牌相机批发销售!你想不到的价格!
品牌手机批发销售!你想不到的价格!
笔记本电脑批发销售!你想不到的价格!
那一年我做了鸭子2
那一年我做了鸭子1
等你十年(下)
等你十年(上)
 
热门下载 [更多]
 
[ ] 手把手学单片机20个例
[ ] 单片机做的智能台灯
[ ] 单片机入门书
[ ] linux系统移植开发文档
[ ] IC卡的读写程序
[ ] 8051单片机C语言彻底应用
[ 常用软件] 555定时器电路设计软件V1.2
[ 常用软件] 51定时器计算软件
[ ] ARM处理器应用开发4步骤
[ ] 实用电源电路集锦
 
论坛新帖 [更多]
 
新店开业,部分开发板&元器件特...
[原创]VB编程RS232串口...
红外摄像机控制故障分析与处理方...
红外防水摄像机在智能视频监控中...
步进电机不用驱动芯片能驱动吗?...
我要选一块双串口,带AD的单片...
[分享]运放和功放的区别是什么...
4×4矩阵式键盘的课程设计...
做过高速信号滤波的高手帮忙...
做视频信号放大器,各位有什么好...

 
赞助商 [更多]
 


ICP许可证号:[粤 05056597]
联系电话:010-82517432 82517615 传真: 010-82517615

版权所有 Copyright © 2006 嵌入式技术网