zoukankan      html  css  js  c++  java
  • 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)类似可以完成读写多个字节的函数,暂不补充。



  • 相关阅读:
    当统计信息不准确时,CBO可能产生错误的执行计划,并在10053 trace中找到CBO出错的位置示例
    ruby class_eval的使用
    ruby修改TXT文件
    ruby格式化
    VIM常用命令集合
    Watir::IE.attach与IE7选项卡的设置关系
    ruby 连接mysql数据库
    AutoIT删除Internet临时文件
    watir学习之—如何遍历页面所有的超链接
    watir如何取到元素的css属性
  • 原文地址:https://www.cnblogs.com/yuzaipiaofei/p/4124347.html
Copyright © 2011-2022 走看看