I2C设备驱动介绍
- 格式:ppt
- 大小:2.23 MB
- 文档页数:40
1、I2C概述I2C是philips公司提供的外设总线,I2C有两条数据线,一条是串行数据线SDA、一条是时钟线SCL,使用SDA和SCL实现了数据的交换,便于布线。
I2C总线方便用在EEPROM、实时钟、小型LCD等与CPU外部的接口上。
2、Linux下的驱动思路Linux系统下编写I2c驱动主要有两种方法:一种是把I2C当做普通字符设备来使用;另一种利用Linux下驱动的体系结构来实现。
第一种方法:优点:思路比较直接,不用花费大量时间去了解Linux系统下I2C体系结构缺点:不仅对I2C设备操作要了解,还有了解I2C的适配器操作不仅对I2C设备器和设备操作需要了解,编写的驱动移植性差,内核提供的I2C设备器都没有用上。
第二种方法:第一种的优点就是第二种的缺点,第一种的缺点就是第二种的优点。
3、I2C框架概述Linux的I2C体系结构分为3部分:1)I2C核心I2C核心提供了I2C总线驱动和设备驱动的注册和注销的方法,I2C 通信方法(algorithm)上层,与具体适配器无关的代码,检测设备上层的代码等。
2)I2C总线驱动I2C总线驱动是对I2C硬件体系结构中适配器端的实现,适配器可以直接受CPU来控制。
3)I2C设备驱动I2C设备驱动是对I2C硬件体系结构中设备端的实现,设备端挂在受CPU控制的适配器上,通过I2C适配器与CPU交换数据。
Linux下的I2C体系结构:1)Linux下的I2C体系结构4、I2C设备驱动编写方法首先让我们明白适配器驱动的作用是让我们能够通过它发出标准的I2C时序,在linux内核源代码中driver/I2C/buss包含一些适配器的驱动,例如s3c2410的驱动I2C-s3c2410.c,适配器被加载到内核中,接下的任务就是实现设备驱动的编写。
编写设备驱动的方法主要分为两种方法:第一种:利用设备提供的I2C-dev.c来实现I2C适配器设备文件,然后通过上层应用程序来操作I2C设备器来控制I2C设备。
详细讲解RT-Thread I2C设备驱动框架及相关函数本应用笔记以驱动I2C接口的6轴传感器MPU6050为例,说明了如何使用I2C设备驱动接口开发应用程序,并详细讲解了RT-Thread I2C设备驱动框架及相关函数。
1 本文的目的和结构1.1 本文的目的和背景I2C(或写作i2c、IIC、iic)总线是由Philips公司开发的一种简单、双向二线制(时钟SCL、数据SDA)同步串行总线。
它只需要两根线即可在连接于总线上的器件之间传送信息,是半导体芯片使用最为广泛的通信接口之一。
RT-Thread中引入了I2C设备驱动框架,I2C 设备驱动框架提供了基于GPIO模拟和硬件控制器的2种底层硬件接口。
1.2 本文的结构本文首先描述了RT-Thread I2C设备驱动框架的基本情况,然后详细描述了I2C设备驱动接口,并使用I2C设备驱动接口编写MPU6050的驱动程序,并给出了在正点原子STM32F4探索者开发板上验证的代码示例。
2 I2C设备驱动框架简介在使用MCU进行项目开发的时候,往往需要用到I2C总线。
一般来说,MCU带有I2C 控制器(硬件I2C),也可以使用MCU的2个GPIO自行编写程序模拟I2C总线协议实现同样的功能。
RT-Thread提供了一套I/O设备管理框架,它把I/O设备分成了三层进行处理:应用层、I/O 设备管理层、底层驱动。
I/O设备管理框架给上层应用提供了统一的设备操作接口和I2C 设备驱动接口,给下层提供的是底层驱动接口。
应用程序通过I/O设备模块提供的标准接口访问底层设备,底层设备的变更不会对上层应用产生影响,这种方式使得应用程序具有很好的可移植性,应用程序可以很方便的从一个MCU移植到另外一个MCU。
本文以6轴惯性传感器MPU6050为例,使用RT-Thread I2C设备驱动框架提供的GPIO模拟I2C控制器的方式,阐述了应用程序如何使用I2C设备驱动接口访问I2C设备。
I2C设备与驱动的关联作者:leeoo 联系方式:neu_linuxer@在Linux操作系统中,驱动程序的加载分为两种:内核启动时自动加载和用户手动加载;硬件设备也可以采用两种方式添加到系统中:在系统启动前及系统运行时的热插拨。
下面,我们以arm体系结构下的at91处理器中的I2C控制器为例,介绍一下硬件设备及相关的驱动程序是如何绑定及松绑的。
1.平台驱动注册过程1.1 at91_i2c_init()函数在文件drivers/i2c/busses/i2c-at91.c中,定义了结构体struct platform_driver并进行了初始化,通过使用module_init()宏进行声明,当模块被加载到内核时会调用 at91_i2c_init()函数。
在此函数中,调用了platform_driver_register()函数来完成注册。
static struct platform_driver at91_i2c_driver = {.probe = at91_i2c_probe,.remove = __devexit_p(at91_i2c_remove),.suspend = at91_i2c_suspend,.resume = at91_i2c_resume,.driver = {.name = "at91_i2c",.owner = THIS_MODULE,},};static int __init at91_i2c_init(void){return platform_driver_register(&at91_i2c_driver);}1.2 platform_driver_register()函数在文件drivers/base/platform.c中,实现并导出了platform_driver_register()函数,以便使其他模块中的函数可以调用此函数。
I2C驱动传入probe的参数解释在进行I2C设备的驱动开发过程中,常常会涉及到I2C驱动的probe 函数。
probe函数是Linux内核驱动中的一种特殊函数,它在驱动被加载并且设备被检测到时被调用,用于初始化设备并注册设备驱动。
在编写I2C驱动的probe函数时,通常需要传入不同的参数进行配置和初始化。
本文将对I2C驱动传入probe的参数进行解释和说明,帮助读者更好地理解和使用I2C设备驱动。
1. struct i2c_client *client在I2C驱动的probe函数中,通常需要传入一个指向structi2c_client结构体的指针作为参数。
这个结构体是I2C设备在内核中的表示,包含了I2C设备的位置区域、总线信息、驱动信息等。
通过这个参数,我们可以获取I2C设备的各种信息,并进行相应的初始化和配置。
2. const struct i2c_device_id *id另一个常见的参数是一个指向const struct i2c_device_id结构体的指针,用于指定要注册的设备驱动的ID信息。
这个结构体中通常包含了设备的厂商ID、设备类型、设备名称等信息,用于匹配加载指定的设备驱动。
在probe函数中,我们可以使用这个参数来判断当前检测到的I2C设备是否匹配当前的驱动,从而进行相应的初始化和注册操作。
3. int (*probe)(struct i2c_client *client, const struct i2c_device_id *id)最后一个重要的参数是probe函数本身。
这个参数是一个函数指针,用于指定实际的probe函数的位置区域。
在probe函数中,我们可以根据传入的client和id参数,进行设备的初始化、资源的申请、注册设备驱动等操作。
通过这个函数指针参数,内核可以在加载驱动并检测到设备时正确地调用对应的probe函数。
I2C驱动传入probe的参数包括指向I2C设备结构体的指针、指向设备ID信息的指针以及probe函数的函数指针。
TI-I2C驱动一、与I2C驱动相关的文件分成两部分:1)应用层接口部分:程序在svn中的路径如下:在https://dareglob-971006/svn/eocOS/branches/eocOS_v4/branches/bsp/user/i2c目录下,i2ctest.c文件,提供了lm75a_temp_read()方法,用来读取LM75A设备温度寄存器中的温度信息的功能。
2)内核驱动部分:内核位于svn中的路径如下:https://dareglob-971006/svn/eocOS/branches/eocOS_v4/branches/bsp/kernel(1)总线驱动:i2c-davinci.c:在内核目录中driver/i2c/busses目录下,适用于TI的I2C总线驱动程序。
I2C总线驱动是对I2C硬件体系结构中适配器端的实现。
(2)I2C驱动代码核心:i2c-core.c:在内核目录中driver/i2c/目录下,是I2C代码的核心,用于沟通虚拟文件系统与底层实现。
该文件提供了I2C总线驱动和设备驱动的注册、注销方法,I2C通信方法上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码等。
(3)I2C设备驱动:lm75.c:在内核目录中driver/hwmon目录下,是针对LM75A以及其他能兼容的温度传感器的设备驱动。
I2C设备驱动是对I2C硬件体系结构中设备端的实现,设备一般挂接在受CPU控制的I2C适配器上,通过I2C适配器与CPU交换数据。
二、I2C简要工作流程1)在总线驱动初始化时候,当通过Linux内核源代码/driver/base/platform.c文件中定义platform_driver_register()函数注册platform_driver结构体时,其中probe指针指向的davinci_i2c_probe()函数将被调用,以初始化适配器硬件。
2)而davinci_i2c_remove()函数则完成与davinci_i2c_probe()相反的功能。
1. 几个基本概念1.1. 设备模型由总线(bus_type)+ 设备(device)+ 驱动(device_driver)组成,在该模型下,所有的设备通过总线连接起来,即使有些设备没有连接到一根物理总线上,linux为其设置了一个内部的、虚拟的platform总线,用以维持总线、驱动、设备的关系。
因此,对于实现一个linux下的设备驱动,可以划分为两大步:1、设备注册;2、驱动注册。
当然,其中还有一些细节问题:1、驱动的probe函数2、驱动和设备是怎么进行绑定的。
1.2. i2c设备驱动的几个数据结构i2c_adapter:每一个i2c_adapter对应一个物理上的i2c控制器,在i2c总线驱动probe函数中动态创建。
通过i2c_add_adapter注册到i2c_core。
i2c_algorithm:i2c_algorithm中的关键函数master_xfer(),以i2c_msg为单位产生i2c访问需要的信号。
不同的平台所对应的master_xfer()是不同的,需要根据所用平台的硬件特性实现自己的xxx_xfer()方法以填充i2c_algorithm的master_xfer指针;在A31上即是sun6i_i2c_algorithm函数。
i2c_client:代表一个挂载到i2c总线上的i2c从设备,包含该设备所需要的数据:该i2c从设备所依附的i2c控制器 struct i2c_adapter *adapter该i2c从设备的驱动程序struct i2c_driver *driver该i2c从设备的访问地址addr, name该i2c从设备的名称name。
2. i2c总线驱动2.1. 功能划分从硬件功能上可划分为:i2c控制器和i2c外设(从设备)。
每个i2c控制器总线上都可以挂载多个i2c外设。
Linux中对i2c控制器和外设分开管理:通过i2c-sun6i.c 文件完成了i2c控制器的设备注册和驱动注册;通过i2c-core.c为具体的i2c外设提供了统一的设备注册接口和驱动注册接口,它分离了设备驱动device driver和硬件控制的实现细节(如操作i2c的寄存器)。
I2C设备驱动介绍I2C(Inter-Integrated Circuit)是一种串行通信协议,用于连接并使多个外部设备与主控制器进行通信。
在嵌入式系统中,I2C设备驱动起着至关重要的作用,负责将操作系统与I2C总线上的设备进行通信,促进数据的传输和交互。
1.初始化:驱动程序需要初始化I2C控制器,包括设置时钟频率、地址范围等。
2.设备注册:设备驱动需要在操作系统中注册I2C设备,以便操作系统能够识别和管理设备。
3.读写操作:驱动程序需要实现读写设备寄存器的功能,包括发送开始和停止信号、以及发送、接收数据等。
4.错误处理:驱动程序需要处理I2C通信过程中可能出现的错误,例如传输失败、设备无响应等情况。
5.中断处理:驱动程序需要支持I2C设备的中断机制,以便及时处理设备的状态变化或数据传输完成的中断信号。
6.电源管理:驱动程序需要支持设备的电源管理功能,包括设备的唤醒、睡眠等操作。
7.设备控制:驱动程序需要实现设备特定的控制功能,例如设置传感器的采样率、配置设备的工作模式等。
8. 虚拟文件系统接口:在Linux系统中,驱动程序通常通过虚拟文件系统接口(如/dev)与用户空间进行交互,提供读写设备寄存器的功能。
1.确定设备:首先,开发者应该确定需要驱动的I2C设备。
这可能包括传感器、EEPROM、显示器等。
2.确定硬件连接:确定I2C设备与主控制器之间的硬件连接和电气特性。
这包括设备的I2C地址、I2C总线上的物理接口等。
3.编写驱动程序:在操作系统中,开发者可以根据设备的文档或芯片厂商提供的驱动程序框架,编写自己的I2C设备驱动程序。
驱动程序需要实现上述提到的功能,并且根据设备的特点进行相应的适配和优化。
4.编译和测试:完成驱动程序的编写后,需要将其编译成与操作系统内核匹配的模块或静态链接库。
然后,通过加载驱动模块或重新编译内核来使驱动程序生效。
最后,进行测试,确保驱动程序在各种场景下的正常运行。
Linux I2C设备驱动编写(一)在Linux驱动中I2C系统中主要包含以下几个成员:如果一个I2C适配器不支持I2C通道,那么就将master_xfer成员设为NULL。
如果适配器支持SMBUS 协议,那么需要去实现smbus_xfer,如果smbus_xfer指针被设为NULL,那么当使用SMBUS协议的时候将会通过I2C通道进行仿真。
master_xfer指向的函数的返回值应该是已经成功处理的消息数,或者返回负数表示出错了。
functionality指针很简单,告诉询问着这个I2C主控器都支持什么功能。
在内核的drivers/i2c/i2c-stub.c中实现了一个i2c adapter的例子,其中实现的是更为复杂的SMBUS。
SMBus 与I2C的区别通常情况下,I2C和SMBus是兼容的,但是还是有些微妙的区别的。
时钟速度对比:在电气特性上他们也有所不同,SMBus要求的电压范围更低。
I2C driver具体的I2C设备驱动,如相机、传感器、触摸屏、背光控制器常见硬件设备大多都有或都是通过I2C 协议与主机进行数据传输、控制。
结构体如下:如同普通设备的驱动能够驱动多个设备一样,一个I2C driver也可以对应多个I2C client。
以重力传感器AXLL34X为例,其实现的I2C驱动为:这里要说明一下module_i2c_driver宏定义(i2c.h):module_driver():理解上述宏定义后,将module_i2c_driver(adxl34x_driver)展开就可以得到:这一句宏就解决了模块module安装卸载的复杂代码。
这样驱动开发者在实现I2C驱动时只要将i2c_driver结构体填充进来就可以了,无需关心设备的注册与反注册过程。
I2C client即I2C设备。
I2C设备的注册一般在板级代码中,在解析实例前还是先熟悉几个定义:下面还是以adxl34x为例:这样ADXL34X的i2c设备就被注册到了系统中,当名字与i2c_driver中的id_table中的成员匹配时就能够出发probe匹配函数了。
I2C设备驱动介绍I2C(Inter-Integrated Circuit)是一种简单的串行通信协议,用于在微控制器和外部设备之间传输数据。
它是由飞利浦公司(现在的恩智浦)于1982年推出的,现在已成为一种广泛应用的通信接口。
总线驱动是与I2C总线硬件相关的组件,它负责控制总线的时钟频率和数据传输速度。
它还提供了与硬件相关的函数,如初始化总线、发送数据和接收数据。
设备驱动是与特定设备相关的组件,它负责控制设备的初始化和配置,并提供与设备相关的功能函数。
设备驱动还负责将数据从总线读取到设备或从设备写入总线。
用户接口是设备驱动和应用程序之间的接口,通常是通过设备文件或命令行界面实现的。
用户接口提供了一组API函数,允许应用程序通过设备驱动与I2C设备进行通信。
1.初始化:驱动程序负责初始化I2C总线和设备,包括设置速率、地址和模式等。
2.读操作:驱动程序负责从设备读取数据,并将其传输到应用程序。
它可以使用主动读取或中断读取的方式来获取数据。
3.写操作:驱动程序负责将数据从应用程序写入设备,并通过I2C总线将其传输。
它可以使用主动写入或中断写入的方式发送数据。
4.错误处理:驱动程序需要能够检测和处理I2C传输中的错误,例如总线冲突、超时和校验错误等。
5.设备控制:驱动程序提供了控制设备状态和功能的功能函数。
6.多设备支持:驱动程序可以支持多个I2C设备,并提供适当的接口来选择和操作特定的设备。
1.可移植性:驱动程序应该是可移植的,适用于不同的硬件平台和操作系统。
2.灵活性:驱动程序应该具有足够的灵活性,以允许根据不同的应用需求进行配置和定制。
3.可靠性:驱动程序应该能够处理各种异常情况,并提供合适的错误处理机制。
4.性能:驱动程序应该能够实现高速数据传输,并尽可能减少处理延迟。
5.易用性:驱动程序应该提供简单易用的接口,以便应用程序能够方便地使用和控制I2C设备。
总之,I2C设备驱动是控制和管理I2C设备的关键组成部分。