Linux下I2C设备驱动开发和实现

发布者:王大雷最新更新时间:2012-03-26 来源: 计算机与信息技术 关键字:I2C  Linux  串行总线 手机看文章 扫描二维码
随时随地手机看文章
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设备驱动程序,在驱动中完成对特定的数据格式的解释以及实现一些专用的功能。[page]
 
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]Philips Corporation,I2C bus specification version 2.1,2000
[2]Aless and Robin著,魏永明等译.《LINUX设备驱动程序(第二版)》.北京:中国电力出版社,2004年
[3]Texas Instruments,inc . USA . TMP75 Datasheet,2004
[4]郑旭阳,李兵兵,黄新平.模拟I2C总线多主通信研究与软件设计.单片机与嵌入式系统应用,2005
关键字:I2C  Linux  串行总线 引用地址:Linux下I2C设备驱动开发和实现

上一篇:基于嵌入式Linux的短信收发系统设计
下一篇:串行RapidIO: 高性能嵌入式互连技术

推荐阅读最新更新时间:2024-03-16 12:56

STM32F1使用I/0模拟I2C接口
使用模拟时序的方法,对比于硬件I2C接口来说,在实时性和传输速度上会带来一些无法避免的下降,但是I2C总线本身也不是一种速度很快的总线(据相关资料可查,最高的速度为400KHZ),同时也不需要具备很高的实时性能。 所以,模拟I2C时序完全能满足绝大部分的场合要求,并且移植性得到了很大的提高。 闲话不多说,贴上代码,大家一起分享下。 首先贴出 i2c_soft.h实现: /*********************************************************************************** * 文件名 :i2c_soft.h * 描述 :使用I/0模拟I2C接口 *
[单片机]
基于FPGA的I2C SLAVE模式总线的设计方案
由于在嵌入式系统开发中越来越多的应用到FPGA,而一些嵌入式CPU,比如STM32 为了降低成本,减小封装尺寸,没有外接专门的CPU 读写总线,而只提供了一些如SPI 和I2C 的接口。而且在应用中经常有数据要配置到FPGA 中,如FPGA 中的应用配置寄存器,和配置表项等,都需要CPU 配置。这些数据的数据量不大,速度也不要求很高,很适合用I2C 总线来配置。 I2C 总线是Philips 公司设计的一种控制和配置内部IC 双向两线的串行总线。主要特点是接口信号线较少,但是其数据的传送速率不是很高,其高速模式下为3.4Mb/s.应用于配置FPGA 比较适合。在通常的应用中嵌入式CPU 作为MASTER 模式的主器件,FPGA 作
[电源管理]
基于FPGA的<font color='red'>I2C</font> SLAVE模式总线的设计方案
Linux下ARM 和单片机的串口通信设计
0 引言 数据采集系统中由于单片机侧重于控制,数据处理能力较弱,对采集的数据进行运算处理比较繁琐,如果通过串口与上位机通信,利用上位机强大的数据处理能力和友好的控制界面对数据进行处理和显示则可以提高设计效率。串口通信以其简单的硬件连接,成熟的通信协议,成为上下位机之间通信的首选。移植了Linux 操作系统的s3c2440 可以在Linux 环境下操作串口,降低了串口操作的难度,可以使开发者集中精力开发大规模的应用程序,而不必在操作底层设计上耗费时间。 1 硬件连接 s3c2440 是 三星 公司生产的基于ARM9 核的处理器,采用3.3 V 电压供电; C8051Fxxx 系列单片机是美国CYGNAL 公司推出的与8051
[单片机]
恩智浦推出双向电压I2C总线转换缓冲器
    中国上海,2013年8月19日讯——恩智浦半导体(NXP Semiconductors N.V.)(纳斯达克代码:NXPI)近日宣布推出PCA9617A超快速模式(Fm+) I²C总线缓冲器,该产品专为使用DDR4 SDRAM存储器的新兴服务器应用而设计。这款具有突破性的电压转换总线缓冲器凭借工作频率高达1 MHz的I²C总线以及CPU侧0.8 V至SDRAM模块侧2.5 V的电压电平转换,使工程师能够采用全新DDR4技术设计新一代服务器系统。恩智浦不断推动I²C总线的创新,I²C总线是一种广泛采用的总线系统管理和控制技术,几乎用于所有计算和企业设备应用。PCA9617A是首款专为服务器设计的Fm+器件。该器件工作频率高达
[电源管理]
恩智浦推出双向电压<font color='red'>I2C</font>总线转换缓冲器
NIOS软核处理器的Linux引导程序U-boot设计
摘要:针对将cClinux向Nios处理器移植过程中的启动加载程序U-boot bootloader进行研究。首先介绍移植的步骤,然后利用bootloader的设计思想,着重讨论U-boot在Nios中的设计与实现,最后对U-boot在基于Linux的嵌入式系统 中的运用作了探索和展望。 关键词:U-boot bootloader uClinux Nios软核 1 概述 1.1 Nios简介 Nios是Altera公司以RISC为基础的可配置、可裁减软核处理器。它具有16位指令集和16/32位数据通路,通过将包括16或32位高性能处理器在内的移种应用模块嵌入到通用FPGA/CPLD内,实现完全可配置的嵌入式系统。其开发套件
[半导体设计/制造]
基于EPM7312的新型嵌入式系统的实现
   1 前言   随着以计算机和软件为核心的数字化技术的迅速发展,多媒体技术与Internet 的应用迅速普及。计算机﹑通讯﹑消费电子一体化的趋势日趋明显。作为新型智能3C合一的嵌入式系统与技术进入智能化﹑网络化的发展阶段。   所谓嵌入式系统,即将应用程序和操作系统和计算机硬件集成在一起的系统。简而言之即软硬件一体化。这种系统具有小巧灵活﹑性价比高﹑自动化高﹑实时性强﹑专业性强等特点。嵌入式系统适合应用于人类工作与生活的各个领域,最为典型的应用有机顶盒﹑数字应用﹑WebTV﹑ATM/POS机﹑多媒体手机﹑袖珍电脑﹑车载导航器﹑航空电子等等。嵌入式技术已经深入人类生活和工作的方方面面,在娱乐,军事方面也有强大的应用潜力。
[嵌入式]
常见的工业相机电缆接口类型有多少种?
众所周知,工业相机的定义是机器视觉系统中的一个关键组件,其本质的功能就是将光信号转变成有序的电信号。若想将相机采集图像进行传输,就需要通过相机的接口来实现,将图像数据传输到我们的设备上。而工业相机电缆,就是专门用于工业相机的一种电缆产品。那么常见的工业相机电缆接口类型有哪些吗? 常见的工业相机电缆接口类型,如下: 1、USB 接口 USB 接口相机是数字相机,直接输出数字图像信号。USB 全称是 Universal Serial Bus(通用串行总线),USB 接口是 4“针”,其中 2 根为电源线、2 根为信号线。USB 是串行接口,可热拔插,连接方便。USB2.0,传输速度 480Mbps,通讯距离 5m,80%的带宽用于
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • ARM裸机篇--按键中断
    先看看GPOI的输入实验:按键电路图:GPF1管教的功能:EINT1要使用GPF1作为EINT1的功能时,只要将GPFCON的3:2位配置成10就可以了!GPF1先配 ...
  • 网上下的--ARM入门笔记
    简单的介绍打今天起菜鸟的ARM笔记算是开张了,也算给我的这些笔记找个存的地方。为什么要发布出来?也许是大家感兴趣的,其实这些笔记之所 ...
  • 学习ARM开发(23)
    三个任务准备与运行结果下来看看创建任务和任运的栈空间怎么样的,以及运行输出。Made in china by UCSDN(caijunsheng)Lichee 1 0 0 ...
  • 学习ARM开发(22)
    关闭中断与打开中断中断是一种高效的对话机制,但有时并不想程序运行的过程中中断运行,比如正在打印东西,但程序突然中断了,又让另外一个 ...
  • 学习ARM开发(21)
    先要声明任务指针,因为后面需要使用。 任务指针 volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • 学习ARM开发(20)
  • 学习ARM开发(19)
  • 学习ARM开发(14)
  • 学习ARM开发(15)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved