一文认识 I2C - 学习笔记

学习笔记中大部分是看 B 站江科大自化协后进行总结的,仅供学习交流,如有错误麻烦指正


目录

一、I2C 概述

二、I2C 特点

三、I2C 总线的连接

1、设计要点

2、主从机对 SCL 和 SDA 的使用权

四、实现 IIC 通信的方式

1、软件 I2C 和硬件 I2C 的区别是什么?

2、如何区分它们?

五、I2C 协议

1、I2C 时序的基本组成单元

1)使用 I2C 的起始条件:(怎么开始启动 I2C)

2)主机如何发送一个字节给从机:

3)主机如何接收从机的一个字节:

4)发送应答:

5)接收应答:

6)停止使用 I2C 的终止条件:(停止使用 I2C)

2、I2C 完整时序(完整数据帧,上面基本单元进行整合)

1)指定地址写:

2)当前地址读:

3)指定地址读:


一、I2C 概述

I2C(Inter IC BUS)总线是一种通用数据总线,有两根通信线(串行总线):SCL(serial clock)时钟线、 SDA(serial data)数据线。使用 I2C 进行通信的设备,一般都会在引脚上标有 SCL、SDA,例如采用 i2c 协议的 oled 屏模块,如下


二、I2C 特点

1)同步通信        

        为什么 I2C 不使用异步通信,而是用同步?

        如果采用异步通信,发送方发送一半突然进中断停止了,接收方并不知道,仍然继续按照规定的时间顺序进行同步,如果这时发送端恢复发送就会造成数据接收混乱,这是不允许的,所以异步对硬件外设 USART 电路依赖性很强,需要在 USART 电路的支持下实现异步(异步需要依赖硬件的硬件功能来实现完美的时间把控,如果硬件这方面不行就可能导致时间上的错位),虽然也可软件实现,但因为对时间要求严格所以一般不用软件。同步协议由于存在时钟线 SCL,对时间的要求就不高,发送方可随时停止去处理其他事情(因为暂停传输的同时,时钟线也暂停了,发送方和接收方都定格在暂停时刻,可过一段时间继续)。半双工也可大大节约硬件资源。

2)半双工

        说明只有一根用于交换数据的数据线。发送的时候不需要接收,接收的时候就不需要发送

3)带有数据应答机制       

        为了后续的通信能继续进行下去,才有这种机制。只要接收方接收到数据或命令,都要返回一个应答位(应答信号),发送方只有收到应答位后才继续发送。只有一个特殊情况不用应答位,就是主机(提供时钟信号的一方)作为接收方时,在收到最后一个字节信息时可以不用应答。

        由于IIC的数据线(SDA)一定有一个上拉电阻(检测低电平),如果通信中能收到应答位,一定是接收方把数据线强制拉低,所以在开始学习 IIC 通信时,能收到接收方的应答位,是成功的第一步。

应答信号的理解

1、首先 IIC 通信要分清主机与从机的关系,在主机对从机进行写操作时,一般是在传送完一个数据之后单片机就进入检测应答信号状态:先将两个脚置位 SDA=1;SCL=1;然后在一定时间内不断检测 SDA 脚的电平状态,比如说你弄个循环 for(i=255;i>0;i--){..; if(...)break;...} 进行不断判断,当 SDA 的电平为低时就跳出循环,说明此时从机已经ACK,就可说明是I2C器件拉低;如果为高时,则一直判断完整个循环,到最后还为高时,就说明没有应答。

2、写应答和读应答肯定有所区别的。写应答是在你读从机数据期间,当你接收到一个数据时,可以应答的(想继续通信就应答),就将SDA复位(拉低),不想应答(想结束通信时)就置位(SDA=1)。读应答则在主机写数据给从机期间,每当从机接收到一个数据就会应答一下(将数据SDA线拉低),主机将不断检测SDA线的电平,主机就是凭SDA的电平状态才知道从机是否已经正确地接收了主机发送的数据。

4)支持总线挂载多个设备

        一主多从:单片机作为主机主导I2C总线的运行,挂载在I2C总线的所有外设模块都是从机,从机只有被主机点名后才可控制I2C总线。

        多主多从:就是具有多个主机,总线上任何一个模块都可以主动跳出来成为主机,但是同一时间只能有一个主机,这时就相当于发生了总线冲突,I2C协议会进行仲裁,仲裁胜利的一方取得控制权,协议比较复杂可自行了解。


三、I2C 总线的连接

1、设计要点

1)所有 I2C 设备的 SCL 连在一起,SDA 连在一起

2)所有 I2C 设备的 SCL 引脚和 SDA 引脚,即 GPIO 要配置成开漏输出模式 + 上拉电阻

        GPIO只配置输出模式的时候,其实上半部分的输入功能还是有工作的,TTL 施密特触发器有在工作,如果只配置输入模式,下半部分的输出模式会被关闭,不再有输出功能

为什么不能用推挽输出,而是用开漏输出外加一个上拉电阻?

       是为了避免电源短路。由于主机和从机共用一条 SDA 线,且双方都有输入和输出,在输入和输出之间反复切换,万一要是出现主机是在输出的同时从机也在输出,主机输出高电平,从机输出低电平,就会导致电源短路,为了解决这个问题,I2C规定:禁止所有设备输出强上拉的高电平(推挽输出工作模式下,输出的高电平是强上拉),采用外置弱上拉电阻加开漏输出模式的电路结构,如下图

 

那推挽输出还能不能用?

        如果我们使用软件模拟 I2C,一般就只有一个从机设备,不会出现那种多个从设备挂载在同一个总线上,也就不会出现短路的可能性,所以这种情况下使用推挽输出也就没什么问题。

2、主从机对 SCL SDA 的使用权

主机

①完全控制时钟线 SCL

②空闲状态下,可主动发起对 SDA 的控制,只有在从机发送数据和从机应答时,才会转交SDA的控制权给从机

从机

①任何时候都只能被动的读取 SCL 时钟线

②不允许主动发起对 SDA 的控制,只有在主机发送读取从机的命令后或从机应答时才可短暂获得控制权


四、实现 IIC 通信的方式

实现 I2C 通信的方式有两种:软件 I2C、硬件 I2C

1、软件 I2C 和硬件 I2C 的区别是什么?

        软件 I2C,又称模拟 I2C,是通过纯代码的方式模拟出 I2C 的工作时序,并且不受 GPIO 引脚限制,任何 GPIO 都可以作为 I2C 的 SDA 和 SCL 引脚(一般同步通信的才考虑用软件模拟,而异步通信虽然用软件模拟也可以实现通信,但是很麻烦,所以异步通信一般不考虑用软件模拟,而是用硬件实现通信,例如 usart 通信,就是用 usart 外设实现的通信)

        硬件 I2C,顾名思义,就是有具体的硬件外设(I2C 驱动电路)来帮助我们实现 I2C 的工作时序,我们只需要配备相应的寄存器就可以使用 I2C 进行通信,且工作效率远高于软件 I2C,硬件 I2C 使用的 GPIO 引脚也是固定的。

2、如何区分它们?

        看 I2C 函数,如果调用现成函数、出现某寄存器,就一定是固件 I2C。如果是软件 I2C,肯定有长代码进行模拟,肯定是通过循环结构,模拟一位一位的数据发送。


五、I2C 协议

I2C 协议,是对要传输数据的格式的约定、标准、规范,通信双方都遵循这些规范才能正常的收发数据。那么这些约定、标准或者说规范具体是什么样的?如下

1、I2C 时序的基本组成单元

1)使用 I2C 的起始条件:(怎么开始启动 I2C)

SCL 高电平期间,SDA 从高电平切换到低电平

(具体流程如下)

        起初,I2C 总线处于空闲状态时(没有任何一个设备去碰 SCL 和 SDA),即 SCL 和 SDA 都处于高电平。

        当主机准备开始收发数据时,会先产生一个起始条件:SCL 保持不变, SDA 下降。

        从机捕获到 SCL 高电平和 SDA 的下降沿信号时,会进行自身复位,等待主机召唤(从机会开始等主机发送一个地址过来,目的是建立通信关系)。

        在 SDA 下降沿之后,主机要再把 SCL 拽下来,一方面是占用这个总线,另一方面也是为了方便时序基本单元的拼接,这样之后会保证除了起始和终止条件,每个时序单元的 SCL 都是以低电平开始,以低电平结束,这样各个单元拼接起来 SCL 才可连续

2)主机如何发送一个字节给从机

经过起始条件之后,就可以开始收发数据了(第一个字节必须是由主机发送的,因为主机要先确认通信对象是哪个从机,主机先把要建立通信的从机的地址发到总线上,总线上的从机都能接收到地址,然后跟自己的地址进行比较,如果匹配上了,从机就会向主机发出一个响应信号,告诉主机可以发送数据了,SCL 低电平期间,主机将数据位依次放到 SDA 线上I2C 时序是高位先行,即一字节里面的最高位,如下图的 B7。注意,串口时序是低位先行),然后释放 SCL,从机将在 SCL 高电平期间读取数据位,所以 SCL 高电平期间 SDA 不允许有数据变化,依次循环上述过程8次,即可发送一个字节

(具体流程如下)

        SCL 处于低电平期间,主机将数据依次放到 SDA 线上(高位先行)(主机改变 SDA 的高低电平,主机如果想发送高电平,就放开 SDA(总线有上拉电阻,不拉低 SDA 的情况下,SDA 会默认高电平),如果主机想要发送低电平,就主动拉低 SDA)

(这里为什么有2个 SDA 线,其实只是想表达上升沿和下降沿这两种状态,实际情况肯定只有一个,这里看的时候只需要关注红线部分即可)

        SCL 处于高电平之后,从机需要尽快地读取 SDA,一般是在 SCL 上升沿时刻从机就已完成读取,因为时钟线是主机控制的,从机并不知道什么时候就会出现下降沿了。主机也需要在 SCL 下降沿之后尽快把数据放在 SDA 上,但是它不用那么着急。

        设备接收数据完全是靠时钟线来进行同步的,如果主机的一个字节发送到一半突然进入中断,跑去做其他事,不再操控 SCL 和 SDA 了,时许就会在中断的位置不断拉长,SCL 和 SDA 电平停止变化,等待主机中断结束回来操控。

3主机如何接收从机的一个字节

SCL 处于低电平期间,从机将数据依次放到 SDA 线上(高位先行)(从机改变 SDA 的高低电平,如果想发送高电平,就放开 SDA(总线有上拉电阻,不拉低 SDA 的情况下,SDA 会默认高电平),如果想发送低电平,就主动拉低 SDA)

        然后释放 SCL(由主机释放),主机将在 SCL 高电平期间读取数据位,所以 SCL 高电平期间 SDA 不允许有数据变化,依次循环上述过程8次,即可接收一个字节

(注意,主机在开始接收之前需要先释放 SDA,把 SDA 的控制权交给从机(因为有上拉电阻,释放后如果没有设备控制 SDA,SDA 默认为高电平)。主机释放 SDA,其实就相当于切换成输入模式,因为只有输出模式才有必要去操控 SDA 数据线,操控 SDA 的高低电平来实现要发送的内容,所以作为接收端的设备此时要释放 SDA,不能碰 SDA 线,以免影响别人发送,因为总线是线与的特征,任何一个设备只要主动拉低,SDA 总线就是低电平,如果作为接收的设备控制 SDA 为低,那别人无论发什么数据,始终都是低电平。所有设备(包括主机)都始终处于输入模式,当设备需要发送的时候,就需要主动操控 SDA 线,可以主动去拉低 SDA)

4)发送应答

主机在接收完一个字节之后,会在下一个时钟发送一位数据给从机,这样从机才知道主机是否收到,数据0表示应答,数据1表示非应答(0表示接收到了,1表示没有接收到)

 

5)接收应答

主机在发送完一个字节之后,会在下一个时钟接收从机的一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答

(注意,主机在接收数据之前都要释放 SDA,让从机操控,这样从机才能发送应答位给主机;所有没有应答的从机都会发送数据 1)

6)停止使用 I2C 的终止条件:(停止使用 I2C)

SCL 高电平期间,SDA从低电平切换到高电平。

        最终,SCL 和 SDA 都返回到起始前的高电平状态。

IIC 的起始和终止条件,就类似于串口数据帧里面的起始位和终止位,即起始和终止都是由主机产生,从机不可产生,所以空闲状态下从机必不可碰总线,只能由主机主动发起(当然多主机模式可能可以)

2、I2C 完整时序(完整数据帧,上面基本单元进行整合)

        I2C的完整时序,主要有3种:指定地址写、当前地址读、指定地址读。每个从机设备地址都不同,在I2C协议标准里分为7位地址和10位地址,目前只讲7位地址的,它简单且应用广,这个地址由芯片厂商规定可在手册查找。一般相同型号芯片的地址一样,当挂载在同一总线时,地址低位可通过特定引脚切换。

1)指定地址写:

主机对于指定设备(从机地址Slave Address),在指定地址(内部寄存器地址Reg Address)下,写入指定数据(Data)。

下图Slave Address前7位是选定的从机地址,第8位为0表示写,1表示读,称为读写标志位。

如果就写一个字节,那最后就P停止;如果想写多个字节,就可把Send Byte :0xAA(Data)、RA这部分多重复几次!

2)当前地址读:

(不常用)对于指定设备(Slave Address),在当前地址指针指示的地址下,读取从机数据(Data)。

在I2C协议规定中,主机进行寻址时一旦读写标志位给”1“,下一个字节就必须立马进入读的时序,主机来不及指示寄存器地址,没有指定寄存器地址那么读取哪个单元数据呢?这就需要当前地址指针,在从机中所有寄存器被分配到了一个线性区域,且有一个单独的指针变量指示着其中一个寄存器,这个指针上电默认一般指向0地址,并且每写入一个字节和读出一个字节后,此指针就会自动自增一次移动到下一个位置。比如假设开始调用了上面的指定地址写的时序,在0x19的位置写入了0xAA,那么指针就会+1移动到0x1A的位置,再调用这个当前地址读的时序,返回的就是0x1A地址下的值,如果再调用一次返回的就是0x1B地址下的值,以此类推。

3)指定地址读:

对于指定设备(Slave Address),在指定地址(Reg Address)下,读取从机数据(Data)。RA为Read Ack(发送字节后出现)、SA为Send Ack(读到字节后出现),”0“为应答、”1“为非应答。

这个时序为什么可以指定读的寄存器地址呢?把指定地址写的时序前面指定地址的部分,加到当前地址读的前面,就得到了指定地址读的时序,也叫做复合格式。前面写入的寄存器地址会存在地址指针里面,不会随着时序的变化而消失,应答位RA后面再起始,再发送一个字节(设备还是刚才那个但读写标志位为1),后续开始读字节。

如果就读一个字节,最后就写SA=”1“(非应答)和P停止,非应答就是该主机应答的时候主机不把SDA拉低,从机读到SDA为”1“就代表主机未应答,就知道主机不想继续了,从机就会释放总线,把SDA控制权交还给主机;如果想读多个字节,就需要读一个字节,给从机一个应答SA=”0“,依次类推,最后一个字节给非应答SA=”1“,停止P。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
张正友标定法是一种常用的相机标定方法,广泛应用于计算机视觉领域。该方法通过采集一系列已知的三维物体在相机坐标系下的二维投影点,来计算相机内外参数矩阵,从而实现相机的几何校正和测量。 具体步骤如下: 1. 初始化标定板:选择一个特定的标定板,例如棋盘格,然后在每个方格的交叉点上贴上黑白相间的标志。 2. 放置标定板:将标定板放置在计算机视觉系统所见范围内,保证标定板能够在不同角度、位置下被相机观察到。 3. 拍摄标定图像:使用相机对标定板进行拍摄,至少需要12-20幅图像,图像应该包含不同的姿态和视角。 4. 检测标志物:从每个标定图像中提取特征点,通常使用角点检测算法来检测标志物的位置。 5. 计算相机参数:根据提取的特征点,通过最小二乘法来计算相机的内部参数(焦距、主点坐标)和外部参数(旋转矩阵、平移向量)。 6. 优化结果:根据计算得到的相机参数,利用优化算法来进一步提高标定的精度。 7. 验证标定结果:使用标定结果对图像进行校正,并测量标定板上的特征点,通过计算误差指标来验证标定结果的准确性。 总之,张正友标定法通过采集已知物体在相机坐标系下的二维投影点,实现了相机参数的计算和校正,对于计算机视觉中的三维重建、目标检测等任务具有重要意义。掌握这种标定方法可以帮助我们更好地理解相机成像过程,提高图像处理和计算机视觉算法的精度和稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值