×
单片机 > 单片机程序设计 > 详情

C51IO口模拟I2C总线驱动AT24C16 (I2C协议部分)

发布时间:2020-07-08 发布时间:
|

/* 

名称:C51IO口模拟I2C总线驱动EEPROM(AT24C16)


说明:I2C总线是由Philips公司开发的一种简单、半双工同步串行总线。它只需要两根线(SCL、SDA)即可在连接于总线上的器件之间传送信息。其中SCL时钟总线用于同步数据,SDA数据总线用来发送数据(或地址)。


和SPI总线不同的是,I2C总线通过在SDL上发送存储器的地址用来选中总线上对应的设备。关于具体的通信协议这里就不说了,无非是通过IO口模拟产生所需信号 

(如通信开始信号是SCL为高时,SDA产生一个下降沿信号。) 驱动程序中有 具体的说明。 

*/



//定义I2C相关变量

sbit     SCL=P2^1;     //I2C  时钟 

sbit     SDA=P2^0;     //I2C  数据 


bit ack;                 /*应答标志位*/



static void Delay_I2C() /*延时函数*/

{

    _Nop();

    _Nop();

    _Nop();

    _Nop();

    _Nop();

}



//启动I2C总线,即发送I2C起始条件:SCL为高电平期间,SDA出现下降沿

void Start_I2C()

{

    SDA = 1;

    Delay_I2C();            //延时一段时间

    SCL = 1;

    Delay_I2C();

    SDA = 0;

    Delay_I2C();


    SCL = 0;                //???           /*钳住I2C总线,准备发送或接收数据 */

    Delay_I2C();        



}


//停止I2C总线信号,即发送I2C停止条件:SCL为高电平期间,SDA出现上升沿

void Stop_I2C()

{

    SDA = 0;

    Delay_I2C();            //延时一段时间

    SCL = 1;

    Delay_I2C();

    SDA = 1;

    Delay_I2C();

}



//检验应答信号

bit CheckAck(void)

{

        bit val;

        /*发送完一个字节后检验设备的应答信号*/

        SDA=1;

        SCL=1;

        Delay_I2C();

        val=SDA;

        Delay_I2C();

        SCL=0;

        Delay_I2C();


        return val;

}



//通过I2C总线发送一个字节

bit  SendByte_I2C(unsigned char  c)

{

    unsigned char i = 0;


    SCL = 0;                //???           /*钳住I2C总线,准备发送或接收数据 */

    Delay_I2C();        


    for(i = 0;i<8;++i)

    {

        if(c<

            SDA = 1;

        else

            SDA = 0;


            SCL = 1;    /*置时钟线为高,通知被控器开始接收数据位*/

            Delay_I2C();    

            SCL = 0;

            Delay_I2C();            //???


    }


    return CheckAck();      //返回接收方的确认结果

}



//从I2C总线中接收一个字节的数据

unsigned char RecByte_I2C()

{

    unsigned char  retc;

  unsigned char  BitCnt;


  retc=0; 

  SDA=1;                       /*释放总线*/

  for(BitCnt=0;BitCnt<8;BitCnt++)

    {


        SCL=0;                  /*置时钟线为低,准备接收数据位*/

        Delay_I2C();

        SCL=1;                  /*置时钟线为高使数据线上数据有效*/

        Delay_I2C();

        retc=retc<<1;

        if(SDA==1)retc=retc+1;  /*读数据位,接收的数据位放入retc中 */

        Delay_I2C(); 

    }

        SCL=0;    

        Delay_I2C();

        return(retc);

}



//发送应答信号

void Ack_I2C(bit ack)

{

    if(ack==0)

        SDA=0;              /*在此发出应答或非应答信号 */

  else

        SDA=1;

  Delay_I2C();     

  SCL=1;

  Delay_I2C();

  SCL=0;                     /*清时钟线,钳住I2C总线以便继续接收*/

  Delay_I2C(); 

}





『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32中断向量表的位置.重定向