嵌入式linux/鸿蒙开发板(IMX6ULL)开发(十九)I2C应用编程(中)

简介: 嵌入式linux/鸿蒙开发板(IMX6ULL)开发(十九)I2C应用编程

1.3.2 SMBus协议分析


对于I2C协议,它只定义了怎么传输数据,但是并没有定义数据的格式,这完全由设备来定义。

对于SMBus协议,它定义了几种数据格式。


注意:

下面文档中的Functionality flag是Linux的某个I2C控制器驱动所支持的功能。

比如Functionality flag: I2C_FUNC_SMBUS_QUICK,表示需要I2C控制器支持SMBus Quick Command

1 symbols(符号)
S     (1 bit) : Start bit(开始位)
Sr    (1 bit) : 重复的开始位
P     (1 bit) : Stop bit(停止位)
R/W#  (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0.(读写位)
A, N  (1 bit) : Accept and reverse accept bit.(回应位)
Address(7 bits): I2C 7 bit address. Note that this can be expanded as usual to
                get a 10 bit I2C address.
                (地址位,7位地址)
Command Code  (8 bits): Command byte, a data byte which often selects a register on
                the device.
                (命令字节,一般用来选择芯片内部的寄存器)
Data Byte (8 bits): A plain data byte. Sometimes, I write DataLow, DataHigh
                for 16 bit data.
                (数据字节,8位;如果是16位数据的话,用2个字节来表示:DataLow、DataHigh)
Count (8 bits): A data byte containing the length of a block operation.
    (在block操作总,表示数据长度)
[..]:           Data sent by I2C device, as opposed to data sent by the host
                adapter.
                (中括号表示I2C设备发送的数据,没有中括号表示host adapter发送的数据)


SMBus Quick Command

1670915196515.jpg

只是用来发送一位数据:R/W#本意是用来表示读或写,但是在SMBus里可以用来表示其他含义。

比如某些开关设备,可以根据这一位来决定是打开还是关闭。

Functionality flag: I2C_FUNC_SMBUS_QUICK

SMBus Receive Byte

1670915215040.jpg

I2C-tools中的函数:i2c_smbus_read_byte()。

读取一个字节,Host adapter接收到一个字节后不需要发出回应信号(上图中N表示不回应)。

Functionality flag: I2C_FUNC_SMBUS_READ_BYTE

SMBus Send Byte

1670915231922.jpg

I2C-tools中的函数:i2c_smbus_write_byte()。

发送一个字节。

Functionality flag: I2C_FUNC_SMBUS_WRITE_BYTE

SMBus Read Byte

1670915256909.jpg

I2C-tools中的函数:i2c_smbus_read_byte_data()。

先发出Command Code(它一般表示芯片内部的寄存器地址),再读取一个字节的数据。

上面介绍的SMBus Receive Byte是不发送Comand,直接读取数据。

Functionality flag: I2C_FUNC_SMBUS_READ_BYTE_DATA


SMBus Read Word

1670915277700.jpg

I2C-tools中的函数:i2c_smbus_read_word_data()。

先发出Command Code(它一般表示芯片内部的寄存器地址),再读取2个字节的数据。

Functionality flag: I2C_FUNC_SMBUS_READ_WORD_DATA


SMBus Write Byte

1670915293292.jpg

I2C-tools中的函数:i2c_smbus_write_byte_data()。

先发出Command Code(它一般表示芯片内部的寄存器地址),再发出1个字节的数据。

Functionality flag: I2C_FUNC_SMBUS_WRITE_BYTE_DATA

SMBus Write Word

1670915343397.jpg

I2C-tools中的函数:i2c_smbus_write_word_data()。

先发出Command Code(它一般表示芯片内部的寄存器地址),再发出1个字节的数据。

Functionality flag: I2C_FUNC_SMBUS_WRITE_WORD_DATA


SMBus Block Read

1670915357156.jpg

I2C-tools中的函数:i2c_smbus_read_block_data()。

先发出Command Code(它一般表示芯片内部的寄存器地址),再发起度操作:

 先读到一个字节(Block Count),表示后续要读的字节数

 然后读取全部数据

Functionality flag: I2C_FUNC_SMBUS_READ_BLOCK_DATA


SMBus Block Write

1670915371791.jpg

I2C-tools中的函数:i2c_smbus_write_block_data()。

先发出Command Code(它一般表示芯片内部的寄存器地址),再发出1个字节的Byte Conut(表示后续要发出的数据字节数),最后发出全部数据。

Functionality flag: I2C_FUNC_SMBUS_WRITE_BLOCK_DATA


I2C Block Read

1670915384516.jpg

在一般的I2C协议中,也可以连续读出多个字节。

它跟SMBus Block Read的差别在于设备发出的第1个数据不是长度N,如下图所示:


I2C-tools中的函数:i2c_smbus_read_i2c_block_data()。

先发出Command Code(它一般表示芯片内部的寄存器地址),再发出1个字节的Byte Conut(表示后续要发出的数据字节数),最后发出全部数据。

Functionality flag: I2C_FUNC_SMBUS_READ_I2C_BLOCK


I2C Block Write

1670915399775.jpg

在一般的I2C协议中,也可以连续发出多个字节。

它跟SMBus Block Write的差别在于发出的第1个数据不是长度N,如下图所示:


I2C-tools中的函数:i2c_smbus_write_i2c_block_data()。

先发出Command Code(它一般表示芯片内部的寄存器地址),再发出1个字节的Byte Conut(表示后续要发出的数据字节数),最后发出全部数据。

Functionality flag: I2C_FUNC_SMBUS_WRITE_I2C_BLOCK


SMBus Block Write - Block Read Process Call

1670915408648.jpg

先写一块数据,再读一块数据。

Functionality flag: I2C_FUNC_SMBUS_BLOCK_PROC_CALL


Packet Error Checking (PEC)


PEC是一种错误校验码,如果使用PEC,那么在P信号之前,数据发送方要发送一个字节的PEC码(它是CRC-8码)。

以SMBus Send Byte为例,下图中,一个未使用PEC,另一个使用PEC:

1670915431725.jpg


1.3.3 SMBus和I2C的建议


因为很多设备都实现了SMBus,而不是更宽泛的I2C协议,所以优先使用SMBus。

即使I2C控制器没有实现SMBus,软件方面也是可以使用I2C协议来模拟SMBus。

所以:Linux建议优先使用SMBus。


1.4. I2C系统的重要结构体


参考资料:

Linux驱动程序: drivers/i2c/i2c-dev.c

I2CTools: https://mirrors.edge.kernel.org/pub/software/utils/i2c-tools/


1.4.1. I2C硬件框架

1670915472175.jpg


1.4.2. I2C传输协议

1670915485121.jpg


1.4.3. Linux软件框架



1.4.4. 重要结构体


使用一句话概括I2C传输:APP通过I2C Controller与I2C Device传输数据。

在Linux中:

怎么表示I2C Controller

一个芯片里可能有多个I2C Controller,比如第0个、第1个、……

对于使用者,只要确定是第几个I2C Controller即可

使用i2c_adapter表示一个I2C BUS,或称为I2C Controller

里面有2个重要的成员:

nr:第几个I2C BUS(I2C Controller)

i2c_algorithm,里面有该I2C BUS的传输函数,用来收发I2C数据

i2c_adapter

1670915504680.jpg

i2c_algorithm

1670915516148.jpg


怎么表示I2C Device

一个I2C Device,一定有设备地址

它连接在哪个I2C Controller上,即对应的i2c_adapter是什么

使用i2c_client来表示一个I2C Device

1670915530713.jpg

怎么表示要传输的数据

在上面的i2c_algorithm结构体中可以看到要传输的数据被称为:i2c_msg


i2c_msg中的flags用来表示传输方向:bit 0等于I2C_M_RD表示读,bit 0等于0表示写

一个i2c_msg要么是读,要么是写

举例:设备地址为0x50的EEPROM,要读取它里面存储地址为0x10的一个字节,应该构造几

个i2c_msg?

要构造2个i2c_msg

第一个i2c_msg表示写操作,把要访问的存储地址0x10发给设备

第二个i2c_msg表示读操作

代码如下

u8 data_addr = 0x10;
i8 data;
struct i2c_msg msgs[2];
msgs[0].addr = 0x50;
msgs[0].flags = 0;
msgs[0].len = 1;
msgs[0].buf = &data_addr;
msgs[1].addr = 0x50;
msgs[1].flags = I2C_M_RD;
msgs[1].len = 1;
msgs[1].buf = &data;
相关文章
|
6月前
|
安全 应用服务中间件 网络安全
在Linux环境部署Flask应用并启用SSL/TLS安全协议
至此,你的Flask应用应该能够通过安全的HTTPS协议提供服务了。记得定期更新SSL证书,Certbot可以帮你自动更新证书。可以设定cronjob以实现这一点。
420 10
|
6月前
|
Java Linux 网络安全
Linux云端服务器上部署Spring Boot应用的教程。
此流程涉及Linux命令行操作、系统服务管理及网络安全知识,需要管理员权限以进行配置和服务管理。务必在一个测试环境中验证所有步骤,确保一切配置正确无误后,再将应用部署到生产环境中。也可以使用如Ansible、Chef等配置管理工具来自动化部署过程,提升效率和可靠性。
674 13
|
5月前
|
存储 数据采集 监控
ubuntu(linux)系统主要应用于哪些工业场景中?研维三防ubuntu系统的手持工业三防平板电脑在哪些行业中有实际应用
Ubuntu 系统凭借其独特的优势,在众多工业场景中得到了广泛应用,为工业数字化、智能化发展提供了有力支持。而研维三防基于 Ubuntu 定制系统的手持工业三防平板电脑,更是将 Ubuntu 系统的优势与工业级的性能、坚固耐用性完美结合,在电力、物流、制造等多个行业中展现出强大的应用价值,助力企业提高生产效率、优化管理流程、提升产品质量,成为推动工业现代化发展的重要力量。随着技术的不断进步与创新,相信 Ubuntu 系统以及研维三防这类工业级设备将在更多的工业领域中发挥更大的作用,为工业发展带来更多的机遇与变革。
|
11月前
|
机器学习/深度学习 安全 Linux
Linux 主要应用领域的归纳
服务器领域 Linux在服务器领域的应用是其最为广泛和成熟的领域之一。由于其开源、稳定、高效和安全的特性,Linux成为许多企业服务器的首选操作系统。 Web服务器:Linux是Web服务器的理想选择,因为它支持Apache、Nginx等流行的Web服务器软件,这些软件在Linux上运行稳定且性能卓越。Linux服务器可以高效地处理大量并发请求,提供快速、可靠的Web服务。 数据库服务器:Linux也广泛用于数据库服务器,如MySQL、PostgreSQL和Oracle等数据库管理系统在Linux上运行良好。Linux的稳定性和安全性使得它成为存储和管理敏感数据的理想平台。 邮件服务器:Lin
638 5
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
575 13
|
缓存 Linux 开发者
Linux内核中的并发控制机制:深入理解与应用####
【10月更文挑战第21天】 本文旨在为读者提供一个全面的指南,探讨Linux操作系统中用于实现多线程和进程间同步的关键技术——并发控制机制。通过剖析互斥锁、自旋锁、读写锁等核心概念及其在实际场景中的应用,本文将帮助开发者更好地理解和运用这些工具来构建高效且稳定的应用程序。 ####
280 5
|
存储 安全 关系型数据库
Linux系统在服务器领域的应用与优势###
本文深入探讨了Linux操作系统在服务器领域的广泛应用及其显著优势。通过分析其开源性、安全性、稳定性和高效性,揭示了为何Linux成为众多企业和开发者的首选服务器操作系统。文章还列举了Linux在服务器管理、性能优化和社区支持等方面的具体优势,为读者提供了全面而深入的理解。 ###
|
Unix Linux Ruby
在windows和linux上高效快捷地发布Dash应用
在windows和linux上高效快捷地发布Dash应用
647 4
|
Linux iOS开发 开发者
跨平台开发不再难:.NET Core如何让你的应用在Windows、Linux、macOS上自如游走?
【8月更文挑战第28天】本文提供了一份详尽的.NET跨平台开发指南,涵盖.NET Core简介、环境配置、项目结构、代码编写、依赖管理、构建与测试、部署及容器化等多个方面,帮助开发者掌握关键技术与最佳实践,充分利用.NET Core实现高效、便捷的跨平台应用开发与部署。
1551 3
|
存储 监控 Linux
在Linux中,如何进行虚拟化技术的应用?
在Linux中,如何进行虚拟化技术的应用?

热门文章

最新文章