Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1655362
  • 博文数量: 1493
  • 博客积分: 38
  • 博客等级: 民兵
  • 技术积分: 5834
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-19 17:28
文章分类

全部博文(1493)

文章存档

2016年(11)

2015年(38)

2014年(137)

2013年(253)

2012年(1054)

2011年(1)

分类:

2012-12-25 09:44:55

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

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. { 
  52.       I2C_SDA_Output(1);
  53.       I2C_SCL_Output(1); //默认拉高
  54. }

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

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

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

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

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

  125.  

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

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

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

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

  157. u8 I2C_Byte_Read(u8 device_ID,u8 address)
  158. { 
  159.        u8 bytedata;

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

  169. (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. { 
  17.     mt_set_gpio_mode(GPIO_I2C_SDA_PIN,GPIO_MODE_00);
  18.     mt_set_gpio_mode(GPIO_I2C_SCA_PIN,GPIO_MODE_00);

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

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

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

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

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

  82.     return ack;
  83. }


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

  89.     GPIO_SDA_INP;

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

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

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

  108.     return get_byte;
  109. } 



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

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

  155.     return get_byte;
  156. }

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

  180. u8 I2C_Bytes_Read(u8 *a_puBuff, u8 reglen ,u8 *byteget,u8 bytelen,u8 i2c_addr)
  181. { 

  182.     kal_uint16 get_byte = 0xFFFF;
  183.     kal_uint8 fail_try_no = 4;
  184.     volatile kal_uint32 i = 0;
  185.     u8 ack_flag = 0;

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

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

  217.     return get_byte;

  218. }    

  219. int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId)
  220. {
  221.     I2C_Byte_Write(a_pSendData,a_sizeSendData,i2cId);
  222.     return 0;
  223. }

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