I²C总线仅使用SCL,SDA两根讯号线实现设备间的数据交互,被广泛应用于微控制领域芯片与芯片之间的通讯,如EEPROMlinux i2c 驱动,实时时钟,大型LCD等与CPU之间的通讯。
I2C合同
I2C借助两根总线按照自己的通讯合同实现数据交互
起始讯号:当SCL为高期间,SDA由高到低的跳变;启动讯号是一种电平跳变时序讯号,而不是一个电平讯号。
停止讯号:当SCL为高期间,SDA由低到高的跳变;停止讯号也是一种电平跳变时序讯号,而不是一个电平讯号。
ACK应答讯号:发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答讯号。应答讯号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器早已成功地接收了该字节;应答讯号为高电平时,规定为非应答位(NACK),通常表示接收器接收该字节没有成功。对于反馈有效应答位ACK的要求是,接收器在第9个时钟脉冲之前的低电平期间将SDA线拉低,但是确保在该时钟的高电平期间为稳定的低电平。假如接收器是主控器,则在它收到最后一个字节后,发送一个NACK讯号,以通知被控发送器结束数据发送,并释放SDA线,便于主控接收器发送一个停止讯号P。
以上就是I2C的时序,在单片机上用到I2C我们须要自己写时序,但是在LinuxI2C中我们不须要自己写时序linux i2c 驱动,内核早已帮我们实现。
LinuxI2C构架层次
第一层:提供i2cadapter的硬件驱动,侦测、初始化i2cadapter(如申请i2c的io地址和中断号),驱动soc控制的i2cadapter在硬件上形成讯号(start、stop、ack)以及处理i2c中断。覆盖图中的硬件实现层
第二层:提供i2cadapter的algorithm,用具体适配器的xxx_xferf()函数来填充i2c_algorithm的master_xfer函数表针,并把形参后的i2c_algorithm再形参给i2c_adapter的algo表针。覆盖图中的访问具象层、i2c核心层
第三层:实现i2c设备驱动中的i2c_driver插口,用具体的i2cdevice设备的attach_adapter()、detach_adapter()方式形参给i2c_driver的成员函数表针。实现设备device与总线(或则叫adapter)的挂接。覆盖图中的driver驱动层
第四层:实现i2c设备所对应的具体device的驱动,i2c_driver只是实现设备与总线的挂接,而挂接在总线上的设备则是千差万别的,所以要实现具体设备device的write()、read()、ioctl()等方式,形参给file_operations,之后注册字符设备(多数是字符设备)。覆盖图中的driver驱动层
第一层和第二层又叫i2c总线驱动(bus),第三第四属于i2c设备驱动(devicedriver)。
在linux驱动构架中,几乎不须要驱动开发人员再添加bus,由于linux内核几乎集成所有总线bus,如usb、pci、i2c等等。而且总线bus中的(与特定硬件相关的代码)已由芯片提供商编撰完成,比如三星的s3c-2440平台i2c总线bus为/drivers/i2c/buses/i2c-s3c2410.c
LinuxI2C驱动结构
linux下I2C驱动体系结构包括I2C总线驱动linux命令大全,I2C核心linux mint,I2C从设备驱动三个部份。通常来说,假如CPU中集成了I2C控制器而且Linux内核支持这个CPU,这么总线驱动方面内核会帮我们实现。但若果CPU中没有I2C控制器,而是外接的话则须要我们自己实现I2C总线驱动。对于设备驱动来说,常用的设备驱动内核早已帮我们实现,同样,假如用到比较稀少的I2C设备,内核没有帮我们实现,则须要我们自己完成设备驱动的编撰。
*I2C总线驱动
2440中的I2C控制器有一个驱动(s3c2440中的I2C适配器驱动基于platform实现)。这个驱动拿来操作控制器来形成特定的I2C的时序讯号,来发送数据和接收数据。也就是让适配器工作。
*I2C设备驱动
挂接在I2C总线上的从设备AT2424CC0202(e2prom)为例,它也有一个驱动,这个拿来操作读写我们的芯片,读取和储存具体获得的数据。
*I2C核心
通过一系列的通讯方式(algorithm)把总线驱动,设备驱动与用户层串上去,其中还包括有总线驱动和设备驱动的注册,注销技巧。i2c-core.c实现i2c核心的功能以及/proc/bus/i2c*插口。
driver的I2C目录下的文件介绍
i2c-core.c为I2C驱动中的I2C核心,提供了一组不依赖于硬件平台的插口函数(/proc/bus/i2c*插口)作为I2C总线驱动和I2C设备驱动之间的纽带。如:
inti2c_add_adapter(structi2c_adapter*adapter)
inti2c_del_adapter(structi2c_adapter*adap)
inti2c_register_driver(structmodule*owner,structi2c_driver*driver)
voidi2c_del_driver(structi2c_driver*driver)
i2c-dev.c实现了I2C适配器设备文件的功能,每一个I2C适配器都被分配起码一个设备。通过适配器访设备时的主设备号都为89,次设备号为0-255。I2c-dev.c并没有针对特定的设备而设计,只是提供了通用的read(),write(),和ioctl()等插口,应用层可以借用这种插口访问挂接在适配器上的I2C设备的储存器或寄存器,并控制I2C设备的工作方法。
busses文件夹中包含了一些I2C总线的驱动,如针对S3C2410处理器的I2C控制器驱动为i2c-s3c2410.c。在该文件中,定义描述具体I2C总线适配器的i2c_adapter数据结构、实现在具体I2C适配器上的I2C总线通讯方式,并由i2c_algorithm数据结构进行描述。经过I2C总线驱动的的代码,可以为我们控制I2C形成开始位、停止位、读写周期以及从设备的读写、产生ACK等。
algos文件夹实现了一些I2C总线适配器的algorithm。
关于AT24C02
AT24C02的储存容量为2Kb(2048bit),内容分成32页,每页8Byte,共256Byte,操作时有两种轮询形式:芯片轮询和片内子地址轮询。
(1)芯片轮询:AT2424CC0202的芯片地址为1010,其地址控制字格式为1010A2A1A0R/W。其中A2,A1,A0可编程地址选择位。A2,A1,A0引脚接高、
低电平后得到确定的三位编码,与1010产生7位编码,即为该元件的地址码。R/W为芯片读写控制位,该位为0,表示芯片进行写操作。
(2)片内子地址轮询:芯片轮询可对内部256B中的任一个进行读/写操作,其轮询范围为00~FF,共256个轮询单位。
更改内核添加I2C支持
1.添加makemenuconfig
DeviceDrivers--->
I2Csupport--->
[*]Enablecompatibilitybitsforolduser-space
I2Cdeviceinterface
I2Cbusmultiplexingsupport
[*]Autoselectpertinenthelpermodules
I2CHardwareBussupport--->
[*]I2CCoredebuggingmessages
[*]I2CAlgorithmdebuggingmessages
[]I2CBusdebuggingmessages
[*]Miscdevices--->
EEPROMsupport--->
I2CEEPROMsfrommostvendors
SPIEEPROMsfrommostvendors
OldI2CEEPROMreader
MaximMAX6874/5powersupplysupervisor
EEPROM93CXCX6support
2.更改内核文件linux/arch/arm/mach-s3c2440/mach-smdk2440.c
添加如下代码:
#include/*添加头文件*/
staticstructat24_platform_dataat2424cc0202={
.byte_len=SZ_2K/8,
.page_size=8,
.flags=0,
staticstructi2c_board_info__initdatasmdk_i2c_devices[]={
/*moredevicescanbeaddedusingexpansionconnectors*/
I2C_BOARD_INFO("24c02",0x50),
.platform_data=&at24c02,
},
};
3./*在smdk2440_machine_init函数中降低如下:*/
i2c_register_board_info(0,smdk_i2c_devices,ARRAY_SIZE(smdk_i2c_devices));
测试EEPROM
对内核完成上述更改以后,重新编译内核并烧写到开发板运行。启动后步入
/sys/devices/platform/s3c2440-i2c/i2c-0/0-0050/进行以下测试:
本文永久更新地址: