嵌入式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;
相关文章
|
4月前
|
Shell Linux
Linux shell编程学习笔记30:打造彩色的选项菜单
Linux shell编程学习笔记30:打造彩色的选项菜单
|
26天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
94 13
|
2月前
|
运维 监控 Shell
深入理解Linux系统下的Shell脚本编程
【10月更文挑战第24天】本文将深入浅出地介绍Linux系统中Shell脚本的基础知识和实用技巧,帮助读者从零开始学习编写Shell脚本。通过本文的学习,你将能够掌握Shell脚本的基本语法、变量使用、流程控制以及函数定义等核心概念,并学会如何将这些知识应用于实际问题解决中。文章还将展示几个实用的Shell脚本例子,以加深对知识点的理解和应用。无论你是运维人员还是软件开发者,这篇文章都将为你提供强大的Linux自动化工具。
|
4月前
|
Shell Linux
Linux shell编程学习笔记82:w命令——一览无余
Linux shell编程学习笔记82:w命令——一览无余
|
12天前
|
存储 人工智能 JavaScript
Harmony OS开发-ArkTS语言速成二
本文介绍了ArkTS基础语法,包括三种基本数据类型(string、number、boolean)和变量的使用。重点讲解了let、const和var的区别,涵盖作用域、变量提升、重新赋值及初始化等方面。期待与你共同进步!
72 47
Harmony OS开发-ArkTS语言速成二
|
14天前
|
API 索引
鸿蒙开发:实现一个超简单的网格拖拽
实现拖拽,最重要的三个方法就是,打开编辑状态editMode,实现onItemDragStart和onItemDrop,设置拖拽移动动画和交换数据,如果想到开启补位动画,还需要实现supportAnimation方法。
71 13
鸿蒙开发:实现一个超简单的网格拖拽
|
13天前
|
索引 API
鸿蒙开发:自定义一个股票代码选择键盘
金融类的软件,特别是股票基金类的应用,在查找股票的时候,都会有一个区别于正常键盘的键盘,也就是股票代码键盘,和普通键盘的区别就是,除了常见的数字之外,也有一些常见的股票代码前缀按钮,方便在查找股票的时候,更加方便的进行检索。
鸿蒙开发:自定义一个股票代码选择键盘
|
13天前
|
API
鸿蒙开发:自定义一个英文键盘
实现方式呢,有很多种,目前采用了比较简单的一种,如果大家采用网格Grid组件实现方式,也是可以的,但是需要考虑每行的边距以及数据,还有最后两行的格子占位问题。
鸿蒙开发:自定义一个英文键盘
|
14天前
|
存储 JSON 数据库
鸿蒙元服务项目实战:备忘录内容编辑开发
富文本内容编辑我们直接使用RichEditor组件即可,最重要的就是参数,value: RichEditorOptions,通过它,我们可以用来设置样式,和获取最后的富文本内容,这一点是很重要的。
鸿蒙元服务项目实战:备忘录内容编辑开发
|
13天前
|
前端开发 API 数据库
鸿蒙开发:异步并发操作
在结合async/await进行使用的时候,有一点需要注意,await关键字必须结合async,这两个是搭配使用的,缺一不可,同步风格在使用的时候,如何获取到错误呢,毕竟没有catch方法,其实,我们可以自己创建try/catch来捕获异常。
鸿蒙开发:异步并发操作