APP下载

Linux下I2C设备驱动的一种适配器层直接实现方法

2011-06-25杨文铂邢鹏康

单片机与嵌入式系统应用 2011年6期
关键词:适配器接收器寄存器

杨文铂,邢鹏康

(河南工业职业技术学院,南阳 473000)

1 概 述

I2C总线作为一种接口标准最早由Philips公司提出,因其优良的性能在电子工业中得到了广泛的应用。在嵌入式Linux系统下,标准的I2C驱动为分层架构,由上至下依次是设备层、核心层和适配器层。这种多层架构有效满足了Linux下多设备、多任务并行工作的要求,但同时也使I2C设备驱动的开发变得非常复杂。本文探讨了一种在I2C设备串行工作的情况下,直接在适配器层实现的I2C驱动方法,这将有效简化Linux下I2C设备驱动的开发。这里基于ARM9的S3C2440芯片和2.6.30核心的嵌入式Linux系统平台进行分析。

2 I 2C总线及时序

I2C设备分为主机及从机。主机即主控芯片内的I2C适配器,它完成基本的时序控制功能,如起始、传输数据、停止等。从机即外围I2C芯片,它是被主机寻址的器件,接收主机发送的命令和数据,返回相应的数据。按数据流的方向又可将I2C设备分为发送器或接收器。常用的数据传输模式主要有两种:主机发送模式,此时主机为发送器,从机为接收器;主机接收模式,此时主机为接收器,从机为发送器。一个设备是发送器还是接收器,取决于实际数据流的方向。一个完整的主机读或写过程称为一个消息,每一个消息都必须有一个起始信号(S)来指示其开始,起始信号由主机发出。在SCL线是高电平时SDA线从高电平向低电平切换,这个情况表示起始条件。如果一个I2C通信过程是主机多个读写过程的组合,则要有多个消息,需重复发出起始信号。在每个消息中,主机发出起始信号后都要接着发送从机地址字节,这个字节前7位代表从设备物理地址,最低位R/W决定了数据流的方向,如果是0,表示主机写数据到从机,1表示主机向从机读。发送到SDA总线上的数据必须是8位,但是每次发送的字节数不受限制。数据传输必须带应答(ACK),应答脉冲由接收器产生,在应答的时钟脉冲期间,发送器释放SDA线。通常被寻址的接收器在接收到每个字节后,必须产生一个应答,才能正常通信。最后,需要由主机发出一个停止信号,结束整个通信过程,使总线回到空闲状态,当SCL是高电平时SDA线由低电平向高电平切换表示停止条件。基本I2C总线时序如图1所示。

图1 基本I 2 C总线时序

3 主机适配器及基本I 2C时序的实现

3.1 S3C2440的I 2C适配器

S3C2440中I2C适配器中的寄存器主要有IICDS、ICSTAT、IICCON、IICADD等。IICDS寄存器为一个8位的移位寄存器,待发的数据先送至此寄存器,在起始信号发出后,将数据逐位发送到SDA总线上。

IICSTAT为状态寄存器,主要实现I2C总线的信号发生功能,如下所示。其中第6、7位是模式选择位,可决定4种模式,分别是主机发送、主机接收、从机发送、从机接收等。第5位是一个读写位,在读时如果为0表明总线空闲,如果为1表明总线正忙。如果向其写1,则主机将会发送开始信号,如果向其写0,则主机将发送停止信号。

模式选择忙、停止、起始状态输出允许 仲裁位 从片地址状态地址零状态最后接收位7∶6 5 4 3 2 1 0

IICCON为一个8位寄存器,主要实现I2C总线的一些配置功能,如下所示。应答设置位控制是否应答,低4位和第6位共同决定了发送时钟的频率。

应答设置发送时钟源选择发送/接收中断中断挂起标志传输时钟选择7 6 5 4 3∶0

3.2 I 2C基本时序的实现

I2C的时序及操作模式都可通过配置主机适配器的方式实现,I2C的基本时序包括起始信号、从机地址、发送数据、读数据、应答信号、停止信号等。操作模式主要包括主机读、主机写、从机读、从机写等。以此为基础,可以通过在总线上组合传输起始信号、地址信号、停止信号等,来实现任意复杂的I2C通信功能。

操作模式:通过写IICSTAT寄存器的高两位操作设置。

起始信号:向IICSTAT寄存器的第5位写1后,将会在总线上发出一个起始信号。

从机地址:这个从机地址需要在发起始信号前写入移位寄存器IICADD中去。IICADD物理地址为0x54000008,8位,高7位保存地址,最低位R/W为读写控制位。

应答信号:由接收器在接到发送器发送的地址或有效数据后发出,如果接收器配置为允许应答,则收到数据后将自动应答,应答设置位在IICCON的最高位,写1为允许应答,写0为禁止应答。

主机发送数据:待发送的数据需事先写入IICDS寄存器中,当发送条件满足后(起始信号发出,或TX/RX中断标志位清除后等),IICDS中的数据将自动移位发送。

主机接收数据:在收到总线上的一字节数据后,将存储于IICDS中。主机可通过查询IICCON中的中断标志位来确定是否接收成功一个字节。如果主机不发送应答信号,则从机将一直处于等待状态。数据接收完毕后如果不清除中断挂起位,I2C通信将进入暂停状态。

停止信号:停止信号的发出由IICSTAT寄存器的第5位清零来实现。

4 Linux下在适配器层中驱动的实现

下文结合LM75传感器采集温度的例子具体说明这种方法在Linux下的实现过程。

4.1 LM75传感器简介

LM75为支持I2C协议的数字式温度传感器,可多达8个传感器共享一根总线,可在环境超过设定温度时通知主控制器,测温精度为0.5℃,转换后的温度值用2字节保存。LM75的温度字节读取时序如图2所示。

4.2 LM75的适配器层驱动程序实现

可以在Linux底层驱动中对I2C寄存器组进行直接操作,根据LM75的时序要求组合I2C基本时序,实现LM75的模式设置及温度采集功能,程序流程如图3所示。

以下是在适配器层的部分驱动函数代码:

图2 LM75的温度字节读取时序

图3 LM75时序的底层实现流程

4.3 适配器层与应用层接口

在驱动函数完成后还要在适配器层填充一个file_operations的数据结构,由于用户空间不能直接调用适配器层中的函数,驱动函数需要映射为应用层的函数,这个数据结构提供了驱动层函数在应用层的函数接口。

适配器层驱动函数iic_LM75_read被映射为应用层的接口函数read,以为应用层所调用。按上述方法构建的I2C驱动在Linux下以普通设备驱动的形式加载,在加载的过程执行初始化操作,通过 MKDEV()函数创建主设备节点并分配设备号,通过I2C_setup_dev()函数实现驱动层到应用层函数的映射。在应用层调用适配器层驱动时,须首先用open()函数打开dev中的主设备,在open过程中配置各个I2C功能寄存器,配置输入/输出端口,完成后,将获得一个设备节点fd,以此节点作为驱动接口的设备参数传入,便可调用底层的驱动函数。

5 小 结

实践证明,在嵌入式Linux环境下,适配器层直接实现I2C设备驱动的方法,构造简单,可靠性高,占用资源少,对不同设备的适应性强,可有效提高I2C设备驱动开发的效率。

[1]I2C 总线规范[OL].[2011-01].www.zlgmcu.com/download/down.asp?ID=780.

[2]Samsung Electronics.S3C2440 32-BIT CMOS Microcontroller User's Manual Revision 1,2004.

[3]安森美半导体.LM75-2线串行温度传感器和监视器,2006.

[4]Jonathan Corbet,Alessandro Rubini,Greg Kroah-Hartman.Linux Device Drivers[M].3rd Edition.O'Reilly,2005.

[5]李俊.嵌入式Linux设备驱动开发详解[M].北京:人民邮电出版社,2008.

猜你喜欢

适配器接收器寄存器
STM32和51单片机寄存器映射原理异同分析
Lite寄存器模型的设计与实现
JXG-50S型相敏轨道电路接收器自动测试台
基于3D打印的轻型导弹适配器
电源适配器怎么选
新型二取二结构的25Hz微电子相敏接收器数据处理方法研究
基于蓝牙串口适配器的GPS接收机与AutoCAD的实时无线通信
美国麦格普公司新型M—LOK相机三脚架适配器
IDT推出超紧凑型无线电源接收器,可节省70%板面积
高速数模转换器AD9779/AD9788的应用