I2C设备驱动介绍
Linux下I2C驱动介绍
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设备驱动框架及相关函数
详细讲解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设备与驱动的关联
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驱动传入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驱动
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()相反的功能。
全志公司对i2c的讲解
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设备驱动介绍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.编译和测试:完成驱动程序的编写后,需要将其编译成与操作系统内核匹配的模块或静态链接库。
然后,通过加载驱动模块或重新编译内核来使驱动程序生效。
最后,进行测试,确保驱动程序在各种场景下的正常运行。
I2C总线性能介绍(疑问解答)二
I2C总线的传输速度有多高它的数据完整性和安全性如何
[答:Bruce]
I2C总线理论上传输速度可以为100KHz(标准)、400KHz(快速)和(高速)。目前还没有成熟的速率的产品。I2C总线是板内总线,总线内部有地址管理和仲裁机制,在总线容量、slave地址等技术指标正确的情况下,数据的完整性和安全性是有保证的
I2C的layout时,对线长、线宽、线距有没有要求
[答:Timothy]
Just remember the max C value on the bus is 400pf.
[问:applebig]
PCA9512对正在使用状态的器件拔出时有什么保护吗比如主发状态的期间拔出时,由谁来发出stop信号
[答:Paul]
[答:Paul]
I2C protocol define each chip one unique slaveif you communicate to several identical ICs, I2C address should be different.If not, the same address ICs will be replied at the same time.
[问:qihong]
请问lpc系列单片机的iic接口是否支持热插拔
[答:Alex]
不支持,I2C总线上的热插拔需要专门的器件支持,比如PCA9511
[问:chenhezhi]
I2C总线在连续写EEPROM时容易出现什么问题,100K的传输速率。
[答:Alex问:david_liao]
I2C总线为同步总线,对抖动性能没有要求
[问:zmyf]
请问高速I2C一般使用多少的波特率呢我们一般使用80K/100Kbits/S,有最优值吗
Linux I2C设备驱动编写
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设备驱动介绍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设备的关键组成部分。
LinuxI2C驱动整理(以RK3399Pro+Kernel4.4为例)
LinuxI2C驱动整理(以RK3399Pro+Kernel4.4为例)⼀. Linux I2C驱动架构Linux内核⾥,I2C驱动框架可以分为两层,adapter驱动和deivce驱动。
Adapter驱动也可以理解为I2C总线驱动,指的是SOC⾥的I2C控制器驱动。
⼀个SOC可能包含多个I2C控制器,⽽每个控制器的使⽤⽅式是相同的(寄存器参数、收发数据的⽅法等),因此多个控制器可以共⽤⼀套adapter驱动;Deivce驱动,对应的是SOC外围的I2C设备,不同类型I2C设备需要开发不同的设备驱动,同⼀类型的I2C设备可以使⽤⼀种驱动,但是每⼀个I2C设备都由⼀个唯⼀的client来描述。
⼆. Adapter配置DTSI⽂件(kernel/arch/arm64/boot/dts/rockchip/rk3399.dtsi)描述了RK3399Pro所有的I2C控制器信息:i2c0: i2c@ff3c0000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff3c00000x00x1000>;clocks = <&pmucru SCLK_I2C0_PMU>, <&pmucru PCLK_I2C0_PMU>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c0_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c1: i2c@ff110000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1100000x00x1000>;clocks = <&cru SCLK_I2C1>, <&cru PCLK_I2C1>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c1_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c2: i2c@ff120000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1200000x00x1000>;clocks = <&cru SCLK_I2C2>, <&cru PCLK_I2C2>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c2_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c3: i2c@ff130000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1300000x00x1000>;clocks = <&cru SCLK_I2C3>, <&cru PCLK_I2C3>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c3_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c5: i2c@ff140000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1400000x00x1000>;clocks = <&cru SCLK_I2C5>, <&cru PCLK_I2C5>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c5_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c6: i2c@ff150000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1500000x00x1000>;clocks = <&cru SCLK_I2C6>, <&cru PCLK_I2C6>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c6_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c7: i2c@ff160000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff1600000x00x1000>;clocks = <&cru SCLK_I2C7>, <&cru PCLK_I2C7>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c7_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c4: i2c@ff3d0000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff3d00000x00x1000>;clocks = <&pmucru SCLK_I2C4_PMU>, <&pmucru PCLK_I2C4_PMU>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c4_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};i2c8: i2c@ff3e0000 {compatible = "rockchip,rk3399-i2c";reg = <0x00xff3e00000x00x1000>;clocks = <&pmucru SCLK_I2C8_PMU>, <&pmucru PCLK_I2C8_PMU>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH 0>;pinctrl-names = "default";pinctrl-0 = <&i2c8_xfer>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};可以看出,该SOC共有9个I2C控制器,分别为I2C0~I2C8, 每个控制器对应了不同的寄存器基地址(例如I2C0对应0xff3c0000),它们的compatible匹配属性都是"rockchip,rk3399-i2c",也就是对应了同⼀个adapter驱动。
AN0003+RT-Thread应用笔记之I2C设备应用指南
图4.2.1-1 发送数据函数调用关系
drv_mpu6050.c 中的 mpu6050_write_reg() 函数是MCU向mpu6050寄存器写数据。此函数的实现共有2种,分别 调用了I2C设备驱动接口 rt_i2c_transfer() 和 rt_i2c_master_send() 实现。
图3.2-2 修改MCU 图3.2-3 修改调试选项
5. 编译工程后下载程序至开发板运行。在终端PuTTY(打开对应端口,波特率配置为115200)输入 list_device 命令可以看到名为i2c2的设备,设备类型是I2C Bus,说明I2C设备驱动添加成功了。如图所示:
图3.2-4使用list_device命令查看i2c总线
1. 用户可以在msh shell输入 list_device 命令查看已有的I2C设备,确定I2C设备名称。 2. 查找设备使用 rt_i2c_bus_device_find() 或者 rt_device_find() ,传入I2C设备名称获取i2c总线设备句
柄。 3. 使用 rt_i2c_transfer() 即可以发送数据也可以接收数据,如果主机只发送数据可以使用
3.3 运行示例代码
将I2C示例代码里的 main.c 拷贝到\rt-thread\bsp\stm32f4xx-HAL\applications目录,替换原有的 main.c 。 drv_mpu6050.c、drv_mpu6050.h 拷贝到\rt-thread\bsp\stm32f4xx-HAL\drivers目录,并将它们添加到工程中对应 分组。如图所示:
i2c 波特率设备树配置
i2c 波特率设备树配置I2C(Inter-Integrated Circuit)是一种串行通信协议,常用于连接微控制器、传感器和其他外设。
在Linux设备驱动开发中,设备树(Device Tree)用于描述硬件设备的配置信息,包括I2C设备的连接和配置方式。
本文将介绍如何在设备树中配置I2C设备的波特率。
首先,在设备树中配置I2C设备的波特率之前,需要确认设备所支持的波特率范围。
通常,I2C的标准模式下的波特率为100kHz,快速模式下为400kHz,超高速模式可以达到1MHz以上。
选择合适的波特率取决于设备的支持能力和通信的需求。
设备树中的I2C设备节点通常由以下属性描述:1. compatible属性:用于匹配I2C设备的驱动程序。
例如,对于I2C总线控制器,可以使用属性"compatible = "i2c-omap";"来匹配OMAP平台的I2C驱动程序。
2. reg属性:指定I2C设备的物理地址、起始地址和地址长度。
例如,对于一个I2C设备的物理地址为0x68,可以使用属性"reg = <0x68>;"来指定。
3. interrupts属性:指定中断号或中断控制器的引脚。
对于I2C设备来说,通常不会使用中断,所以可以为空。
4. clocks属性:指定设备所需的时钟源。
I2C设备通常需要一个时钟源来控制数据传输的速率,可以使用属性"clocks =<&i2c_clk>;"来指定i2c_clk时钟源。
5. dmas属性:指定设备所需的DMA控制器。
对于I2C设备来说,通常不会使用DMA传输,所以可以为空。
配置I2C设备的波特率主要涉及到时钟频率的配置。
在设备树中,可以配置时钟源和分频因子来达到所需的波特率。
例如,对于I2C总线控制器,可以使用属性"clock-frequency =<100000>;"来配置为100kHz的波特率。
rk linux下i2c总线驱动读写原理
RK Linux下I2C总线驱动读写原理RK Linux,一个开源的、强大的、可定制的操作系统,广泛应用于各种嵌入式系统。
I2C总线是一种常用的通信协议,常用于连接低速外围设备,如传感器、EEPROM等。
在RK Linux下,I2C总线驱动的读写原理是什么呢?首先,我们来了解下I2C总线的基本概念。
I2C总线是一种双线串行通信总线,由数据线SDA和时钟线SCL组成。
通过这两根线,多个设备可以在同一总线上进行通信。
每个设备都有一个唯一的地址,主机可以通过发送设备的地址来选择与之通信的设备。
在RK Linux下,I2C总线驱动的读写操作主要依赖于内核提供的API。
这些API 包括i2c_read()、i2c_write()等,它们提供了与I2C设备通信的接口。
那么,这些API是如何实现读写操作的呢?在内核中,I2C驱动程序负责管理I2C总线上所有的设备和它们的通信。
当需要从设备读取数据时,驱动程序首先会向设备发送读请求。
设备接收到请求后,会将数据写入SDA线。
驱动程序会持续监听SDA线,一旦接收到数据,就会将其保存并通知应用程序。
同样地,当需要向设备写入数据时,驱动程序会向设备发送写请求。
设备接收到请求后,会准备好接收数据。
驱动程序会将数据写入SDA线,设备接收到数据后,会将数据保存到内部寄存器中。
需要注意的是,I2C总线的读写操作都是通过驱动程序来完成的。
应用程序只需要调用内核提供的API即可与I2C设备进行通信。
这样设计的好处是应用程序可以专注于自己的业务逻辑,而不需要关心底层的通信细节。
同时,这也使得应用程序与具体的I2C设备无关,具有更好的可移植性和扩展性。
i2c,lcd usb驱动
----杨军(2012 年 4 月 5 日)一、 uboot 启动流程第一阶段启动流程: cpu/arm920t/start.S(汇编阶段)进入 SVC-->关闭看门狗-->关闭中断-->进入 cpu_init_crit()--->(临时设置栈指针 SP)-->调整 CPU 的频率 clock_init() -->把完整的 {初始化 CPU 和 SDRAM 1.刷新出去 I/D cache 2.关闭 MMU 和 cache(一定关闭数据 CACHE,指令 CACHE 无所谓) 3.调用 lowlevel_init}UBOOT 代码从 FLASH 搬移到 SDRAM 中 CopyCode2Ram() -->清除 BSS、设置堆栈-->跳入真正的 C 函数 start_armboot第二阶段启动流程:使能 I/D cache,配置 GPIO 端口【board_init()】 -->:注册倒计时定时器,初始化一个早期串口-->输出 UBOOT 第一条打印 -->NOR/NAND FLASH 初始化-->把环境参数读到 SDRAM-->建立设备管理链表-->重新初始化串口为全功能串口-->网卡初始化-->进入 main_loop()大循环 第一二两个阶段合到一起的描述(这个过程要求面试的时候直接能够说的出来): UBOOT 的启动流程:首先初始化 CPU(进 SVC,关看门狗,关中断,调整 CPU 频率)和 RAM(SDRAM 和 DDR 都需要初始化一次), 将 FLASH 上的 BUOOT拷贝到 RAM 中,清除 BSS 和设置堆栈指针,跳转到 C 函数,接着初始化外设(GPIO 口设置,串口初始化,完整功能的 FLASH,, 网卡初始化),进入一个大的循环检测用户是否有按键按下,如有按下: 停止倒计时,等待用户的后续输入;若 规定时间里面 没有按下,执行 bootcmd 所保存的指令(经常这时是加载内核),然后启动内核二、 内核启动过程head.S arch\arm\boot\Compressed(解压内核)—》head.S arch\arm\Kernel(初始化工作)—》head-common.S arch\arm\Kernel(start_kernel 执行内核) start_kernel() [init/main.c] //vmlinux 的第一个 C 函数 -->setup_arch() 处理 UBOOT 传递过来的 TAG 参数(内存其实位置和大小,bootgars) 把 bootargs 参数各项进行拆解(后续代码可以用__setup()接收参数,例如: __setup("init=", init_setup);) 建立 4KB/页的内存管理,丢弃之前 arch/arm/kernel/head.S 中建立的 1MB/段的内存映射关系-->console_init(); //VMLINUX 的第一行打印输出 -->rest_init()Rest_init()函数分析:内核压缩过程:三、 I2C 驱动Random Read 时序图Byte Write 时序图:I2C 协议:1. i2c 协议特点: ============================================================================================== 1.1 它是飞利浦公司生产的一种串口协议 1.2 1.3 它是两根线传输的 SDA,SCl 数据时钟线 两根线上必须要由上拉电阻1.4 1.5 1.6可以挂多个设备,采用的是主从模式 I2c 的时钟都是由主机产生的 半双工通信方式 (SPI 全双工的,四根线,串行的)1.7 速度问题,低速模式:100K/s 全速模式:400k/s 高速模式:3.4M/s (SPI 的速度一般在 10M 左右) 1.8 真正的多主机总线(解释)1.9 串行 8 位双向传输,先传高位再传低位I2C 驱动分析:四、 LCD 驱动TFT LCD 的 TTL 信号 信号名称 VSYNC HSYNC HCLK VD[23:0] LEND PWREN Framebuffer 概述: 用户可以将 FramBuffer 看成是显卡内存的一个映像,将其映射到进程地址空 间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。
Mini2440之i2c驱动(2)
I2C设备驱动介绍
盈量而知芯,方行天下
I2C子系统
盈量而知芯,方行天下
I2C子系统
在Linux内核源代码中的drivers目录下包含一个i2c目录,而在i2c目录下又包含如下文件和 文件夹: • i2c-core.c : 这个文件实现了I2C核心的功能以及/proc/bus/i2c*接口。 • i2c-dev.c : 实现了I2C适配器设备文件的功能,每一个I2C适配器都被分配一个设备。通过 适配器访问设备时的主设备号都为89,次设备号为0~255。应用程序通过 “i2c-%d” (i2c-0, i2c-1, ..., i2c-10, ...)文件名并使用文件操作接口open()、write()、read()、ioctl()和close()等来 访问这个设备。i2c-dev.c并没有针对特定的设备而设计,只是提供了通用的read()、write() 和ioctl()等接口,应用层可以借用这些接口访问挂接在适配器上的I2C设备的存储空间或寄 存器并控制I2C设备的工作方式。 • chips文件夹 : 这个目录中包含了一些特定的I2C设备驱动,如Dallas公司的DS1337实时钟 芯片、EPSON公司的RTC8564实时钟芯片和I2C接口的EEPROM驱动等。 • busses文件夹:这个文件中包含了一些I2C总线的驱动,如S3C2410的I2C控制器驱动为i2cs3c2410.c。 • algos文件夹 : 实现了一些I2C总线适配器的algorithm。 此外,内核中的i2c.h这个头文件对i2c_driver、i2c_client、i2c_adapter和i2c_algorithm这 4个数据结构进行了定义。理解这4个结构体的作用十分关键,分别给出了它们的定义。
I2C子系统
struct i2c_client { unsigned short flags; /* div., see below */ unsigned short addr; /* chip address - NOTE: 7bit */ /* addresses are stored in the */ /* _LOWER_ 7 bits */ char name[I2C_NAME_SIZE]; struct i2c_adapter *adapter; /* the adapter we sit on */ struct i2c_driver *driver; /* and our access routines */ struct device dev; /* the device structure */ int irq; /* irq issued by device */ struct list_head detected; };
I2C驱动E2PROM
I2C驱动E2PROM*By Neil Chiao ( neilchiao at ) 1、I2C总线原理I2C是一种常用的串行总线,由串行数据线SDA 和串线时钟线SCL组成。
系统的I2C模块分为I2C总线控制器和I2C设备。
I2C总线控制器是CPU提供的控制I2C总线接口,它控制I2C总线的协议、仲裁、时序。
I2C设备是指通过I2C总线与CPU相连的设备,如EEPROM。
使用I2C通信时必须指定主从设备。
一般来说,.I2C总线控制器被配置成主设备,与总线相连的I2C设备如AT24C02作为从设备。
1.1、IIC读写EEPROM 原理IIC总线的开始/停止信号如图1所示。
开始信号为:时钟信号线SCL为高电平,数据线SDA从高变低。
停止信号为:时钟信号线SCL为高电平,数据线SDA从低变高。
图1 IIC Start-Stop Signal 1.1.1 IIC总线Byte WriteIIC总线写数据分几种格式,如字节写和页写。
字节写传送格式如图2所示。
开始信号之后,总线开始发数据,第一个Byte是IIC的设备地址,第二个Byte是设备内的地址(如EEPROM中具体的某个物理地址),然后就是要传送的真正的数据DATA。
NOTE:IIC总线在传送每个Byte后,都会从IIC总线上的接收设备得到一个ACK信号来确认接收到了数据。
其中,第一个Byte的设备地址中,前7位是地址码,第8位是方向位(“0”为发送,“1”为接收)。
IIC的中断信号有:ACK,Start,Stop。
图2 IIC Byte Write Write功能的实际实现原理如图3所示:(1)设置GPIO的相关引脚为IIC输出;(2)设置IIC(打开ACK,打开IIC中断,设置CLK等);(3)设备地址赋给IICDS ,并设置IICSTAT,启动IIC发送设备地址出去;从而找到相应的设备即IIC总线上的EEPROM。
(4)第一个Byte的设备地址发送后,从EEPROM得到ACK信号,此信号触发中断;(5)在中断处理函数中把第二个Byte(设备内地址)发送出去;发送之后,接收到ACK 又触发中断;(6)中断处理函数把第三个Byte(真正的数据)发送到EEPROM中;(7)发送之后同样接收到ACK并触发中断,中断处理函数判断,发现数据传送完毕。
liquidcrystal_i2c 常用函数
liquidcrystal_i2c 常用函数(最新版)目录1.液体水晶 I2C 概述2.液体水晶 I2C 的常用函数3.函数的具体用法和功能正文【液体水晶 I2C 概述】液体水晶 I2C(Liquid Crystal I2C)是一种常用的液晶显示屏驱动方式。
I2C(Inter-Integrated Circuit)是一种串行通信总线,它是由Philips 公司(现在的 NXP 半导体公司)在 1980 年代开发的。
I2C 用于在微控制器(MCU)和周边设备(如液晶显示屏、存储器等)之间进行低速通信。
【液体水晶 I2C 的常用函数】在液体水晶 I2C 的驱动中,有许多常用的函数,这些函数可以实现对液晶显示屏的各种操作。
下面我们将介绍几个常用的函数:1.初始化函数:初始化函数主要用于初始化 I2C 通信,以及配置相关硬件。
在使用液体水晶 I2C 前,需要调用此函数进行初始化。
2.写函数:写函数用于将数据写入液晶显示屏。
通过此函数,可以实现对液晶显示屏的显示内容进行控制。
3.读函数:读函数用于从液晶显示屏读取数据。
通过此函数,可以获取液晶显示屏当前的显示内容。
4.清除屏幕函数:清除屏幕函数用于清空液晶显示屏的显示内容。
使用此函数,可以将液晶显示屏的显示内容全部清空。
5.显示字符串函数:显示字符串函数用于在液晶显示屏上显示字符串。
通过此函数,可以实现对液晶显示屏的显示内容进行动态更新。
【函数的具体用法和功能】下面我们将详细介绍上面提到的几个常用函数的具体用法和功能:1.初始化函数:在使用液体水晶 I2C 前,需要调用此函数进行初始化。
其一般用法如下:```cvoid LiquidCrystal_I2C_Init(void);```此函数的主要功能是初始化 I2C 通信,配置相关硬件,以及初始化显示缓冲区等。
2.写函数:写函数用于将数据写入液晶显示屏。
其一般用法如下:```cvoid LiquidCrystal_I2C_Write(unsigned char dat);```此函数的主要功能是将指定的数据写入液晶显示屏的指定位置。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
盈量而知芯,方行天下
I2C总线
盈量而知芯,方行天下
I2C总线
盈量而知芯,方行天下
I2C总线
盈量而知芯,方行天下
I2C总线
盈量而知芯,方行天下
I2C子系统
I2C子系统
盈量而知芯,方行天下
I2C子系统
为了方便i2c 设备驱动的开发,避免因为I2C 控制器的硬件差异而导致设备驱动的差异 性,linux 对I2C 总线进行了封装。为 I2C 设备、控制器、及驱动提供了统一的注册平台, 同时为数据传输提供了统一的接口。 I2C 总线作为一类抽象的总线模型,具体的通信由总线控制器 i2c_adapter 所提供的总 线驱动算法i2c_algorithm 来完成。与用户空间的交互由设备驱动完成,由 i2c-dev 结构维 护。i2c_driver 结构维护了一类设备的驱动方法,i2c_client 结构维护i2c 子系统中独立的i2c 设备。另外,设备只完成与I2C-core 的数据交互,不能与适配器直接通信,真正数据的传 输由i2c-core 调用相应的i2c 控制器完成。
盈量而知芯,方行天下
I2C子系统
struct i2c_adapter { struct module *owner; unsigned int id; unsigned int class; /* classes to allow probing for */ const struct i2c_algorithm *algo; /* the algorithm to access the bus */ void *algo_data; /* data fields that are valid for all devices */ struct rt_mutex bus_lock; int timeout; /* in jiffies */ int retries; struct device dev; /* the adapter device */ int nr; char name[48]; struct completion dev_released; struct list_head userspace_clients; };
盈量而知芯,方行天下
I2C设备驱动
● 构建i2c_driver static struct i2c_driver pca953x_driver = { .driver = { .name= "pca953x", }, .probe= pca953x_probe, //当有i2c_client和i2c_driver匹配时调用 .remove= pca953x_remove,//注销时调用 .id_table= pca953x_id,//匹配规则 }; ● 注册i2c_driver static int __init pca953x_init(void) { return i2c_add_driver(&pca953x_driver); } module_init(pca953x_init);
盈量而知芯,方行天下
I2C设备驱动
I2C设备驱动
盈量而知芯,方行天下
I2C设备驱动
编写I2C设备驱动有两种方法。一种是利用系统给i2c-dev.c来实现一个i2c适配器的设 备文件,然后通过在应用层操作i2c适配器来控制i2c设备。 另一种是为i2c设备,独立编写一个设备驱动。在这种情况下,是不需要使用i2c-dev.c 的。通常我们为i2c设备在内核层编写驱动程序。 目前内核支持两种编写i2c驱动程序的方式,分别称这两种方式为“Adapter方式 (LEGACY)”和“Probe方式(new style)”。两者流程上基本相似,而前者属于旧式驱 动开发方式,就不作讨论。这里关注现在流行使用的Probe方式。
盈量而知芯,方行天下
I2C子系统
Linux的I2C体系结构分为3个组成部分: • I2C核心 I2C 核心提供了I2C总线驱动和设备驱动的注册、注销方法,I2C通信方法(即 “algorithm”)上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代 码等。 • I2C总线驱动 I2C总线驱动是对I2C硬件体系结构中适配器端的实现,适配器可由CPU控制,甚至直 接集成在CPU内部。 I2C总线驱动主要包含了I2C适配器数据结构i2c_adapter、I2C适配器的algorithm数据结 构i2c_algorithm和控制I2C适配器产生通信信号的函数。 经由I2C总线驱动的代码,我们可以控制I2C适配器以主控方式产生开始位、停止位、 读写周期,以及以从设备方式被读写、产生ACK等。 • I2C设备驱动 I2C设备驱动是对I2C硬件体系结构中设备端的实现,设备一般挂接在受CPU控制的I2C 适配器上,通过I2C适配器与CPU交换数据。 I2C设备驱动主要包含了数据结构i2c_driver和i2c_client,我们需要根据具体设备实现 其中的成员函数。
盈量而知芯,方行天下
I2C子系统
盈量而知芯,方行天下
I2C子系统
在Linux内核源代码中的drivers目录下包含一个i2c目录,而在i2c目录下又包含如下文件和 文件夹: • i2c-core.c : 这个文件实现了I2C核心的功能以及/proc/bus/i2c*接口。 • i2c-dev.c : 实现了I2C适配器设备文件的功能,每一个I2C适配器都被分配一个设备。通过 适配器访问设备时的主设备号都为89,次设备号为0~255。应用程序通过 “i2c-%d” (i2c-0, i2c-1, ..., i2c-10, ...)文件名并使用文件操作接口open()、write()、read()、ioctl()和close()等来 访问这个设备。i2c-dev.c并没有针对特定的设备而设计,只是提供了通用的read()、write() 和ioctl()等接口,应用层可以借用这些接口访问挂接在适配器上的I2C设备的存储空间或寄 存器并控制I2C设备的工作方式。 • chips文件夹 : 这个目录中包含了一些特定的I2C设备驱动,如Dallas公司的DS1337实时钟 芯片、EPSON公司的RTC8564实时钟芯片和I2C接口的EEPROM驱动等。 • busses文件夹:这个文件中包含了一些I2C总线的驱动,如S3C2410的I2C控制器驱动为i2cs3c2410.c。 • algos文件夹 : 实现了一些I2C总线适配器的algorithm。 此外,内核中的i2c.h这个头文件对i2c_driver、i2c_client、i2c_adapter和i2c_algorithm这 4个数据结构进行了定义。理解这4个结构体的作用十分关键,分别给出了它们的定义。
Jiawen.Liang
Shanghai Info TM Microelectronics Co., Ltd.
目录
一.I2C总线
二.I2C子系统
三.I2C设备驱动盈量而知芯,方行天下 Nhomakorabea2C总线
I2C总线
I2C总线
I2C总线
盈量而知芯,方行天下
I2C总线
I2C(Inter-Integrated Circuit)总线是由PHILIPS公司开发的两线式串行总线,用 于连接微控制器及其外围设备,是微电子通信控制领域广泛采用的一种总线标准。 它是同步通信的一种特殊形式,具有接口线少,控制方式简单,器件封装形式小, 通信速率较高等优点。 I2C 总线支持任何IC 生产过程(NMOS CMOS、双极性)。两线――串行数据(SDA) 和串行时钟 (SCL)线在连接到总线的器件间传递信息。每个器件都有一个唯一的地 址识别(无论是微控制器——MCU、LCD 驱动器、存储器或键盘接口),而且都可以 作为一个发送器或接收器(由器件的功能决定)。很明显,LCD 驱动器只是一个接 收器,而存储器则既可以接收又可以发送数据。主机是初始化总线的数据传输并产 生允许传输的时钟信号 的器件;MCU一般作为主机,而其他与其连接的外设都被认 为是从机。
盈量而知芯,方行天下
I2C子系统
struct i2c_driver { unsigned int class; int (*attach_adapter)(struct i2c_adapter *); int (*detach_adapter)(struct i2c_adapter *); /* Standard driver model interfaces */ int (*probe)(struct i2c_client *, const struct i2c_device_id *); int (*remove)(struct i2c_client *); /* driver model interfaces that don't relate to enumeration */ void (*shutdown)(struct i2c_client *); int (*suspend)(struct i2c_client *, pm_message_t mesg); int (*resume)(struct i2c_client *); void (*alert)(struct i2c_client *, unsigned int data); int (*command)(struct i2c_client *client, unsigned int cmd, void *arg); struct device_driver driver; const struct i2c_device_id *id_table; /* Device detection callback for automatic device creation */ int (*detect)(struct i2c_client *, struct i2c_board_info *); const unsigned short *address_list; struct list_head clients; }; 盈量而知芯,方行天下