IIC总线协议不定义数据字节内部位序位序由应用层根据需要定义。IIC总线数据帧长度固定为8位。1.1 数据传输过程中SCL为低电平时SDA上的数据是无效的。SCL为高电平时SDA上的数据是有效的。SDA电平必须在SCL为高电平时保持不变SDA电平变化只能出现在SCL为低电平时。除了起始信号和停止信号主机和从机在改变SDA电平时必须确保SCL处于低电平。正常的情况下SCL和SDA都应使用开漏输出即使主机和从机的IO口都处于输出模式且输出电平不同也不会烧坏IO口。单主通信SCL不使用开漏输出影响不大因为SCL信号单向传输由主机IO输出发出时钟从机IO输入读取时钟。SDA信号双向传输不使用开漏输出可能会出错烧坏IO口。一字节数据传输完成后双方需要改变SDA信号传输方向来传输应答和非应答信号然后又要再改变SDA方向继续传输数据。若切换传输方向时代码被中断打断导致SDA本应改为输入的一方长时间处于输出模式双方SDA都输出一个输出高电平一个输出低电平没有电阻限流电流过大会烧坏IO口。IIC总线标准规定最慢的传输速率是100Kbit/s每个数据位传输耗时10微秒。1.2 数据传输过程主机发完起始信号和寻址命令后检测是否有应答信号若有应答则继续传输数据。若无应答信号则从机可能有故障或者地址有错主机须发送停止信号结束传输。1.2.1 主机只写主机发送地址并收到应答后继续发送数据。若从机发送非应答信号不管数据是否发完主机都发送停止信号结束传输。主机数据发完后不管从机是否发送非应答信号都发送停止信号结束传输。1.2.2 主机先写再读主机发送地址并收到应答后发送命令从机根据命令返回数据最后主机发送非应答信号和停止信号。1.2.3 主机只读主机发送地址并收到应答后从SDA读取数据最后发送非应答信号和停止信号。1.3 起始和停止信号1.3.1 起始和停止信号如何发出若SCL为高电平时SDA电平发生变化则是在发起始和停止信号。由高变低为起始信号由低变高为停止信号。起始信号和停止信号不占用SCL时钟即SCL电平可以不变。数据传输方向随寻址命令一并发出发送寻址命令之前必须先发起始信号。数据传输过程中主机若想改变传输方向可以重新发送寻址命令但是在发寻址命令之前必须先发重复起始信号。也就是说停止信号之前可以有多个起始信号和寻址命令。1.3.2 起始信号起始信号只能由主机发出因为SCL时钟只能由主机发出数据的传输由主机首先发起。主机发出起始信号后接着会发送寻址命令。从机如何检测起始信号从机一直检测SDA线的电平当检测到SDA下降沿时若SCL为高电平则识别为起始信号。若SCL为低电平则不做任何处理因为SCL为低电平时允许SDA电平变化。1.3.3 停止信号停止信号只能由主机发出。主机不再传输数据时发出停止信号。主机发送数据时若数据发送完毕不管从机回复的是应答信号还是非应答信号主机都可以发出停止信号。主机接收数据时若不想再接收数据可以先回复非应答信号等待从机释放SDA后发出停止信号。从机如何检测停止信号从机一直检测SDA线的电平当检测到SDA上升沿时若SCL为高电平则识别为停止信号。若SCL为低电平则不做任何处理因为SCL为低电平时允许SDA电平变化。根据IIC协议规范只有主机能发出停止信号从机不能发出停止信号。主机向从机读取数据从机数据发送完毕主机仍发送应答信号此时从机要如何处理这种情况的结果大概是从机无数据可发只能保持SDA电平不变或者释放SDA控制权等待停止信号主机若继续读数据则只能读到错误的数据。1.4 应答和非应答信号应答和非应答信号与数据位一样需要占用一个SCL时钟。发送信号前须先拉低SCL延时几微秒操作SDA延时几微秒再拉高SCL。应答则拉低SDA表示还可以继续接收数据。非应答则拉高SDA表示不想再继续接收数据发送端不能再发数据。非应答信号之后一般会发送停止信号。1.4.1 主机发从机收从机发应答主机把SDA改为输入延时几微秒然后拉低SCL发出SCL时钟延时几微秒。从机检测到SCL的下降沿后把SDA改为输出然后操作SDA。应答则拉低SDA非应答则拉高SDA。主机拉高SCL延时几微秒检测SDA的电平判断从机发出的是应答还是非应答。1.4.2 主机收从机发主机发应答这种情况从机何时把SDA改为输入来读取应答信号可以有两种方式1从机发出第8位数据后延时几微秒然后主动把SDA改为输入。主机读取SDA后拉低SCL发出SCL时钟延时几微秒操作SDA。这种方式的缺点是不能保证最后一位数据一定能被主机读取从机可能会在主机读取SDA之前把SDA改为输入。这种缺点难以改进若从机把发完最后一位数据到SDA改为输入的延时设置太长则双方SDA可能同时处于输出模式。2主机读取第8位数据后拉低SCL发出SCL时钟延时几十微秒后把SDA改为输出然后操作SDA发出应答。从机检测到SCL下降沿后把SDA改为输入。这种方式的缺点是主机和从机的SDA可能同时处于输出模式从机在把SDA改为输入前代码中断打断导致SDA长时间处于输出模式。改进办法是主机把拉低SCL到SDA改为输出之间的延时设置长一点如延时几百微秒让从机有充足的时间把SDA改为输入。1.5 从机如何发送和接收数据从机会一直检测SCL和SDA的电平变化。1.5.1 起始信号在未开始数据传输时从机要一直检测SDA电平等待起始信号收到起始信号后发送应答。1.5.2 从机发送数据1一直检测SCL的下降沿检测到SCL的下降沿后操作SDA的电平。2发完一字节数据检测到SCL的下降沿后SDA改为输入等待SDA电平变化。3检测到SDA到下降沿时检查SCL电平状态。若SCL为低电平则识别为应答的电平变化延时几微秒读取SDA状态。若为SCL高电平则识别为重复起始信号。停止信号前可以出现重复起始信号可能是因为主机需要改变传输方向。4检测到SDA到上升沿时检查SCL电平状态。若SCL为低电平则识别为非应答的电平跳变延时几微秒读取SDA。若SCL为高电平则识别为停止信号数据传输结束。1.5.3 从机接收数据1一直检测SCL的上升沿检测到SCL的上升沿后延时几微秒然后读取SDA的电平。2收完一字节数据后等待SCL下降沿发送应答信号。3发完应答信号后从机要一直等待SDA上升沿收到SDA上升沿时检测SCL电平。若SCL为低电平则识别为下一位数据的电平跳变延时几微秒读取SDA。若SCL为高电平则识别为停止信号。4发完非应答信号后等待SDA上升沿即停止信号。SCL被拉低延时几微秒SDA被拉低延时几微秒SCL被拉高延时几微秒SDA被拉高停止信号到来。1.6 主机如何发送和接收数据主机会负责发出SCL时钟信号控制总线时序在需要时检测SDA的电平变化。1.6.1 发出起始信号主机负责发出起始信号。数据传输方向由主机在起始信号后发送的地址数据中指定。1.6.2 主机发送数据1发完最后一位数据后延时几微秒拉低SCLSDA改为输入。2延时几微秒检测SDA电平。若SDA为低电平则识别为应答信号。若SDA为高电平则识别为非应答信号。3继续发送数据拉低SCL延时几百微秒让从机有充足的时间把SDA改为输入SDA改为输出。4发出停止信号拉低SCL延时几微秒拉低SDA延时几微秒拉高SCL延时几微秒拉高SDA。1.6.3 主机接收数据1收完一字节数据后拉低SCL延时几百微秒从机释放SDA。2发送应答信号SDA改为输出拉低SDA延时几微秒拉高SCL延时几微秒。继续接收数据SDA改为输入延时几微秒拉低SCL。3发送非应答信号。4发出停止信号拉低SCL延时几微秒拉低SDA延时几微秒拉高SCL延时几微秒拉高SDA。