0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

什么是I2C协议?I2C的功能特点有哪些

FPGA之家 来源:嵌入式悦翔园 作者:李斌 2022-09-06 10:03 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1、什么是I2C协议

I2C协议是一个允许多个 “从机” 芯片和一个或更多的 “主机” 芯片进行通讯的协议。它就像串行外设接口(SPI)一样,只能用于短距离通信。又像异步串行接口(如RS232UART), 只需要两根信号线来交换信息。

实现I2C需要两根信号线完成信息交换,SCL时钟信号线,SDA数据输入/输出线。它属于同步通信,由于输入输出数据均使用一根线,因此通信方向为半双工

总结:短距离、一主多从、半双工、两根线、同步通讯

937c16d2-2d86-11ed-ba43-dac502259ad0.png


2、名词解释

什么是半双工呢?什么是同步通讯?什么是异步通讯?

2.1 什么是半双工?

数据通信中,数据在线路上的传送方式可以分为单工通信半双工通信全双工通信三种。

单工通信: 是指消息只能单方向传输的工作方式。例如遥控、遥测(一部分),就是单工通信方式。单工通信信道是单向信道,发送端和接收端的身份是固定的,发送端只能发送信息,不能接收信息;接收端只能接收信息,不能发送信息,数据信号仅从一端传送到另一端,即信息流是单方向的。

半双工: 是指数据可以沿两个方向传送,但同一时刻一个信道只允许单方向传送,因此又被称为双向交替通信。(信息在两点之间能够在两个方向上进行发送,但不能同时发送的工作方式。)半双工方式要求收发两端都有发送装置和接收装置。由于这种方式要频繁变换信道方向,故效率低,但可以节约传输线路。

全双工: 是指在通信的任意时刻,线路上可以同时存在A到B和B到A的双向信号传输。在全双工方式下,通信系统的每一端都设置了发送器和接收器,因此,能控制数据同时在两个方向上传送。全双工方式无需进行方向的切换,因此,没有切换操作所产生的时间延迟,这对那些不能有时间延误的交互式应用(例如远程监测和控制系统)十分有利。比如,电话机则是一种全双工设备,其通话双方可以同时进行对话。

938cdd28-2d86-11ed-ba43-dac502259ad0.png

2.2 什么是同步通讯

同步通信: 发送端在发送串行数据的同时,提供一个时钟信号,并按照一定的约定(例如:在时钟信号的上升沿的时候,将数据发送出去)发送数据,接收端根据发送端提供的时钟信号,以及大家的约定,接收数据。如:I2C、SPI等有时钟信号的协议,都属于这种通信方式。

异步通信: 接收方并不知道数据什么时候会到达,收发双方可以有各自自己的时钟。发送方发送的时间间隔可以不均,接收方是在数据的起始位和停止位的帮助下实现信息同步的。这种传输通常是很小的分组,比如:一个字符为一组,数据组配备起始位和结束位。所以这种传输方式的效率是比较低的,因为额外加入了很多的辅助位作为负载,常用在低速的传输中。

同步通信与异步通信区别:

(1)同步通信要求接收端时钟频率和发送端时钟频率一致,发送端发送连续的比特流;异步通信时不要求接收端时钟和发送端时钟同步,发送端发送完一个字节后,可经过任意长的时间间隔再发送下一个字节。

(2)同步通信效率高,异步通信效率较低。

(3)同步通信较复杂,双方时钟的允许误差较小;异步通信简单,双方时钟可允许一定误差。

(4)同步通信可用于点对多点;异步通信只适用于点对点。

3、I2C的功能特点

I2C最重要的功能包括:

只需要两条总线;

没有严格的波特率要求,例如使用RS232,主设备生成总线时钟;

所有组件之间都存在简单的主/从关系,连接到总线的每个设备均可通过唯一地址进行软件寻址;

I²C是真正的多主设备总线,可提供仲裁和冲突检测;

传输速度:

标准模式:Standard Mode = 100 Kbps

快速模式:Fast Mode = 400 Kbps

高速模式:High speed mode = 3.4 Mbps

超快速模式:Ultra fast mode = 5 Mbps

最大主设备数:无限制;

最大从机数:理论上是127;

93a314ee-2d86-11ed-ba43-dac502259ad0.png


4、I2C的高阻态

漏极开路(Open Drain)即高阻状态,适用于输入/输出,其可独立输入/输出低电平和高阻状态,若需要产生高电平,则需使用外部上拉电阻

高阻状态:高阻状态是三态门电路的一种状态。逻辑门的输出除有高、低电平两种状态外,还有第三种状态——高阻状态的门电路。电路分析时高阻态可做开路理解。

我们知道IIC的所有设备是接在一根总线上的,那么我们进行通信的时候往往只是几个设备进行通信,那么这时候其余的空闲设备可能会受到总线干扰,或者干扰到总线,怎么办呢?

为了避免总线信号的混乱,IIC的空闲状态只能有外部上拉, 而此时空闲设备被拉到了高阻态,也就是相当于断路, 整个IIC总线只有开启了的设备才会正常进行通信,而不会干扰到其他设备。

5、数据传输协议

主设备和从设备进行数据传输时遵循以下协议格式。数据通过一条SDA数据线在主设备和从设备之间传输0和1的串行数据。串行数据序列的结构可以分为:

93b03cf0-2d86-11ed-ba43-dac502259ad0.png

5.1 开始位

当主设备决定开始通讯时,需要发送开始信号,并且执行以下过程:

将SDA线由高电平切换成低电平;

将SCL线由高电平切换成低电平;

主设备发送开始条件信号之后,所有从机即使处于睡眠模式也将变为活动状态,并等待接收地址位。

93bbb242-2d86-11ed-ba43-dac502259ad0.png

5.2 地址位

地址位支持7bit、10bit,主设备如果需要向从机发送/接收数据,首先要发送对应从机的地址,然后会匹配总线上挂载的从机的地址,故地址为主要用来辨识不同设备。

地址位由主机发送,从设备负责接受并识别该地址是否位自己地址。

5.3 读写位

由于I2C是半双工通讯,所以设备需要确定数据传输的方向,故引入了读写位。

如果主设备需要将数据发送到从设备,则该位设置为 0;

如果主设备需要往从设备接收数据,则将其设置为 1 ;

读写位由主机发送;1表示读操作,0表示写操作。

5.4 应答位

I2C最大的一个特点就是有完善的应答机制,从机接收到主机的数据时,会回复一个应答信号来通知主机表示“我收到了”。

应答信号: 出现在1个字节传输完成之后,即第9个SCL时钟周期内,此时主机需要释放SDA总线,把总线控制权交给从机,由于上拉电阻的作用,此时总线为高电平,如果从机正确的收到了主机发来的数据,会把SDA拉低,表示应答响应。

93db1646-2d86-11ed-ba43-dac502259ad0.png

非应答信号:当第9个SCL时钟周期时,SDA保持高电平,表示非应答信号。

93ebad62-2d86-11ed-ba43-dac502259ad0.png

非应答信号可能是主机产生也可能是从机产生,产生非应答信号的情况主要有以下几种:

I2C总线上没有主机所指定地址的从机设备;

从机正在执行一些操作,处于忙状态,还没有准备好与主机通讯;

主机发送的一些控制命令,从机不支持;

主机接收从机数据时,主机产生非应答信号,通知从机数据传输结束,不要再发数据了;

5.5 数据位

I2C数据总线传输要保证在SCL为高电平时,SDA数据稳定,所以SDA上数据变化只能在SCL为低电平时

93f75e5a-2d86-11ed-ba43-dac502259ad0.png

一次传输的数据总共有8位,由发送方设置,它需要将数据位传输到接收方。发送之后会紧跟一个ACK / NACK位,如果接收器成功接收到数据,则从机发送ACK。否则,从机发送NACK。

数据可以重复发送多个,直到接收到停止位为止。

5.6 停止位

当主设备决定结束通讯时,需要发送结束信号,需要执行以下动作:

先将SDA线从低电压电平切换到高电压电平;

再将SCL线从高电平拉到低电平;

9401c6f6-2d86-11ed-ba43-dac502259ad0.png

5.7 总结

寄存器的标准流程为:

Master发起START

Master发送I2C addr(7bit)和w操作0(1bit),等待ACK

Slave发送ACK

Master发送reg addr(8bit),等待ACK

Slave发送ACK

Master发送data(8bit),即要写入寄存器中的数据,等待ACK

Slave发送ACK

第6步和第7步可以重复多次,即顺序写多个寄存器

Master发起STOP

读寄存器的标准流程为:

Master发送I2C addr(7bit)和w操作1(1bit),等待ACK

Slave发送ACK

Master发送reg addr(8bit),等待ACK

Slave发送ACK

Master发起START

Master发送I2C addr(7bit)和r操作1(1bit),等待ACK

Slave发送ACK

Slave发送data(8bit),即寄存器里的值

Master发送ACK

第8步和第9步可以重复多次,即顺序读多个寄存器

6、仲裁机制

在多主的通信系统中。总线上有多个节点,它们都有自己的寻址地址,可以作为从节点被别的节点访问,同时它们都可以作为主节点向其他的节点发送控制字节和传送数据。

但是如果有两个或两个以上的节点都向总线上发送启动信号并开始传送数据,这样就形成了冲突。要解决这种冲突,就要进行仲裁的判决,这就是I2C总线上的仲裁。

I2C总线上的仲裁分两部分:SCL线的同步和SDA线的仲裁。

6.1 SCL线的同步

SCL同步是由于总线具有线 “与” 的逻辑功能(开漏输出),即只要有一个节点发送低电平时,总线上就表现为低电平。当所有的节点都发送高电平时,总线才能表现为高电平。正是由于线“与”逻辑功能的原理,当多个节点同时发送时钟信号时,在总线上表现的是统一的时钟信号,这就是SCL的同步原理。

94226370-2d86-11ed-ba43-dac502259ad0.png

6.2 SDA线的仲裁

总线仲裁是为了解决多设备同时竞争中线控制权的问题,通过一定的裸机来决定哪个设备能够获得最终的总线控制权。

SDA线的仲裁也是建立在总线具有线“与”逻辑功能的原理上的。节点在发送1位数据后,比较总线上所呈现的数据与自己发送的是否一致(类似于CAN总线的回读机制)。

是,继续发送;

否则,退出竞争;

I2C总线的控制逻辑:低电平优先

SDA线的仲裁可以保证I2C总线系统在多个主节点同时企图控制总线时通信正常进行并且数据不丢失,总线系统通过仲裁只允许一个主节点可以继续占据总线


9428d1ec-2d86-11ed-ba43-dac502259ad0.png

943ba222-2d86-11ed-ba43-dac502259ad0.png


上图过程分析:

第一个周期:所有设备发送1,做与运算后的结果为1,与自己发送的数据相同,继续发送;
第二个周期:所有设备发送1,做与运算后的结果为1,与自己发送的数据相同,继续发送;
第三个周期:所有设备发送0,做与运算后的结果为0,与自己发送的数据相同,继续发送;
第四个周期:AB设备发送1,C设备发送0,做与运算后结果为0,与AB发送的数据不同,则AB退出竞争,节点C获胜;

注:若AB两个设备发送0,C设备发送1,这最后与运算结果为0,与AB数据格式相同,与C数据格式不同,则C退出,AB继续发送,直至AB中有一个退出。

SDA仲裁和SCL时钟同步处理过程没有先后关系,而是同时进行的。

7、I2C死锁

在实际使用过程中,I2C比较容易出现的一个问题就是死锁 ,死锁在I2C中主要表现为:I2C死锁时表现为SCL为高,SDA一直为低。

在I2C主设备进行读写操作的过程中,主设备在开始信号后控制SCL产生8个时钟脉冲,然后拉低SCL信号为低电平,在这个时候,从设备输出应答信号,将SDA信号拉为低电平。

如果这个时候主设备异常复位,SCL就会被释放为高电平。此时,如果从设备没有复位,就会继续I2C的应答,将SDA一直拉为低电平,直到SCL变为低电平,才会结束应答信号。

而对于I2C主设备来说,复位后检测SCL和SDA信号,如果发现SDA信号为低电平,则会认为I2C总线被占用,会一直等待SCL和SDA信号变为高电平。

这样,I2C主设备等待从设备释放SDA信号,而同时I2C从设备又在等待主设备将SCL信号拉低以释放应答信号,两者相互等待,I2C总线进人一种死锁状态。

同样,当I2C进行读操作,I2C从设备应答后输出数据,如果在这个时刻I2C主设备异常复位而此时I2C从设备输出的数据位正好为0,也会导致I2C总线进入死锁状态。

8、I2C的代码实现

参考了STM32的HAL库中I2C驱动,主设备发送函数HAL_I2C_Master_Transmit()具体如下:

/**
*@briefTransmitsinmastermodeanamountofdatainblockingmode.
*@paramhi2cPointertoaI2C_HandleTypeDefstructurethatcontains
*theconfigurationinformationforthespecifiedI2C.
*@paramDevAddressTargetdeviceaddress:Thedevice7bitsaddressvalue
*indatasheetmustbeshiftedtotheleftbeforecallingtheinterface
*@parampDataPointertodatabuffer
*@paramSizeAmountofdatatobesent
*@paramTimeoutTimeoutduration
*@retvalHALstatus
*/
HAL_StatusTypeDefHAL_I2C_Master_Transmit(I2C_HandleTypeDef*hi2c,
uint16_tDevAddress,
uint8_t*pData,
uint16_tSize,
uint32_tTimeout){
uint32_ttickstart=0x00U;

/*Inittickstartfortimeoutmanagement*/
tickstart=HAL_GetTick();

if(hi2c->State==HAL_I2C_STATE_READY){
/*WaituntilBUSYflagisreset*/
if(I2C_WaitOnFlagUntilTimeout(hi2c,I2C_FLAG_BUSY,SET,I2C_TIMEOUT_BUSY_FLAG,tickstart)!=HAL_OK){
returnHAL_BUSY;
}

/*ProcessLocked*/
__HAL_LOCK(hi2c);

/*CheckiftheI2Cisalreadyenabled*/
if((hi2c->Instance->CR1&I2C_CR1_PE)!=I2C_CR1_PE){
/*EnableI2Cperipheral*/
__HAL_I2C_ENABLE(hi2c);
}

/*DisablePos*/
hi2c->Instance->CR1&=~I2C_CR1_POS;

hi2c->State=HAL_I2C_STATE_BUSY_TX;
hi2c->Mode=HAL_I2C_MODE_MASTER;
hi2c->ErrorCode=HAL_I2C_ERROR_NONE;

/*Preparetransferparameters*/
hi2c->pBuffPtr=pData;
hi2c->XferCount=Size;
hi2c->XferOptions=I2C_NO_OPTION_FRAME;
hi2c->XferSize=hi2c->XferCount;

/*SendSlaveAddress*/
if(I2C_MasterRequestWrite(hi2c,DevAddress,Timeout,tickstart)!=HAL_OK){
if(hi2c->ErrorCode==HAL_I2C_ERROR_AF){
/*ProcessUnlocked*/
__HAL_UNLOCK(hi2c);
returnHAL_ERROR;
}else{
/*ProcessUnlocked*/
__HAL_UNLOCK(hi2c);
returnHAL_TIMEOUT;
}
}

/*ClearADDRflag*/
__HAL_I2C_CLEAR_ADDRFLAG(hi2c);

while(hi2c->XferSize>0U){
/*WaituntilTXEflagisset*/
if(I2C_WaitOnTXEFlagUntilTimeout(hi2c,Timeout,tickstart)!=HAL_OK){
if(hi2c->ErrorCode==HAL_I2C_ERROR_AF){
/*GenerateStop*/
hi2c->Instance->CR1|=I2C_CR1_STOP;
returnHAL_ERROR;
}else{
returnHAL_TIMEOUT;
}
}
/*WritedatatoDR*/
hi2c->Instance->DR=(*hi2c->pBuffPtr++);
hi2c->XferCount--;
hi2c->XferSize--;

if((__HAL_I2C_GET_FLAG(hi2c,I2C_FLAG_BTF)==SET)
&&(hi2c->XferSize!=0U)){
/*WritedatatoDR*/
hi2c->Instance->DR=(*hi2c->pBuffPtr++);
hi2c->XferCount--;
hi2c->XferSize--;
}
/*WaituntilBTFflagisset*/
if(I2C_WaitOnBTFFlagUntilTimeout(hi2c,Timeout,tickstart)!=HAL_OK){

if(hi2c->ErrorCode==HAL_I2C_ERROR_AF){
/*GenerateStop*/
hi2c->Instance->CR1|=I2C_CR1_STOP;
returnHAL_ERROR;
}else{
returnHAL_TIMEOUT;
}
}
}

/*GenerateStop*/
hi2c->Instance->CR1|=I2C_CR1_STOP;

hi2c->State=HAL_I2C_STATE_READY;
hi2c->Mode=HAL_I2C_MODE_NONE;

/*ProcessUnlocked*/
__HAL_UNLOCK(hi2c);

returnHAL_OK;
}else{
returnHAL_BUSY;
}
}


审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 串行接口
    +关注

    关注

    3

    文章

    523

    浏览量

    45328
  • SPI接口
    +关注

    关注

    0

    文章

    287

    浏览量

    36879
  • 高电平
    +关注

    关注

    6

    文章

    225

    浏览量

    22879
  • I2C协议
    +关注

    关注

    0

    文章

    29

    浏览量

    9305

原文标题:一文带你读懂I2C协议

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    I2C 为什么只要两根线就能搞定通信?

    到目前为止,我们已经讨论了SPI通信和UART通信的基础知识,现在让我们讨论本系列的最后一个协议,即集成电路间协议I2C)。如果您曾经构建过使用OLED显示器、气压传感器或陀螺仪/加速度计模块
    的头像 发表于 01-04 09:14 2041次阅读
    <b class='flag-5'>I2C</b> 为什么只要两根线就能搞定通信?

    P82B715:I2C总线扩展的得力助手

    P82B715:I2C总线扩展的得力助手 在电子设计领域,I2C总线是一种常用的通信协议,但它的总线电容限制往往会影响实际通信距离和系统设计。今天,我们就来详细了解一下德州仪器(TI
    的头像 发表于 12-26 10:20 1520次阅读

    基于FPGA的I2C控制模块设计

    I2C_WRITE_WDATA.v模块实现I2C写时序,I2C_Controller (I2C控制器)例化了I2C_WRITE_WDATA.
    的头像 发表于 12-26 09:48 5931次阅读
    基于FPGA的<b class='flag-5'>I2C</b>控制模块设计

    基于FPGA的I2C通信协议设计

    I2C(Inter-Integrated Circuit)是一种由飞利浦半导体(现为恩智浦半导体)在1980年代初开发的同步、串行、半双工的总线型通信协议。主要用于近距离(同一块印刷电路板(PCB
    的头像 发表于 12-26 09:44 6352次阅读
    基于FPGA的<b class='flag-5'>I2C</b>通信<b class='flag-5'>协议</b>设计

    深入解析 TCA9539:低电压 16 位 I2C 和 SMBus I/O 扩展器

    : tca9539.pdf 核心特性亮点 接口扩展能力出色 TCA9539 是一款功能强大的 I2C 转并行端口扩展器,可在 I2C 或 SMBus 协议的双线双
    的头像 发表于 12-25 09:30 541次阅读

    AS32X601的I2C模块操作EEPROM详解

    I2C接口模块实现了I2C协议的标准模式和快速模式,支持多主机I2C总线架构。其标准模式为100K,快速模式400K。而EEPROM,作为一种支持字节级单独擦写、数据掉电不丢失的存
    的头像 发表于 12-21 21:39 1580次阅读
    AS32X601的<b class='flag-5'>I2C</b>模块操作EEPROM详解

    I2C死锁的问题

    在实际使用过程中,I2C比较容易出现的一个问题就是死锁 ,死锁在I2C中主要表现为:I2C死锁时表现为SCL为高,SDA一直为低。 在I2C主设备进行读写操作的过程中,主设备在开始信
    发表于 12-04 06:00

    I2C的缺点介绍

    上升时间变慢和潜在的信号衰减。对于长距离通信,其他协议,如 UART(通用异步接收器/发送器)或 SPI(串行外设接口)可能更合适。 速度限制: 虽然 I2C 支持不同的速度模式,但其高速模式(高达
    发表于 11-27 06:10

    SPI、I2CI2S、UART:通信协议解释

            在嵌入式开发中,最常用的几种通信接口无非就是SPI、I2CI2S、UART。名字看起来差不多,但应用场景和特性却大不相同。为什么都叫串行通信,结构却不一样?为什么有的能传音频,有的
    的头像 发表于 11-18 10:53 711次阅读

    SPI、I2CI2S、UART:通信协议对比表

    在嵌入式开发中,最常用的几种通信接口无非就是SPI、I2CI2S、UART。名字看起来差不多,但应用场景和特性却大不相同。很多初学者容易混淆:为什么都叫串行通信,结构却不一样?为什么有的能传音频
    的头像 发表于 11-17 10:53 2106次阅读
    SPI、<b class='flag-5'>I2C</b>、<b class='flag-5'>I2</b>S、UART:通信<b class='flag-5'>协议</b>对比表

    深入剖析I2C协议

    I2C也是一种可以多主设备,多从设备的总线协议,通过地址索引,I2C可以使能所需从设备,I2C的出现主要是用来实现不同集成电路组件之间的控制功能
    的头像 发表于 08-21 15:10 3877次阅读
    深入剖析<b class='flag-5'>I2C</b><b class='flag-5'>协议</b>

    第十八章 I2C通信测试

    本章介绍了I2C协议,其物理层用SDA和SCL双线,支持多设备:协议层含起始/停止信号、应答机制等。还讲解W55MH32的I2C外设及初始化,并进行了通信测试代码的分析。
    的头像 发表于 06-19 17:07 1463次阅读
    第十八章 <b class='flag-5'>I2C</b>通信测试

    第十六章 一文浅谈I2C

    本篇文章介绍了W55MH32的I2C总线,其由SDA和SCL构成,具设备寻址等特点协议含起始 / 停止信号等。阐述主从模式,介绍了相关例程,用于验证 I2C 通信
    的头像 发表于 05-28 16:07 1613次阅读
    第十六章 一文浅谈<b class='flag-5'>I2C</b>

    简单了解I2C接口

    在电子电路的复杂世界里,各种电路模块设备需要相互通信才能协同工作 ,I2C接口就像是电路模块设备间的沟通桥梁,今天就带大家深入了解它。
    的头像 发表于 05-08 14:15 2812次阅读
    简单了解<b class='flag-5'>I2C</b>接口

    基于RT-Thread的I2C(软件) 实践 | 技术集结

    一、软硬件介绍(一)I2C(软件)I2C是一种广泛应用于嵌入式系统中的短距离串行通信协议,支持多主多从设备模式,主机通过时钟信号SCL和数据线SDA与从机进行数据交互。在RT-Thread操作系统中
    的头像 发表于 05-06 18:44 1214次阅读
    基于RT-Thread的<b class='flag-5'>I2C</b>(软件) 实践 | 技术集结