单片机基础--IIC通信协议

1.IIC总线是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。它在传输数据过程中有三种特殊类型信号,分别是:开始信号、结束信号和应答信号。

   区分UART通信:同样使用两根线进行数据传输,但UART通信中一根用于接收数据,一根用于发送数据,每次通信的时候只用到一根线。且其传输数据与时钟无关,因此称为异步串行通信,随时进行数据的接收和发送,SBUF寄存器存满时,则说明完成数据接收;想要进行数据发送时,只需把数据写入SBUF寄存器。

    IIC通信:IIC通信无论发送还是接收,都需要结合时钟SCL来进行数据SDA的传输,因此一次要使用两条线。传输数据与时钟有关,因此称为同步串行通信。

2.IIC通信的起始信号和停止信号

   时钟线SCL为高电平期间,数据线SDA由高电平向低电平变化——起始信号

   时钟线SCL为高电平期间,数据线SDA由低电平向高电平变化——停止信号

   

3.IIC通信的数据传输

   时钟线SCL为高电平期间,数据线SDA上的数据必须保持稳定。

  只有时钟线SCL信号为低电平期间,数据线SDA状态才允许变化。

  

4.数据线SDA上的数据一般先于时钟SCL发生变化

   原因:发生变化说明信号需要翻转,分两种情况(数据线SDA随你怎么翻)。情况1-1:当数据线SDA先发生变化,时钟线SCL再从1变为0,与上述第3点相违背,在时钟SCL为高电平时,数据线SDA并没有保持稳定,而发生翻转,这样的信号只会被当做是起始信号或停止信号;情况1-2:数据线SDA还是先发生变化,时钟线SCL从0变1,在时钟线SCL为0时,数据线SDA早已经完成了翻转,也就是说,在时钟线SCL为0时,数据线没有发生变化,那么在后来时钟线SCL为1时,所传输的数据则是数据线SDA上刚完成翻转后的数据。情况2-1:时钟线SCL由0变1,先于数据线SDA发生变化,时钟线SCL低电平时的状态内,数据线SDA没有发生任何变化,所以只在最后维持高电平有效,而在高电平后,再改变数据线SDA的数据,违反了上述第3点;情况2-2:时钟线SCL由1变0,先于数据线SDA发生变化,在变0之后,数据线SDA会完成信号的翻转。在之后得等时钟线SCL重新置1,才能确认数据线SDA的传输数据----那如果这样的话,不就又变成了数据线SDA先变化,时钟线SCL后变化的情况了??

   综上所述,去除掉违反IIC数据传输的规则的两则情况后,剩下的红色两种情况,则是现在第4点的最好说明...

5.IIC的数据读写和应答

   区分UART数据传输:UART数据传输先传低位,后传高位

    IIC数据传输:先传高位,后传低位

   主机写数据时,每发送一个字节,接收机需要回复一个应答位“0”,通过应答位来判断从机是否接收成功

   主机读数据时,接收一个字节结束后,主机也需要发一个应答位“0”,但是当接收最后一个字节结束后,需要发送一个非应答位“1”,发完这个非应答位“1”后,再发一个停止信号,最终结束通信。

   如果需要检测应答信号“0”,得先置高数据线SDA,如果数据线后来检测到应答信号“0”,则是应答信号存在的最好说明!

   如果需要检测非应答信号“1”,得先拉低数据线SDA,如果数据线后来检测到非应答信号“1”,也是非应答信号存在的最好说明!

6.IIC协议传输一位数据程序分析

void Delay(void)                               //在使用IIC进行通信的时候,需要控制传输数据的速度,这里的使用了4个机器周期的延时,而具体的延时由于包括了 函

{ //数调用时的压栈和出栈,而且受编译环境的影响,因此实际延时并不止4个机器周期

_nop_() ;_nop_() ;_nop_() ;_nop_() ;

}

void  IIC_Send_Byte(unsigned char byte)                   //有数据传入,类型为八位无符号字节型——传入数据 / 命令 / 地址

 

{
     unsigned char mask, i;                                             //定义两个八位无符号字节型变量,一个用以for循环,另一个用以把传入的十六进制数,以二进制方式提取各个位
 
     mask = 0x80;//再结合时钟线SCL时序变化,控制数据线SDA进行信号传输
     for(i = 0; i < 8; i++)
     {
          SCL = 0;//先把时钟线SCL置“0”,为了使数据线SDA数据能变化
          Delay();//数据传输的延时
          if((mask & byte) == 0)  //用mask十六进制数(以二进制的方式)与传入的数据byte取“与”,把传入的十六进制byte以二进制的方式提取位
     {
SDA = 0;//如果该位取“与”为0,则控制数据线SDA数据变为0
      }
          else   
          { 
  SDA = 1;  //否则如果该位取“与”为1,则控制数据线SDA数据变为1
    }
          mask >>= 1;//mask变量右移一位,假如第一次mask值为1000 0000,完成数据线SDA的一次输出后,mask的值为0100 0000,方便
          Delay();//继续提取第二位数据,数据传输的延时
          SCL= 1;//在时钟线SCL为1的时候维持数据SDA的稳定,便能确认传入的数据
          Delay(); //数据传输的延时
     }
     SCL = 0;//先置低时钟线SCL,才能拉高数据线SDA,用以检测后面的应答信号
     SDA= 1;
     Delay();
     SCL= 1;//下面对时钟线SCL的操纵则是用以检测应答信号的
     Delay();
     SCL= 0;
}
 

 

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值