I2C-update2016.5

一些细节上的东西容易忘记,其实貌似也不需要记那么多,需要用的时候调用就可以了;
不过还是记一下吧,以后可能会看。

在看源代码的时候发现I2C函数里面有一些不懂,搜了一下发现是时序协议不清楚。
ref@http://www.cnblogs.com/BitArt/archive/2013/05/28/3103917.html

I2C-update2016.5_第1张图片
  • 空闲状态:
    SDA和SCL都为高电平。

此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。

所以,在传输完一个Byte之后:

 //if SDA==SCL==1,I2C is free
    BS004_I2C_SDA_1; //free I2C
    BS004_I2C_NOP;
    BS004_I2C_SCL_1;
    BS004_I2C_NOP;   
  • 每次传输一个bit,时钟总线SCL都需要跳变一下
    这个跟数电里面差不多吧,数据要跟着时钟走。时钟就是脉搏,就是节拍器。

并且数据的跳变也是有要求的:

I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定;
只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。

所以要人为的做这个跳变:

    for(i=0;i<8;i++)
    {  
        if(bs004_i2c_data&0x80) BS004_I2C_SDA_1;  //set bit
        else BS004_I2C_SDA_0;
            //
        bs004_i2c_data<<=1;
        BS004_I2C_NOP;
            //
        BS004_I2C_SCL_1;  //why do we do this?
        BS004_I2C_NOP;
        BS004_I2C_SCL_0;
        BS004_I2C_NOP; 
    }
  • ACK应答

应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。 对于反馈有效应答位ACK的要求是,接收器在第9个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。 如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放SDA线,以便主控接收器发送一个停止信号P。

  • 协议
    在发送start信号之后,我们需要发送器件的地址+读/写 信号

不过如果我们要写的地址不是器件的起始地址呢?我们在后面再发送一个偏移量。

虽然这一点并没有在标准的协议中看见,但是有人这么使用:

1、主机向所要访问的设备发送一个起始信号,标志着I2C通信开始,同时主机把设备地址和“写”操作命令发出,若操作成功,设备会发送一个应答信号。
2、在随机“写”操作的时候,一般发送的第一个数据作为偏移地址。在偏移地址发送成功后,设备会送发一个应答信号。同时产生一个中断,中断处理程序把刚得到的偏移地址保存起来。
3、主机向所要访问的设备再次发送一个起始信号,同时主机把设备地址和“读”操作命令发出,此时设备产生一个中断,中断处理程序把刚刚保存起来的偏移地址寻址,把需要发送的数据得到。操作成功后,发送一个应答信号,标志着准备发送数据给上位机。
4、在设备发送一个应答信号之后,产生一个中断信号,把刚刚准备好发送数据发送出去

你可能感兴趣的:(I2C-update2016.5)