GPIO模拟I2C-1

来源: 电子工程世界
新闻行业新闻

GPIO模拟I2C是嵌入式中较为常用的一种应用。各个地方有各种不同的做法,按照我自己的个人理解,最好是把I2C的各种状态分割开来,比如起始条件终止条件,读数据和写数据,然后根据具体的使用场合组合起来。


这里需要注意两点:一是SCL的波形并不规律,不能将它理解为方波,它本身只是一段段独立的波形。二是每段操作时,之前和之后的SCL和SDA波形是可以不用计较的;通常情况下I2C开始之前和I2C结束之后,两者都是高电平,而在正常工作时两者不受控制的情况下都是默认低电平。


(1)基础宏定义


#define GPIO_SCL             S3C2410_GPF3

#define GPIO_SDA             S3C2410_GPF0

#define GPIO_SDA_OUTP   S3C2410_GPF0_OUTP  //设定SDA输出

#define GPIO_SDA_INP      S3C2410_GPF0_INP     //设定SDA输入

#define GPIO_SCL_OUTP   S3C2410_GPF3_OUTP  //设定SCL输出


void I2C_SCL_OUTP( void )

{

      s3c2410_gpio_cfgpin(GPIO_SCL,GPIO_SCL_OUTP);

}


void I2C_SCL_Output(u8 value)

{

      if(value)

      {                                               

            s3c2410_gpio_setpin(GPIO_SCL,value); 

      }

      else

      {

            s3c2410_gpio_setpin(GPIO_SCL,value ); 

      }

}


void I2C_SDA_Mode(u8 v_mode)   //SDA输出方向

{

       if(v_mode)

       {                                               

              s3c2410_gpio_cfgpin(GPIO_SDA, GPIO_SDA_OUTP);  

       }

       else

       {

              s3c2410_gpio_cfgpin(GPIO_SDA, GPIO_SDA_INP);  

       }

}


void I2C_SDA_Output(u8 value)

{

       if(value)

       {                                               

               s3c2410_gpio_setpin(GPIO_SDA,value); 

       }

       else

       {

                s3c2410_gpio_setpin(GPIO_SDA,value ); 

       }

}


u8 I2C_SDA_Read(void)    //SDA读数据

{

       return s3c2410_gpio_getpin(GPIO_SDA); 

}


(2)基础段


void I2C_Init(void)

{

      I2C_SDA_Output(1);

      I2C_SCL_Output(1);      //默认拉高

}


void I2C_Wait(void)

{

      u16 i;

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

}


void I2C_Start(void)

{

      I2C_SDA_Output(1);

      I2C_SCL_Output(1);

      I2C_Wait();

      I2C_SDA_Output(0);

      I2C_Wait();

      I2C_SCL_Output(0);

}

void I2C_Stop(void)

{

      I2C_SDA_Output(0);

      I2C_Wait();

      I2C_SCL_Output(1);

      I2C_Wait();

      I2C_SDA_Output(1);

}

(3)读写单个字节的段


u8 I2C_Send_Byte(u8 bytedata)

{

      u8 i,ack;

      I2C_SDA_Mode(1);  //SDA输出

      I2C_SCL_OUTP();


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

      {

              if (bytedata & 0x80)

              {

                     I2C_SDA_Output(1);

              }

              else

              {

                    I2C_SDA_Output(0);

              }

              bytedata <<= 1;

            

              I2C_SCL_Output(1);

              udelay(3);

              I2C_SCL_Output(0);

              udelay(1);

       }    

  

        I2C_SDA_Output(1);  //release

        udelay(3);

       

        I2C_SDA_Mode(0);  //设定SDA输入

        I2C_SCL_Output(1);  

        udelay(3);

        ack = I2C_SDA_Read();   //读应答

        I2C_SDA_Mode(1);

        I2C_SCL_Output(0);

        udelay(3);

      

        return ack;  

}


u8 I2C_Receive_Byte(void) 

{

       u8 i;

       u8 bytedata = 0x00;

       u8 temp;

 

       I2C_SDA_Mode(0);

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

       {

             I2C_SCL_Output(1);

             udelay(3);


             bytedata <<= 1;

             temp = I2C_SDA_Read();

             printk("reda SDA'value is:%dn",temp);

 

             if (temp)

                   bytedata |= 0x01;

             printk("  bytedata is:%xn",bytedata);

             I2C_SCL_Output(0);

             udelay(1);

       }

       I2C_SDA_Mode(1);

       return bytedata;

}


(4)读写单个字节的I2C应用函数


u8 I2C_Byte_Write(u8 device_ID,u8 address,u8 bytedata)

{  

       u8 ack;

       printk("device_ID is:%xn",device_ID);

       printk("address is:%xn",address);

       printk("date is:%xn",bytedata);

       I2C_Start(); 

       ack=I2C_Send_Byte(device_ID);

       printk("ack is:%dn",ack);

       if(ack)


             I2C_Stop();

       I2C_Send_Byte(address);

       I2C_Send_Byte(bytedata);

       I2C_Stop();

       I2C_Wait();

       return 0;

}


u8 I2C_Byte_Read(u8 device_ID,u8 address)

{  

       u8 bytedata;


       I2C_Start();

       I2C_Send_Byte(device_ID);

       I2C_Send_Byte(address);

       I2C_Start();

       I2C_Send_Byte(device_ID+1);

       bytedata = I2C_Receive_Byte();  //读单个字节,不需要再发应答

       I2C_Stop();   

       return bytedata;

}


(5)类似可以完成读写多个字节的函数,暂不补充。


文章来源于: 电子工程世界原文链接

本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。