iic通信底层讲解
文章目录
-
- 概要
概要
在MCU的使用中我们经常会用到各类通讯,比如串口通信 iic通信 spi通信 can通信等等,某些通信我们想使用时只需要略微懂其原理就可以开始使用 比如串口通信 而iic通信却比较麻烦 因为iic是有两种的 一种硬件iic,一种软件iic,我们某些传感器用的是软件iic 当我们尝试将软件iic移植到STM32的硬件iic时,经常会出现问题或者看不懂厂商给的数据手册 所以对于iic底层的理解尤为重要,本篇文章将从iic通信的底层原理进行讲解
整体架构流程
我们先要了解一个概念是时序图,时序图代表了单片机内部的通信原理,学会看时序图是我们理解通信最为基础也是最为重要的一个点,所以我们先补充一下时序图怎么看如何看
1.单信号时序图
如下就是一个最简单的时序图,我们的横坐标表示时间,纵坐标表示电压大小,因为我们的单片机是数字电路,所以时序图中的电平也就只有两种状态 高电平和低电平
上图中的时序图是一种理想时序图但在实际的电路中时序的变化并不是突变的 它从低电平变换到高电平是有一个过渡的时间的,所以在某些时序图中表示方法是中间有一段过渡时间的
2.多信号时序图
多信号的时序图是由两个信号来决定的,比如在下图中有起始信号和终止信号而中间SDA段的上下段,代表其信号由实际数据内容决定电平状态
iic总线时序图的理解方式
在下图中 有两条线,一条信号线一条数据线,数据线的改变必须以信号线的改变为前提(我们后面会详细说明),
我们先看上面这幅图中的第一个1,这个1代表第一个高电平信号,后面的9代表第九个高电平信号
再来看第二根线 这条线中的 0 1分别代表高低电平,然后为了让我们知道信号是谁发出的 我们最下面那根线就代表了 信号的发出方,比如刚开始的时候 信号是由Master(主机)发送的,过了一会信号是由从机LM75发出的
现在我们开始iic驱动的书写
如下就是我们iic的硬件连接图
有了这样的硬件连接后,我们在iic中规定数据线SDA 高电平时为1,低电平时为0(二进制)
有了这样的规定我们就可以根据硬件高低电平的变化来代替二进制数字信号的发送实现通信
但是在这样的规定下就会出现一个问题,如下图我们无法知道到底发送了多少个1,因为在图中的一段都是高电平,我们完全不知道在这个高电平内 有多少个信号1
所以这个时候我们引入时序图,只有在时序线变化的过程中我们的数据线SDA才能跟着变化,然后我们让数据线以固定的频率拉高拉低也就是变化 这个变化的频率就决定了通信总速度
然后我们现在以具体的实例进行讲解,比如我们这个时候要发送8位数据 10101111
我们按照上面的理论发送完八位数据 (你可以在图中看出我们的SDA想要进行有效发送,就必须在SCL线处于高电平的时候)
八位数据被发送完成后,还有一个问题也就出现,我们只有主机在进行单一的发送,我们不知道从机是否进行到有效的接受,所以我们必须引入一种从机的反馈模式来保证从机有真正的收到主机发送的信号 所以我们以八个数据做为一个节点,在接受完八个数据之后 我们的第九个数据(相对SDA) 或者是第九个工作期间(相对SCL),我们会把SDA的权限交给从机来控制,我们知道的是SDA数据线的控制权在发送八位信号的时候是由主机控制的,到了第九位信号的时候我们把它的控制权限交给从机 若SDA为高电平则代表从机无应答 也就代表从机没有正常接受到数据
如果是低电平则代表有应答 则代表从机正常接收到信号
有了应带信号后,还有一个问题没有解决,那就是我们的从机并不知道什么时候是第一个工作期间,因为SCL是一直产生信号的
这个时候我们在第一个工作期之前添加了起始信号,在最后一个工作期之后添加了停止信号,但是现在问题又出现了 如何表示这个起始信号和停止信号?用高低电平表示显然是不对的,因为我们的高低电平已经用来表示了二进制信号 1和0,那么我们该如何解决这个表示问题呢?
单片机的发明者引出了一个天才的想法,用变化信号表示 起始信号和停止信号
所以iic规定,SDA从1变成0 代表第一个工作期的开始也就是起始位,SDA从0变成1 代表信号发送完成 也就是结束位
所以总的工作时序图也就出来了
现在我们从数据层面研究iic
单片机发送数据
从机发送数据
我们知道了发送和接受的不同,但是这个时候又有一个问题出现了 从机如何知道是要读信号还是写信号
那么这个时候我们在第一组数据的最后一位引入读写位
这里又会出现一个新的问题就是每个从设备中会有多个数据分别存在内部的多个寄存器中,可以把寄存器理解为一个个柜子,每次读写多个数据都要从第一个寄存器的盒子开始读写,假如我们想写第四个寄存器中的数据,我们依旧要从第一个寄存器开始写 连续写四个才行。
所以我们iic设计了一个指针功能,我们把它设计在第二组数据 你可以理解为第二组数据的数据值就代表了我们要读写的起始寄存器是那个寄存器 比如下面这个程序的第二组数据就是00000100 这就代表我们从第四个寄存器开始写数据 至于只写第四个还是接着往后写,我们要根据实际情况来写
现在我们来看读操作和写操作有一点不同
先发一个起始位 然后再发指针值,然后再重新发一次起始位 然后开始读数据
解决完了数据的发送和接收,我们现在的问题就是解决一个主设备多个从设备的通信顺序问题,从设备如何知道主设备到底是给那个从设备通信
解决这个问题的方法就是给每个不同的设备设计一个设备码 每个从设备的设备码都是独一无二的,同时iic规定 第一组DATA数据的前七位二进制数就代表着器件地址