Chinaunix首页 | 论坛 | 博客

OS

  • 博客访问: 2280202
  • 博文数量: 691
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2660
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-05 12:49
个人简介

不浮躁

文章分类

全部博文(691)

文章存档

2019年(1)

2017年(12)

2016年(99)

2015年(207)

2014年(372)

分类: LINUX

2014-11-14 21:03:20

原文地址:linux平台上GPIO模拟I2C 作者:deem_passion

       GPIO模拟I2C是嵌入式中较为常用的一种应用。各个地方有各种不同的做法,按照我自己的个人理解,最好是把I2C的各种状态分割开来,比如起始条件终止条件,读数据和写数据,然后根据具体的使用场合组合起来。
       这里需要注意两点:一是SCL的波形并不规律,不能将它理解为方波,它本身只是一段段独立的波形。二是每段操作时,之前和之后的SCL和SDA波形是可以忽略的;通常情况下I2C开始之前和I2C结束之后,两者都是有上拉的高电平,而在正常工作时两者不受控制的情况下都是默认低电平。三是I2C是要默认外部上拉的,但是不能有内部上拉也就是必须内部下拉,否则会出现I2C传输时的错误。

点击(此处)折叠或打开

  1. (1)基础宏定义

  2. #define GPIO_SCL S3C2410_GPF3
  3. #define GPIO_SDA S3C2410_GPF0
  4. #define GPIO_SDA_OUTP S3C2410_GPF0_OUTP //设定SDA输出
  5. #define GPIO_SDA_INP S3C2410_GPF0_INP //设定SDA输入
  6. #define GPIO_SCL_OUTP S3C2410_GPF3_OUTP //设定SCL输出

  7. void I2C_SCL_OUTP( void )
  8. {
  9.       s3c2410_gpio_cfgpin(GPIO_SCL,GPIO_SCL_OUTP);
  10. }

  11. void I2C_SCL_Output(u8 value)
  12. {
  13.       if(value)
  14.       { 
  15.             s3c2410_gpio_setpin(GPIO_SCL,value); 
  16.       }
  17.       else
  18.       {
  19.             s3c2410_gpio_setpin(GPIO_SCL,value ); 
  20.       } 
  21. }

  22.  

  23. void I2C_SDA_Mode(u8 v_mode) //SDA输出方向
  24. {
  25.        if(v_mode)
  26.        { 
  27.               s3c2410_gpio_cfgpin(GPIO_SDA, GPIO_SDA_OUTP); 
  28.        }
  29.        else
  30.        {
  31.               s3c2410_gpio_cfgpin(GPIO_SDA, GPIO_SDA_INP); 
  32.        }
  33. }

  34. void I2C_SDA_Output(u8 value)
  35. {
  36.        if(value)
  37.        { 
  38.                s3c2410_gpio_setpin(GPIO_SDA,value); 
  39.        }
  40.        else
  41.        {
  42.                 s3c2410_gpio_setpin(GPIO_SDA,value ); 
  43.        }
  44. }

  45. u8 I2C_SDA_Read(void) //SDA读数据
  46. {
  47.        return s3c2410_gpio_getpin(GPIO_SDA); 
  48. }

  49. (2)基础段

  50. void I2C_Init(void)

  51.       I2C_SDA_Output(1);
  52.       I2C_SCL_Output(1); //默认拉高
  53. }

  54. void I2C_Wait(void)
  55. {
  56.       u16 i;
  57.       for(i=0;i<200;i++);
  58. }

  59. void I2C_Start(void) 
  60. {
  61.       I2C_SDA_Output(1);
  62.       I2C_SCL_Output(1);
  63.       I2C_Wait();
  64.       I2C_SDA_Output(0);
  65.       I2C_Wait();
  66.       I2C_SCL_Output(0);
  67. }
  68. void I2C_Stop(void) 
  69. {
  70.       I2C_SDA_Output(0);
  71.       I2C_Wait();
  72.       I2C_SCL_Output(1);
  73.       I2C_Wait();
  74.       I2C_SDA_Output(1);
  75. }

  76. (3)读写单个字节的段

  77. u8 I2C_Send_Byte(u8 bytedata) 
  78. {
  79.       u8 i,ack;
  80.       I2C_SDA_Mode(1); //SDA输出
  81.       I2C_SCL_OUTP();
  82.       for (i = 0; i < 8; i++) 
  83.       {
  84.               if (bytedata & 0x80) 
  85.               {
  86.                      I2C_SDA_Output(1);
  87.               }
  88.               else
  89.               {
  90.                     I2C_SDA_Output(0);
  91.               }
  92.               bytedata <<= 1;
  93.              
  94.               I2C_SCL_Output(1);
  95.               udelay(3);
  96.               I2C_SCL_Output(0);
  97.               udelay(1);
  98.        } 
  99.    
  100.         I2C_SDA_Output(1); //release
  101.         udelay(3);
  102.         
  103.         I2C_SDA_Mode(0); //设定SDA输入
  104.         I2C_SCL_Output(1); 
  105.         udelay(3);
  106.         ack = I2C_SDA_Read(); //读应答
  107.         I2C_SDA_Mode(1); 
  108.         I2C_SCL_Output(0); 
  109.         udelay(3);
  110.        
  111.         return ack; 
  112. }

  113. u8 I2C_Receive_Byte(void) 
  114. {
  115.        u8 i;
  116.        u8 bytedata = 0x00;
  117.        u8 temp;
  118.  
  119.        I2C_SDA_Mode(0); 
  120.        for ( i = 0; i < 8; i++)
  121.        {
  122.              I2C_SCL_Output(1);
  123.              udelay(3);

  124.  

  125.              bytedata <<= 1;
  126.              temp = I2C_SDA_Read(); 
  127.              printk("reda SDA'value is:%d/n",temp);
  128.  
  129.              if (temp)
  130.                    bytedata |= 0x01; 
  131.              printk(" bytedata is:%x/n",bytedata);
  132.              I2C_SCL_Output(0);
  133.              udelay(1);
  134.        }
  135.        I2C_SDA_Mode(1); 
  136.        return bytedata;
  137. }

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

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

  140.        u8 ack;
  141.        printk("device_ID is:%x/n",device_ID);
  142.        printk("address is:%x/n",address);
  143.        printk("date is:%x/n",bytedata);
  144.        I2C_Start(); 
  145.        ack=I2C_Send_Byte(device_ID);
  146.        printk("ack is:%d/n",ack);
  147.        if(ack) 

  148.              I2C_Stop();
  149.        I2C_Send_Byte(address);
  150.        I2C_Send_Byte(bytedata);
  151.        I2C_Stop();
  152.        I2C_Wait(); 
  153.        return 0;
  154. }

  155. u8 I2C_Byte_Read(u8 device_ID,u8 address)

  156.        u8 bytedata;

  157.        I2C_Start();
  158.        I2C_Send_Byte(device_ID);
  159.        I2C_Send_Byte(address);
  160.        I2C_Start();
  161.        I2C_Send_Byte(device_ID+1);
  162.        bytedata = I2C_Receive_Byte(); //读单个字节,不需要再发应答
  163.        I2C_Stop(); 
  164.        return bytedata;
  165. }

  166. (5)类似可以完成读写多个字节的函数,暂不补充。
第二种方式也可以用

点击(此处)折叠或打开

  1. #ifdef I2C_USE_GPIO
  2. #define GPIO_I2C_DEBUG

  3. #define GPIO_I2C_SDA_PIN GPIO_I2C1_SCA_PIN
  4. #define GPIO_I2C_SCA_PIN GPIO_I2C1_SDA_PIN
  5. #define GPIO_SDA_OUTP mt_set_gpio_dir(GPIO_I2C_SDA_PIN,GPIO_DIR_OUT) //设定SDA输出
  6. #define GPIO_SDA_INP mt_set_gpio_dir(GPIO_I2C_SDA_PIN,GPIO_DIR_IN) //设定SDA输入
  7. #define GPIO_SCL_OUTP mt_set_gpio_dir(GPIO_I2C_SCA_PIN,GPIO_DIR_OUT) //设定SCL输出

  8. #define I2C_SDA_Output(value) mt_set_gpio_out(GPIO_I2C_SDA_PIN,value)
  9. #define I2C_SCL_Output(value) mt_set_gpio_out(GPIO_I2C_SCA_PIN,value)

  10. #define DELAY_TIME 0xc0

  11. u8 I2C_SDA_Read(void) //SDA读数据
  12. {
  13.        return mt_get_gpio_in(GPIO_I2C_SDA_PIN); 
  14. }


  15. void I2C_Init(void)

  16.     mt_set_gpio_mode(GPIO_I2C_SDA_PIN,GPIO_MODE_00);
  17.     mt_set_gpio_mode(GPIO_I2C_SCA_PIN,GPIO_MODE_00);

  18.     GPIO_SDA_OUTP;
  19.     GPIO_SCL_OUTP;
  20.     
  21.       I2C_SDA_Output(1);
  22.       I2C_SCL_Output(1); //默认拉高
  23. }

  24. #define I2C_START_TRANSMISSION 
  25.     { 
  26.         volatile u8 idx; 
  27.         GPIO_SCL_OUTP; 
  28.         GPIO_SDA_OUTP; 
  29.         I2C_SDA_Output(1); 
  30.         for (idx = 0; idx < DELAY_TIME; idx++); 
  31.         I2C_SCL_Output(1); 
  32.         for (idx = 0; idx < DELAY_TIME; idx++); 
  33.         I2C_SDA_Output(0); 
  34.         for (idx = 0; idx < DELAY_TIME; idx++); 
  35.         I2C_SCL_Output(0); 
  36.     }

  37.     #define I2C_STOP_TRANSMISSION 
  38.     { 
  39.         volatile u8 idx; 
  40.         GPIO_SCL_OUTP; 
  41.         GPIO_SDA_OUTP; 
  42.         I2C_SCL_Output(0); 
  43.         I2C_SDA_Output(0); 
  44.         for (idx = 0; idx < DELAY_TIME; idx++); 
  45.         I2C_SCL_Output(1); 
  46.         for (idx = 0; idx < DELAY_TIME; idx++); 
  47.         I2C_SDA_Output(1); 
  48.     }

  49. static kal_uint8 I2C_Send_Byte(kal_uint8 send_byte)
  50. {
  51.     volatile signed char i = 0;
  52.     volatile kal_uint16 j = 0;
  53.     kal_uint8 ack = 0;

  54.     for (i = 7; i >= 0; i--)
  55.     {
  56.         if (send_byte&(1 << i))
  57.         {
  58.             I2C_SDA_Output(1);
  59.         }
  60.         else
  61.         {
  62.             I2C_SDA_Output(0);
  63.         }
  64.         for (j = 0; j < DELAY_TIME; j++);
  65.         I2C_SCL_Output(1);
  66.         for (j = 0; j < DELAY_TIME; j++);
  67.         GPIO_SDA_OUTP; /* only for delay */
  68.         for (j = 0; j < DELAY_TIME; j++);
  69.         I2C_SCL_Output(0);
  70.         for (j = 0; j < DELAY_TIME; j++);
  71.     }
  72.     GPIO_SDA_INP;
  73.     for (j = 0; j < DELAY_TIME; j++);
  74.     I2C_SCL_Output(1);
  75.     for (j = 0; j < DELAY_TIME; j++);
  76.     ack = I2C_SDA_Read();
  77.     for (j = 0; j < DELAY_TIME; j++);
  78.     I2C_SCL_Output(0);
  79.     for (j = 0; j < DELAY_TIME; j++);
  80.     GPIO_SDA_OUTP;

  81.     return ack;
  82. }


  83. static kal_uint8 I2C_Receive_Byte(void)
  84. {
  85.     volatile signed char i = 0;
  86.     volatile kal_uint16 j = 0;
  87.     kal_uint8 get_byte = 0;

  88.     GPIO_SDA_INP;

  89.     for (j = 0; j < DELAY_TIME; j++);

  90.     for (i = 7; i >= 0; i--) { // data bit 7~0
  91.         I2C_SCL_Output(1);
  92.         for (j = 0; j < DELAY_TIME; j++);
  93.         if (I2C_SDA_Read()) {
  94.             get_byte |= (1 << i);
  95.         }
  96.         for (j = 0; j < DELAY_TIME; j++);
  97.         I2C_SCL_Output(0);
  98.         for (j = 0; j < DELAY_TIME; j++);
  99.     }

  100.     // don't care bit, 9th bit
  101.     GPIO_SDA_OUTP;
  102.     I2C_SDA_Output(1);
  103.     for (j = 0; j < DELAY_TIME; j++);
  104.     I2C_SCL_Output(1);
  105.     for (j = 0; j < DELAY_TIME; j++);
  106.     I2C_SCL_Output(0);

  107.     return get_byte;




  108. static kal_uint16 I2C_Receive_word(void)
  109. {
  110.     volatile signed char i = 0;
  111.     volatile kal_uint32 j = 0;
  112.     kal_uint16 get_byte = 0;

  113.     for (i = 15; i >= 8; i--)
  114.     {
  115.         GPIO_SDA_INP;
  116.         for (j = 0; j < DELAY_TIME; j++);
  117.         I2C_SCL_Output(1);
  118.         for (j = 0; j < DELAY_TIME; j++);
  119.         if (I2C_SDA_Read()) get_byte |= (1 << i);
  120.         for (j = 0; j < DELAY_TIME; j++);
  121.         I2C_SCL_Output(0);
  122.         for (j = 0; j < DELAY_TIME; j++);
  123.     }
  124.     I2C_SDA_Output(0);
  125.     GPIO_SDA_OUTP;
  126.     for (j = 0;j < DELAY_TIME; j++);
  127.     I2C_SCL_Output(1);
  128.     for (j = 0;j < DELAY_TIME; j++);
  129.     GPIO_SDA_OUTP; /* just for delay */
  130.     for (j = 0;j < DELAY_TIME; j++);
  131.     I2C_SCL_Output(0);
  132.     for (j = 0;j < DELAY_TIME; j++);
  133.     for (; i >= 0; i--)
  134.     {
  135.         GPIO_SDA_INP;
  136.         for (j = 0; j < DELAY_TIME; j++);
  137.         I2C_SCL_Output(1);
  138.         for (j = 0; j < DELAY_TIME; j++);
  139.         if (I2C_SDA_Read()) get_byte |= (1 << i);
  140.         for (j = 0; j < DELAY_TIME; j++);
  141.         I2C_SCL_Output(0);
  142.         for (j = 0; j < DELAY_TIME; j++);
  143.     }
  144.     I2C_SDA_Output(1);
  145.     GPIO_SDA_OUTP;
  146.     for (j = 0;j < DELAY_TIME; j++);
  147.     I2C_SCL_Output(1);
  148.     for (j = 0;j < DELAY_TIME; j++);
  149.     GPIO_SDA_OUTP; /* just for delay */
  150.     for (j = 0;j < DELAY_TIME; j++);
  151.     I2C_SCL_Output(0);
  152.     for (j = 0;j < DELAY_TIME; j++);

  153.     return get_byte;
  154. }

  155. u8 I2C_Byte_Write(u8 * a_puBuff , u8 len , u8 i2c_addr)

  156.        kal_uint8 fail_try_no = 4;
  157.     volatile signed char i = 0 ;
  158.     u8 ack_flag = 0;
  159.     while (--fail_try_no > 0)
  160.     {
  161.         ack_flag = 0;
  162.         I2C_START_TRANSMISSION;
  163.         if (I2C_Send_Byte(i2c_addr)) continue;
  164.            for(i = 0 ;i < len;i++){
  165.             if (I2C_Send_Byte(a_puBuff[i])){
  166.                 ack_flag = 1;
  167.                 break;
  168.             } 
  169.            }
  170.         if(ack_flag)
  171.             continue;
  172.         break;
  173.     }
  174.     I2C_STOP_TRANSMISSION;
  175.        return 0;
  176. }

  177. u8 I2C_Bytes_Read(u8 *a_puBuff, u8 reglen ,u8 *byteget,u8 bytelen,u8 i2c_addr)


  178.     kal_uint16 get_byte = 0xFFFF;
  179.     kal_uint8 fail_try_no = 4;
  180.     volatile kal_uint32 i = 0;
  181.     u8 ack_flag = 0;

  182.     while (--fail_try_no > 0)
  183.     {
  184.         ack_flag = 0;
  185.         I2C_START_TRANSMISSION;
  186.         if (I2C_Send_Byte(i2c_addr)) continue;
  187.         
  188.         //send reg
  189.      for(i = 0 ;i < reglen;i++){
  190.             if (I2C_Send_Byte(a_puBuff[i])){
  191.                 ack_flag = 1;
  192.                 break;
  193.             } 
  194.            }
  195.         if(ack_flag)
  196.             continue;
  197.         
  198.         I2C_START_TRANSMISSION;
  199.         if (I2C_Send_Byte(i2c_addr | 1)) continue;
  200.         
  201.         if(bytelen == 1)
  202.          byteget[0] = get_byte = I2C_Receive_Byte(); //读单个字节,不需要再发应答
  203.         else if(bytelen > 1)
  204.         {
  205.              get_byte=I2C_Receive_word();
  206.              byteget[1] = get_byte & 0x00ff;
  207.               byteget[0] = (get_byte & 0xff00) >> 8;
  208.          }
  209.         break;
  210.     }
  211.     I2C_STOP_TRANSMISSION;

  212.     printk("----%s---read data %x---n",__func__,get_byte);

  213.     return get_byte;

  214. }    

  215. int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId)
  216. {
  217.     I2C_Byte_Write(a_pSendData,a_sizeSendData,i2cId);
  218.     return 0;
  219. }

  220. int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId)
  221. {
阅读(757) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~