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

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

3天内不再提示

I2C的入门基础知识,从I2C协议的硬件层,协议层

Q4MP_gh_c472c21 来源:小麦大叔 作者:菜刀和小麦 2020-11-16 16:32 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

背景

I2C(Inter-Integrated Circuit),中文应该叫集成电路总线,它是一种串行通信总线,使用多主从架构,是由飞利浦公司在1980年代初设计的,方便了主板、嵌入式系统手机与周边设备组件之间的通讯。由于其简单性,它被广泛用于微控制器传感器阵列,显示器,IoT设备,EEPROM等之间的通信。

I2C最重要的功能包括:

只需要两条总线;

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

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

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

传输速度;

标准模式:Standard Mode=100Kbps

快速模式:Fast Mode=400Kbps

高速模式:High speed mode=3.4 Mbps

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

最大主设备数:无限制;

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

以上是I2C的一些重要特点,下面会进一步对I2C进行介绍。

硬件层

I2C协议仅需要一个SDA和SCL引脚。SDA是串行数据线的缩写,而SCL是串行时钟线的缩写。这两条数据线需要接上拉电阻

设备间的连接如下所示:

使用I2C,可以将多个从机(Slave)连接到单个主设备(Master),并且还可以有多个主设备(Master)控制一个或多个从机(Slave)。

假如希望有多个微控制器(MCU)将数据记录到单个存储卡或将文本显示到单个LCD时,这个功能就非常有用。

I2C总线(SDA,SCL)内部都使用漏极开路驱动器(开漏驱动),因此SDA和SCL可以被拉低为低电平,但是不能被驱动为高电平,所以每条线上都要使用一个上拉电阻,默认情况下将其保持在高电平;

上拉电阻的值取决于许多因素。德州仪器TI 建议 使用以下公式来计算正确的上拉电阻值:

其中是逻辑低电压;

是逻辑低电流

信号的最大上升时间;

是总线(电线)电容

具体如下所示:

根据上表,这里不难发现需要在做电阻选择需要满足几个条件;

灌电流 最大值为;

另外I2C总线规范和用户手册还为低电平输出电压设置了最大值为0.4V

所以根据上述公式可以计算,对于5V的电源,每个上拉电阻阻值至少1.53kΩ,而对于3.3V的电源,每个电阻阻值至少967Ω。

如果觉得计算电阻值比较麻烦,也可以使用典型值 4.7kΩ。

上述推导过程可以参考 TI的文档《I2C Bus Pullup Resistor Calculation》 https://www.ti.com/lit/an/slva689/slva689.pdf

最终在调试的时候,当我们测量SDA或SCL信号并且逻辑LOW上的电压高于0.4V时,我们就知道可以知道灌电流太高了;

当然,这并不意味着每当灌电流超过3mA时,设备就会立即停止工作。但是,在操作超出其规格的设备时,应始终小心,因为它可能导致通信故障,缩短其使用寿命甚至甚至永久损坏设备。

数据传输协议

主设备和从设备进行数据传输时遵循以下协议格式。数据通过一条SDA数据线在主设备和从设备之间传输0和1的串行数据。串行数据序列的结构可以分为,开始条件,地址位,读写位,应答位,数据位,停止条件,具体如下所示;

开始条件

当主设备决定开始通讯时,需要发送开始信号,需要执行以下动作;

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

然后将SCL从高电平切换到低电平;

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

具体如下图所示;

地址位

通常地址位占7位数据,主设备如果需要向从机发送/接收数据,首先要发送对应从机的地址,然后会匹配总线上挂载的从机的地址;

I2C还支持10位寻址;

读写位

该位指定数据传输的方向;

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

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

ACK / NACK

主机每次发送完数据之后会等待从设备的应答信号ACK;

在第9个时钟信号,如果从设备发送应答信号ACK,则SDA会被拉低;

若没有应答信号NACK,则SDA会输出为高电平,这过程会引起主设备发生重启或者停止;

数据块

传输的数据总共有8位,由发送方设置,它需要将数据位传输到接收方。

发送之后会紧跟一个ACK/NACK位,如果接收器成功接收到数据,则设置为0。否则,它保持逻辑“ 1”。

重复发送,直到数据完全传输为止。

停止条件

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

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

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

具体如下图所示;

实际上如何工作?

第一步:起始条件

主设备通过将SDA线从高电平切换到低电平,再将SCL线从高电平切换到低电平,来向每个连接的从机发送启动条件 :

第二步:发送从设备地址

主设备向每个从机发送要与之通信的从机的7位或10位地址,以及相应的读/写位;

第三步:接收应答

每个从设备将主设备发送的地址与其自己的地址进行比较。如果地址匹配,则从设备通过将SDA线拉低一位以表示返回一个ACK位;

如果来自主设备的地址与从机自身的地址不匹配,则从设备将SDA线拉高,表示返回一个NACK位;

第四步:收发数据

主设备发送或接收数据到从设备;

第五步:接收应答

在传输完每个数据帧后,接收设备将另一个ACK位返回给发送方,以确认已成功接收到该帧:

第六步:停止通信

为了停止数据传输,主设备将SCL切换为高电平,然后再将SDA切换为高电平,从而向从机发送停止条件;

单个主设备连接多个从机

I2C总线上的主设备使用7位地址对从设备进行寻址,可以使用128()个从机地址。

请使用4.7K上拉电阻将SDA和SCL线连接到Vcc;

多个主设备连接多个从机

多个主设备可以连接到一个或多个从机;

当两个主设备试图通过SDA线路同时发送或接收数据时,同一系统中的多个主设备就会出现问题。

为了解决这个问题,每个主设备都需要在发送消息之前检测SDA线是低电平还是高电平;

如果SDA线为低电平,则意味着另一个主设备可以控制总线,并且主设备应等待发送消息。

如果SDA线为高电平,则可以安全地发送消息。

要将多个主设备连接到多个从机,请使用下图,其中4.7K上拉电阻将SDA和SCL线连接到Vcc:

如何编程

Talk is cheap. Show me the code.

参考了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; } }

总结

本文主要介绍I2C的入门基础知识,从I2C协议的硬件层,协议层进行了简单介绍;作者能力有限,难免存在错误和纰漏,请大佬不吝赐教。

责任编辑:lq

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

    关注

    2578

    文章

    55567

    浏览量

    794150
  • 集成电路
    +关注

    关注

    5464

    文章

    12695

    浏览量

    375824
  • I2C
    I2C
    +关注

    关注

    28

    文章

    1563

    浏览量

    131777

原文标题:再谈I2C!结合项目经验说说这项知识

文章出处:【微信号:gh_c472c2199c88,微信公众号:嵌入式微处理器】欢迎添加关注!文章转载请注明出处。

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

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    RK平台I2C开发:硬件原理到实战排查

    在嵌入式开发中,I2C 总线是连接外设的 “桥梁”—— 小到传感器、EEPROM,大到 LCD 驱动器、音频芯片,都离不开它的控制。而瑞芯微(Rockchip)系列芯片作为主流嵌入式方案,其 I2C 控制器的开发是很多工程师的必备技能。
    的头像 发表于 02-05 13:42 2644次阅读
    RK平台<b class='flag-5'>I2C</b>开发:<b class='flag-5'>从</b><b class='flag-5'>硬件</b>原理到实战排查

    瑞萨RA系列FSP库开发实战指南之I2C通讯协议的物理协议简介

    I2C通讯协议(Inter-Integrated Circuit)是由 Philips公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要USART、CAN等通讯协议的外部收发设
    的头像 发表于 01-21 10:10 4118次阅读
    瑞萨RA系列FSP库开发实战指南之<b class='flag-5'>I2C</b>通讯<b class='flag-5'>协议</b>的物理<b class='flag-5'>层</b>和<b class='flag-5'>协议</b><b class='flag-5'>层</b>简介

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

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

    基于FPGA的I2C控制模块设计

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

    基于FPGA的I2C通信协议设计

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

    AS32X601的I2C模块操作EEPROM详解

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

    I2C的总线协议

    用状态。 I2C 通信采用主从结构,并由主机发起和结束通信。主机通过发送 START 起始信号来发起通信,之后发送SLA+W/R 共 8bit 数据(其中,SLA 为 7bit 机地址,W/R 为
    发表于 12-15 08:07

    I2C死锁的问题

    产生8个时钟脉冲,然后拉低SCL信号为低电平,在这个时候,设备输出应答信号,将SDA信号拉为低电平。 如果这个时候主设备异常复位,SCL就会被释放为高电平。此时,如果设备没有复位,就会继续I2C
    发表于 12-04 06:00

    I2C的缺点介绍

    的最大数量。在设备数量较多的场景下,可能会出现地址冲突,需要采取地址复用或协议转换器等额外措施来克服限制。仔细规划和考虑设备寻址方案对于避免冲突并确保成功通信至关重要。 时钟拉伸: I2C 允许设备
    发表于 11-27 06:10

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

    , SCLK, CS) 全双工、主从 高速(可达几十 MHz) Flash、传感器、显示屏 硬件简单、速率高,但线多,扩展性差 I2C Int
    的头像 发表于 11-18 10:53 733次阅读

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

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

    第十八章 I2C通信测试

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

    第十六章 一文浅谈I2C

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

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

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