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

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

3天内不再提示

主机通过发送设备地址后由应答位确定该设备是否存在

lhl545545 来源:玩转单片机 作者:玩转单片机 2020-06-11 16:17 次阅读

I2C(Inter-Integrated Circuit BUS) 集成电路总线,该总线由 NXP(原 PHILIPS)公司设计,多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距离短,任意时刻只能有一个主机等特性。连接到总线的 IC 数量只是受到总线的最大负载电容 400pf 限制。

I2C 支持 0kHz~5MHz 的设备:

普通模式(100kHz)、快速模式(400kHz)、快速模式+(1MHz)、高速模式(3.4MHz)和超高速模式(5MHz)。

两根数据线:SDA,SCL,均为漏级开路结构。一般接上拉电阻,形成“线与”逻辑(只要一方为低电平,则此线即为低电平)。当 SDA,SCL 为高电平时,表示总线空闲。一般来说,主机发起传输之前都要检查总线的电平状态(称为仲裁),以确定是否进行数据传输(当总线上只有一个主机时,可以不用)。如果 I/O 口既能输入也能输出,可以配置成开漏输出,但是必须外接拉电阻;如果 I/O 不能配置成开漏输出,则可以转换 I/O 输入输出方向,输出采用推挽输出,输入使用上拉输入即可。注意使用转换方向的方式时必须先转换方向之后才开始释放总线。

支持多主控,但是同一时间只能有一个主控。每个设备都有自己的设备地址(共 7bit,有的是 10bit),用于区分挂在在总线上的设备,广播地址 0x00。最低位用于读写控制位,1 表示读数据,0 表示写数据。”

开始信号

当开始进行一次数据传输时,需要向从设备发送一个开始信号,表示数据传输开始。

SCL 为高电平期间,SDA 由高到低表示开始信号。

主机通过发送设备地址后由应答位确定该设备是否存在

结束信号

当结束一次传输时,需要发送结束信号

SCL 为高电平期间,SDA 由低到高表示结束信号。

(若主机在对一个从机操作之后,若主机希望继续占用总线进行新的数据传送,则可以不产生终止信号,马上再次发出起始信号对另一从机进行寻址)

主机通过发送设备地址后由应答位确定该设备是否存在

数据位

当传输数据位时,在 SCL 为低时改变 SDA,在 SCL 为高时保持 SDA 稳定。高位先传输。

主机通过发送设备地址后由应答位确定该设备是否存在

应答位

数据的第 9 位为应答位。

应答:第 9 个 CLK 时钟为高电平期间,如果 SDA 为为低电平,则为应答信号。

非应答:第 9 个 CLK 时钟为高电平期间,如果 SDA 为为高电平,则为非应答信号。

主机每向从机发送一个字节数据,从机都需要发送一个应答信号,而主机每接收一个字节都需要发送一个应答信号,当主机不准备接收下一个字节时,发送一个非应答信号,也就是说,非应答信号是由主机发送的,从机只能发送应答信号。应答位的数据状态则遵循“谁接收谁产生”的原则,即总是由接收器产生应答位

可以通过发送设备地址后由应答位确定该设备是否存在。

注意:任何在 SCL 为高电平期间的 SDA 上的电平改变都会被认为是起始或者停止信号,所以数据线 SDA 必须要在时钟线 SCL 为低电平时改变。

如下为传输一个字节的情况:

主机通过发送设备地址后由应答位确定该设备是否存在

所有数据传输的发起者都是主设备,从设备只能被动接受主设备的请求。

实际上发送一个字节之后就马上发送停止信号一般是不能实现一次完整的数据传输的,那么正常传输流程应该是怎样的呢?

因为 I2C 总线上可能挂在了很多设备,所以首先需要在总线上发送一个设备地址,并且指明本次传输的方向。然后又因为一个设备里面有很多寄存器,所以还要再发送一个寄存器地址,最后才是发送寄存器的内容。

• 发送数据(橘色为从机发送应答位)

• 接收数据(灰色部分为主机应答)

以上这些理论知识只是和 I2C 有关的,实际使用的时候根据驱动器件的不同又会有所不同。比如 AT2402,只能连续发送 8 个字节的寄存器内容(类似 8 字节缓存),下次再发送的话需要重新发送开始信号,另外,进行下一次数据的传输时,需要延时一段时间,让器件将 8 字节缓存的内容实际写入 EEPROM 中才可,否则会将缓存内容覆盖,导致写入错误。

主机通过发送设备地址后由应答位确定该设备是否存在

通过编写 I2C 驱动程序,并利用 KEIL仿真功能可以得到如下波形:

主机通过发送设备地址后由应答位确定该设备是否存在

这是一个发送设备地址 0xA0 的波形,因为没有从机,所以在第 9 个 CLK 的高电平期间 SDA 为高。当总线上有设备地址为 0xA0 的从机时,SDA 应被从机设置为低电平。

以上知识实际上是比较简单的,基础的,适合用于单主机的情况下,如果是多主机通信,远比单主机复杂的多,涉及到时钟同步和总线仲裁,有兴趣的同学可以自行研究。

更多关于 I2C 的问题,可以查阅《I2C 总线规范》。

关于总线死锁问题:

“总线死锁主要是因为主从设备中的主机异常复位造成从机始终处于应答状态(应答状态时 SDA 为低电平,只有在 SCL 变为低电平的时候,才会变为高电平,从而释放 SDA),解决方案可在链接中找到。”

STM32硬件 I2C 有缺陷,但是可以通过一些方法避免,具体寻找网上的方法。

一直以为可以连续写入数据,每写入一个数据加入写入延时,给 EEPROM 写入时间,当写完最后一个数据之后发送一个写入停止信号即可,可实际是上是必须要有一个停止信号,EEPROM 在收到这个停止信号后才会进行写写入操作,否则必然导致写入出错。正是因为有这样错误的认识,所以在读取数据的时候读出的数据和自己想要的数据不一致,而这个数据刚好用于指针索引,好巧不巧的是因为这指针错误的指向,刚好将某个函数指针地址改变了,导致程序一直运行不正常。后来花了半天时间调试,才发现了函数指针数据被更改。但是我又奇怪为什么我的程序又能运行(正是因为能运行而不是直接死在某一个地方,才让自己寻找 bug 的方向错了)。后来才想通,虽然我的函数指针指向错误,运行出错,但是因为我开启了看门狗,所以当函数运行出错后,程序无法喂狗,导致成程序自动复位,又重新运行了,但是表明上看程序又运行到起来了,实际上呢,它已经从程序的最开始重新运行了。记录此教训,以提醒后来人。

还有一点就是单字节写入数据效率特别低,如果写入数据超过两个字节,在内存足够的情况下,最好开启一个页缓冲区,以加快写入速度。但是如果你认为写入数据是你可以接受的,那么不需要这个页缓冲区了,毕竟一旦加入页缓冲,也是要加入不少逻辑去维护的。

再介绍一个页写入的算法,之前看了一些页写入的算法,发现实在是太麻烦了。我就在想肯定有一种更为简单的算法的,直到这次更新笔记的时候才偶然发现了该算法。

主机通过发送设备地址后由应答位确定该设备是否存在

自行理解吧,不是很难的逻辑思路。
责任编辑:pj

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

    关注

    9

    文章

    1525

    浏览量

    63561
  • 数据线
    +关注

    关注

    8

    文章

    261

    浏览量

    37056
收藏 人收藏

    评论

    相关推荐

    STM8L I2C程序第二次数据通信失败是什么原因导致的?

    主机速度设置为100kbps的情况下,程序调时发现相同的数据连续从主控发给从机,第一次通信能成功,第二次通信时设备地址可正常发送,从机也有应答
    发表于 04-16 07:12

    stm i2c的主机10地址寻机,从机7地址,能找到吗?

    stm i2c的 主机10地址寻机,从机7地址,能找到么? 开发时都用的10
    发表于 04-10 07:10

    虚拟机的ip地址主机一样吗

    虚拟机的ip地址主机一样吗  虚拟机的IP地址主机的IP地址通常不相同。虚拟机是在主机
    的头像 发表于 03-26 15:34 379次阅读

    【米尔-瑞萨RZ/G2UL开发板】2.IIC设备读取陀螺仪数据

    I2C 设备的器件地址访问指定的 I2C 设备了,一个 I2C 总线连接多个 I2C 设备。 帧起始:I2C 通信起始标志,通过这个起始
    发表于 01-28 17:22

    通过RS232转Profinet网关连接PLC与RS232协议设备的步骤

    需要根据您的PLC型号和通信协议设置相应的通信参数,如波特率、数据、停止等。启动配置软件并加载GSD文件。根据您的设备和网关型号,您需要加载相应的GSD文件以识别网关设备。在博图软
    发表于 01-26 14:46

    蓝牙设备地址的类型 蓝牙Random静态设备地址的生成与设置

    所有蓝牙设备都应具有一个蓝牙设备地址 (BD_ADDR),该地址(及其地址类型)可以唯一地(一定范围内唯一)标识该
    的头像 发表于 01-03 09:37 1223次阅读
    蓝牙<b class='flag-5'>设备</b><b class='flag-5'>地址</b>的类型 蓝牙Random静态<b class='flag-5'>设备</b><b class='flag-5'>地址</b>的生成与设置

    stm32 usb 主机发送 pid in的原理和实现方法

    数据包的类型。在USB主机发送数据时,PID IN表示主机请求从设备读取数据。 为了实现STM32 USB主机
    的头像 发表于 12-20 15:56 534次阅读

    什么是子网掩码?如何根据掩码来确定ip地址网段?

    什么是子网掩码?如何根据掩码来确定ip地址网段?如何判断两个IP地址是否在同一个网段? 子网掩码是用于划分网络中主机和网络
    的头像 发表于 12-07 09:40 1141次阅读

    AT32F4xx I2C使用10地址进行主机接收从机发送

    AT32F4xx I2C使用10地址进行主机接收从机发送演示AT32F403Axx I2C使用10
    发表于 10-27 08:26

    AT32F4xx I2C使用10地址进行主机发送从机接收

    AT32F4xx I2C使用10地址进行主机发送从机接收演示AT32F403Axx I2C使用10
    发表于 10-27 07:50

    终于搞清了:SPI、UART、I2C通信的区别与应用!

    的7或10序列,用于主从设备之间的地址识别。 读/写:一,如果
    发表于 10-07 17:01

    访问PCI/PCIe设备的流程

    主机读取设备配置信息、分配空间 主机上的程序访问 PCI/PCIe 设备,读出配置信息。 分配地址空间:注意,分配的是 PCI/PCIe
    的头像 发表于 07-30 09:44 1047次阅读

    I2C先写后读是什么

    加一个 R/W 位,1 为读,0 为写)。等待从机产生应答信号。然后发送寄存器地址,告诉从机读哪一个寄存器。紧接着,收到应答信号后,主设备
    的头像 发表于 07-22 15:58 1307次阅读
    I2C先写后读是什么

    是否计划在ESP-32系列设备上支持ESP BASIC?

    和 54102 uC)。鉴于我在 ARMbasic 中开发,我在 interwebz 周围搜索以查找存在哪些固件选项,适用于我已经确定的各种 ESP 设备(ESP8266 用于非 BT/非 BLE
    发表于 05-10 08:07

    Modbus从设备如何回应主机的消息及VB的小问题?

    Modbus从设备如何回应主机的消息?就是如何主机发往从设备要求查询地址4001地址的数据,从
    发表于 05-05 16:10