通信协议:IIC


      我们经常在各种开发板的介绍中看见,支持UART,SPI,IIC,CAN通信等等,这些协议在单片机的应用里面非常简单,可能是一个简单的函数:SPI.transfer(),Wire.write()就解决了问题。但是那么这些函数在硬件层次到底是如何实现的呢?想了解这个,首先要了解一些关于单片机对于电路的控制方式。
      控制器的输入输出口通常只能输出高低电平。所谓高低电平也就是用高电平代表1(输出口有正电压),低电平代表0(通常电压为0)。
 
     通信协议的作用是什么?
 
      高低电平的变换对应的0和1,可以组成一组二进制数,这组二进制数就可以传递信息,收到高电平就当作收到1,收到低电平就当作收到0,于是这个时候接收这个信号的芯片就好像在做一个电报接收员一样把一连串的010101信号对应着一个信号表翻译成具体的指令。说到这里就有了一个问题,如果要连续发送2个0信号怎么发?
      有两个解决办法:
      1 、限定每个信号的时间,比如规定高低电平持续时间为1ms,那么2ms低电平就代表2个0.   (UART基本是用的这个原理)
      2 、多添加一个信号线,当这个信号线上的电平发生变化的时候读入之前信号线上的信号(后来这个新加的信号线就叫时钟线,大部分协议都是用的这种方式)
       这两种方式各有利弊,第一种只需要1根线,同样由于只有一根线,那么为了减少误传输只能降低传输速度,第二个需要2根线,但可以以很快的速度进行数据传输。也可以再加一组线组成全双工模式(发送数据的同时还可以接收数据)。
什么是IIC
 
      IIC是以上述第二种方式运行的一套协议。他由3根线组成分别叫SDA,SCL,GND。SDA为数据线,SCL为时钟线,GND为参考电平,就是0电平,这个线的主要功能是提供一个参考的电压,告诉IC到底多少为0V电势(通常我们说的多少V是说的电势差及电压)。
      先说下为 什么要使用协议,有人可能会想,按照之前所说,当时钟线上电平发生改变(我们形象的称之为上升沿和下降沿)时读入数据线的0或1不就好了,为什么还要什么协议呢?
       说说我个人理解,之所以有协议是为了更加稳定也更加的可靠。举个例子,家里敲门,大家可能都有这样的经历,有时候听到敲门然后出门,发现门外并没有人,这就有2个可能,一个是外部原因:外面有什么人或者物不小心敲到了门。或者是内因:自己不小心听错了。无论是什么原因,都造成了我们信息的错误获取(认为有人敲门),所以我们想到一个方法,以后每次敲门都先敲1下,然后连续敲3下,以此表示我要进来这个信号,这样里面的人听到有人敲门后再听到3次短促的敲门才去开门,这样外因或者内因产生的错误都将大大减少,我认为这是发明协议的最初原因。
      下面说说什么叫IIC协议:
       这种总线类型是由飞利浦半导体公司在八十年代初设计出来的,主要是用来连接整体电路,IIC是一种多向控制总线,也就是说多个芯片可以连接在一起,同时每个芯片都可以对其他的芯片进行数据传输。这种方式简化了信号传输总线。但是这种方式也增加了一个传送数据的步骤,就是需要对信号线上的每个芯片定义一个逻辑地址,让芯片知道这个信息是发给他的(类似电话号码的功能)。
      IIC 协议包含开始信号:START(类似于第一下敲门)、应答信号:ACK(里面的人给予回应)、无应答:NACK(另一种回答)、停止信号:STOP(表示数据发送结束) 这几个东西,当然还少不了普通的数据发送。尽管协议中规定START必须,其他几个非必须,但实际上其他三个仍旧非常重要。
IIC的具体形式
       IIC 发送数据是8位数据(即8个0或1,也就是一个字节)。整个协议发送的顺序如下:
       通常我们为了方便把设备分为主设备和从设备,我的划分方法是谁控制时钟线(即控制SCL的电平高低变换),谁就是主设备。

  •        主发从收:主机发送  START 信号-> 主机发送地址 -> 从机发送ACK应答 -> (主机发送数据 -> 从机发送ACK应答 (循环)) -> 主机发送STOP信号 或 主机发送 START 信号启动下一次传输
  •        主收从发:主机发送 START 信号-> 从机发送发地址 -> 主机发送ACK应答 -> (从机发送数据 -> 主机发送ACK应答 (循环)) -> 接受至最后一个字节时,主机发送NACK -> 主机发送 STOP 信号或 主机发送START信号 启动下一次传输
      看下面一段Arduino的代码:
   
      Wire.beginTransmission(0x04);
      Wire.write(0xaa);               
      Wire.endTransmission();  

 

      0x 代表的是16进制数转换为2进制为  0x04=0100b 0xaa=10101010b
       以上是一段主发从收的代码。
      Wire.beginTransmission(0x04);//执行了3步  主机发送 START信号 -> 主机发送地址-> 从机发送 ACK应答  后面的0x04就是从机的地址
      Wire.write(0xaa);// 执行了2步  主机发数据 -> 从机发送ACK应答 (循环) 参数0xaa就是发送的数据
      Wire.endTransmission();  // 执行了最后一步 主发送STOP信号

IIC底层原理

1:STTART&STOP

       我们要往底层走一步,每个数据的发送,START ACK NACK STOP到底是怎么以电平变化的方式发送的呢?请看下面这个图:

 

 

 

 

       这个图在工程上我们叫他时序图,这个图讲的正是START,和STOP的发送方式。
       看一个虚线的地方我们很容易的看到所谓START其实就是在SCL,SDA都为高的时候把SDA变为低电平(拉低)嘛,和敲门一样的道理。
       同样第二个虚线的地方,STOP就是在SDA为低,SCL为高的时候把SDA变为高电平(拉高)。
2、DATA INPUT

       下面我们可以来看看IIC协议是如何传输数据的,如下图

       在IIC协议中数据传输也很简单,IIC在SCL(时钟线)为高电平时对SDA进行读取(digitalRead,即采样)读到高电平即收到一个1,读到低即收到一个0。现在只剩下应答信号ACK NACK,了解了这2个就算是完全了解了IIC协议。

3、ACK&NACK

      所谓应答就是告诉发送数据的一方,我收到了数据。所以说到底,应答也是一种数据,说白了就是0或者1,只不过换了一个发送方。具体地说就是就是A对B发送了8位数据之后,这时B会给A返回一个1位的数据,非0则1,当返回0在IIC协议里称为ACK,返回1称为NACK,但是请注意这里与发送数据有一点不同的地方,即发送的时候SCL,SDA的信号都是有发送方(主机)控制的,但是在ACK的时候SCL是主机控制的,SDA接收方(从机)控制的,所以反应在程序上,你所做的是等!当你控制MCU拉低SCL之后,需要不断读取SDA的值,直到其被从机拉低,才可以认为从机发送了ACK信号。
       至此关于IIC的介绍已经全部完成了,下面给大家一个图,让大家对于IIC能有一个更加直观的认识:
     

 

 

 

 

 

 

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM