嵌入式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;
相关文章
|
19天前
|
Linux 编译器 Android开发
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
在Linux环境下,本文指导如何交叉编译x265的so库以适应Android。首先,需安装cmake和下载android-ndk-r21e。接着,下载x265源码,修改crosscompile.cmake的编译器设置。配置x265源码,使用指定的NDK路径,并在配置界面修改相关选项。随后,修改编译规则,编译并安装x265,调整pc描述文件并更新PKG_CONFIG_PATH。最后,修改FFmpeg配置脚本启用x265支持,编译安装FFmpeg,将生成的so文件导入Android工程,调整gradle配置以确保顺利运行。
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
|
5天前
|
安全 Linux Android开发
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
该文介绍了如何在Linux服务器上交叉编译Android的FFmpeg库以支持HTTPS视频播放。首先,从GitHub下载openssl源码,解压后通过编译脚本`build_openssl.sh`生成64位静态库。接着,更新环境变量加载openssl,并编辑FFmpeg配置脚本`config_ffmpeg_openssl.sh`启用openssl支持。然后,编译安装FFmpeg。最后,将编译好的库文件导入App工程的相应目录,修改视频链接为HTTPS,App即可播放HTTPS在线视频。
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
|
10天前
|
Ubuntu 算法 Linux
嵌入式Linux的学习误区
该文指出了学习嵌入式Linux开发的两个常见误区。一是过分专注于学习桌面或服务器版Linux,而非关注嵌入式开发本身,实际上只需熟悉基本操作即可。二是试图在没有基础的情况下直接阅读Linux内核源代码,这是不切实际的,应先建立基础知识再进行源码学习。文章还提到了在嵌入式系统中获取和处理屏幕数据的示例,包括使用gsnap工具将framebuffer数据转为图像,以及涉及的交叉编译过程。
11 0
|
10天前
|
前端开发 Linux iOS开发
【Flutter前端技术开发专栏】Flutter在桌面应用(Windows/macOS/Linux)的开发实践
【4月更文挑战第30天】Flutter扩展至桌面应用开发,允许开发者用同一代码库构建Windows、macOS和Linux应用,提高效率并保持平台一致性。创建桌面应用需指定目标平台,如`flutter create -t windows my_desktop_app`。开发中注意UI适配、性能优化、系统交互及测试部署。UI适配利用布局组件和`MediaQuery`,性能优化借助`PerformanceLogging`、`Isolate`和`compute`。
【Flutter前端技术开发专栏】Flutter在桌面应用(Windows/macOS/Linux)的开发实践
|
13天前
|
编解码 Linux
FFmpeg开发笔记(十二)Linux环境给FFmpeg集成libopus和libvpx
在《FFmpeg开发实战》一书中,介绍了如何在Linux环境下为FFmpeg集成libopus和libvpx,以支持WebM格式的Opus和VP8/VP9编码。首先,下载并安装libopus。接着,下载并安装libvpx。最后,在FFmpeg源码目录下,重新配置FFmpeg,启用libopus和libvpx,编译并安装。通过`ffmpeg -version`检查版本信息,确认libopus和libvpx已启用。
FFmpeg开发笔记(十二)Linux环境给FFmpeg集成libopus和libvpx
|
13天前
|
编解码 Linux
FFmpeg开发笔记(十)Linux环境给FFmpeg集成vorbis和amr
在Linux环境下,为FFmpeg添加对AAC、MP3、OGG和AMR音频格式的支持,需安装libogg、libvorbis和opencore-amr库。首先,从官方源下载各库的最新源码,如libogg-1.3.5、libvorbis-1.3.7和opencore-amr-0.1.6,然后解压并依次执行`./configure`、`make`和`make install`进行编译安装。接着,在FFmpeg源码目录中,使用`./configure`命令重新配置,并重新编译安装FFmpeg。最后,验证FFmpeg版本信息确认已启用ogg和amr支持。
FFmpeg开发笔记(十)Linux环境给FFmpeg集成vorbis和amr
|
9月前
|
IDE JavaScript API
HarmonyOS开发第一步,熟知开发工具DevEco Studio
本文主要以常见的功能点作为概述希望可以帮助到学习HarmonyOS的开发者。
233 0
|
9月前
|
开发框架 开发者 JavaScript
HarmonyOS学习路之方舟开发框架—学习ArkTS语言(状态管理 三)
子组件中被@Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。
|
4月前
|
数据管理 API 调度
【华为鸿蒙系统学习】- HarmonyOS4.0开发|自学篇
【华为鸿蒙系统学习】- HarmonyOS4.0开发|自学篇
223 0
|
9月前
|
开发框架
HarmonyOS学习路之方舟开发框架—学习ArkTS语言(状态管理 四)
被@Observed装饰的类,可以被观察到属性的变化;子组件中@ObjectLink装饰器装饰的状态变量用于接收@Observed装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定。这个实例可以是数组中的被@Observed装饰的项,或者是class object中是属性,这个属性同样也需要被@Observed装饰。单独使用@Observed是没有任何作用的,需要搭配@ObjectLink或者@Prop使用。