GPIO模拟I2C-1

发布时间:2024-07-25  

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)类似可以完成读写多个字节的函数,暂不补充。


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

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>