GPIO模拟I2C1

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:%d\n",temp);
 
             if (temp)
                   bytedata |= 0x01;
             printk("  bytedata is:%x\n",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:%x\n",device_ID);
       printk("address is:%x\n",address);
       printk("date is:%x\n",bytedata);
       I2C_Start(); 
       ack=I2C_Send_Byte(device_ID);
       printk("ack is:%d\n",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)类似可以完成读写多个字节的函数,暂不补充。



原文地址:https://www.cnblogs.com/yuzaipiaofei/p/4124347.html