linux平台上GPIO模拟I2C

来源:互联网 发布:淘宝评价生效时间 编辑:程序博客网 时间:2024/05/29 04:44
GPIO模拟I2C是嵌入式中较为常用的一种应用。各个地方有各种不同的做法,按照我自己的个人理解,最好是把I2C的各种状态分割开来,比如起始条件终止条件,读数据和写数据,然后根据具体的使用场合组合起来。

      这里需要注意两点:一是SCL的波形并不规律,不能将它理解为方波,它本身只是一段段独立的波形。二是每段操作时,之前和之后的SCL和SDA波形是可以忽略的;通常情况下I2C开始之前和I2C结束之后,两者都是有上拉的高电平,而在正常工作时两者不受控制的情况下都是默认低电平。三是I2C是要默认外部上拉的,但是不能有内部上拉也就是必须内部下拉,否则会出现I2C传输时的错误。

[cpp] view plaincopyprint?
  1. (1)基础宏定义 
  2.  
  3. #define GPIO_SCL             S3C2410_GPF3 
  4. #define GPIO_SDA             S3C2410_GPF0 
  5. #define GPIO_SDA_OUTP   S3C2410_GPF0_OUTP  //设定SDA输出 
  6. #define GPIO_SDA_INP      S3C2410_GPF0_INP     //设定SDA输入 
  7. #define GPIO_SCL_OUTP   S3C2410_GPF3_OUTP  //设定SCL输出 
  8.  
  9. void I2C_SCL_OUTP( void
  10.       s3c2410_gpio_cfgpin(GPIO_SCL,GPIO_SCL_OUTP); 
  11.  
  12. void I2C_SCL_Output(u8 value) 
  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.  
  24. void I2C_SDA_Mode(u8 v_mode)   //SDA输出方向 
  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.        if(value) 
  36.        {                                                 
  37.                s3c2410_gpio_setpin(GPIO_SDA,value);   
  38.        } 
  39.        else 
  40.        { 
  41.                 s3c2410_gpio_setpin(GPIO_SDA,value );   
  42.        } 
  43.  
  44. u8 I2C_SDA_Read(void)    //SDA读数据 
  45.        return s3c2410_gpio_getpin(GPIO_SDA);   
  46.  
  47. (2)基础段 
  48.  
  49. void I2C_Init(void
  50. {  
  51.       I2C_SDA_Output(1); 
  52.       I2C_SCL_Output(1);      //默认拉高 
  53.  
  54. void I2C_Wait(void
  55.       u16 i; 
  56.       for(i=0;i<200;i++); 
  57.  
  58. void I2C_Start(void)  
  59.       I2C_SDA_Output(1); 
  60.       I2C_SCL_Output(1); 
  61.       I2C_Wait(); 
  62.       I2C_SDA_Output(0); 
  63.       I2C_Wait(); 
  64.       I2C_SCL_Output(0); 
  65. void I2C_Stop(void)  
  66.       I2C_SDA_Output(0); 
  67.       I2C_Wait(); 
  68.       I2C_SCL_Output(1); 
  69.       I2C_Wait(); 
  70.       I2C_SDA_Output(1); 
  71.  
  72. (3)读写单个字节的段 
  73.  
  74. u8 I2C_Send_Byte(u8 bytedata)  
  75.       u8 i,ack; 
  76.       I2C_SDA_Mode(1);  //SDA输出 
  77.       I2C_SCL_OUTP(); 
  78.       for (i = 0; i < 8; i++)   
  79.       { 
  80.               if (bytedata & 0x80)  
  81.               { 
  82.                      I2C_SDA_Output(1); 
  83.               } 
  84.               else 
  85.               { 
  86.                     I2C_SDA_Output(0); 
  87.               } 
  88.               bytedata <<= 1; 
  89.               
  90.               I2C_SCL_Output(1); 
  91.               udelay(3); 
  92.               I2C_SCL_Output(0); 
  93.               udelay(1); 
  94.        }      
  95.     
  96.         I2C_SDA_Output(1);  //release 
  97.         udelay(3); 
  98.          
  99.         I2C_SDA_Mode(0);  //设定SDA输入 
  100.         I2C_SCL_Output(1);    
  101.         udelay(3); 
  102.         ack = I2C_SDA_Read();   //读应答 
  103.         I2C_SDA_Mode(1);  
  104.         I2C_SCL_Output(0);  
  105.         udelay(3); 
  106.         
  107.         return ack;    
  108.  
  109. u8 I2C_Receive_Byte(void)   
  110.        u8 i; 
  111.        u8 bytedata = 0x00; 
  112.        u8 temp; 
  113.   
  114.        I2C_SDA_Mode(0);  
  115.        for ( i = 0; i < 8; i++) 
  116.        { 
  117.              I2C_SCL_Output(1); 
  118.              udelay(3); 
  119.  
  120.   
  121.  
  122.              bytedata <<= 1; 
  123.              temp = I2C_SDA_Read();  
  124.              printk("reda SDA'value is:%d/n",temp); 
  125.   
  126.              if (temp) 
  127.                    bytedata |= 0x01;  
  128.              printk("  bytedata is:%x/n",bytedata); 
  129.              I2C_SCL_Output(0); 
  130.              udelay(1); 
  131.        } 
  132.        I2C_SDA_Mode(1);  
  133.        return bytedata; 
  134.  
  135. (4)读写单个字节的I2C应用函数 
  136.  
  137. u8 I2C_Byte_Write(u8 device_ID,u8 address,u8 bytedata) 
  138. {    
  139.        u8 ack; 
  140.        printk("device_ID is:%x/n",device_ID); 
  141.        printk("address is:%x/n",address); 
  142.        printk("date is:%x/n",bytedata); 
  143.        I2C_Start();   
  144.        ack=I2C_Send_Byte(device_ID); 
  145.        printk("ack is:%d/n",ack); 
  146.        if(ack)  
  147.  
  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. {    
  157.        u8 bytedata; 
  158.  
  159.        I2C_Start(); 
  160.        I2C_Send_Byte(device_ID); 
  161.        I2C_Send_Byte(address); 
  162.        I2C_Start(); 
  163.        I2C_Send_Byte(device_ID+1); 
  164.        bytedata = I2C_Receive_Byte();  //读单个字节,不需要再发应答 
  165.        I2C_Stop();     
  166.        return bytedata; 
  167.  
  168. (5)类似可以完成读写多个字节的函数,暂不补充。 

==================================================================================================================================

==================================================================================================================================

第二种方式也可以用

[cpp] view plaincopyprint?
  1. #ifdef I2C_USE_GPIO 
  2. #define GPIO_I2C_DEBUG 
  3.  
  4. #define GPIO_I2C_SDA_PIN   GPIO_I2C1_SCA_PIN 
  5. #define GPIO_I2C_SCA_PIN   GPIO_I2C1_SDA_PIN 
  6. #define GPIO_SDA_OUTP   mt_set_gpio_dir(GPIO_I2C_SDA_PIN,GPIO_DIR_OUT)  //设定SDA输出 
  7. #define GPIO_SDA_INP      mt_set_gpio_dir(GPIO_I2C_SDA_PIN,GPIO_DIR_IN)     //设定SDA输入 
  8. #define GPIO_SCL_OUTP   mt_set_gpio_dir(GPIO_I2C_SCA_PIN,GPIO_DIR_OUT)  //设定SCL输出 
  9.  
  10. #define I2C_SDA_Output(value)  mt_set_gpio_out(GPIO_I2C_SDA_PIN,value) 
  11. #define I2C_SCL_Output(value)  mt_set_gpio_out(GPIO_I2C_SCA_PIN,value) 
  12.  
  13. #define DELAY_TIME   0xc0 
  14.  
  15. u8 I2C_SDA_Read(void)   //SDA读数据 
  16.        return mt_get_gpio_in(GPIO_I2C_SDA_PIN);   
  17.  
  18.  
  19. void I2C_Init(void
  20. {  
  21.     mt_set_gpio_mode(GPIO_I2C_SDA_PIN,GPIO_MODE_00); 
  22.     mt_set_gpio_mode(GPIO_I2C_SCA_PIN,GPIO_MODE_00); 
  23.  
  24.     GPIO_SDA_OUTP; 
  25.     GPIO_SCL_OUTP; 
  26.      
  27.       I2C_SDA_Output(1); 
  28.       I2C_SCL_Output(1);      //默认拉高 
  29.  
  30. #define I2C_START_TRANSMISSION \ 
  31.     { \ 
  32.         volatile u8 idx; \ 
  33.         GPIO_SCL_OUTP; \ 
  34.         GPIO_SDA_OUTP; \ 
  35.         I2C_SDA_Output(1); \ 
  36.         for (idx = 0; idx < DELAY_TIME; idx++); \ 
  37.         I2C_SCL_Output(1); \ 
  38.         for (idx = 0; idx < DELAY_TIME; idx++); \ 
  39.         I2C_SDA_Output(0); \ 
  40.         for (idx = 0; idx < DELAY_TIME; idx++); \ 
  41.         I2C_SCL_Output(0); \ 
  42.     } 
  43.  
  44.     #define I2C_STOP_TRANSMISSION \ 
  45.     { \ 
  46.         volatile u8 idx; \ 
  47.         GPIO_SCL_OUTP; \ 
  48.         GPIO_SDA_OUTP; \ 
  49.         I2C_SCL_Output(0); \ 
  50.         I2C_SDA_Output(0); \ 
  51.         for (idx = 0; idx < DELAY_TIME; idx++); \ 
  52.         I2C_SCL_Output(1); \ 
  53.         for (idx = 0; idx < DELAY_TIME; idx++); \ 
  54.         I2C_SDA_Output(1); \ 
  55.     } 
  56.  
  57. static kal_uint8 I2C_Send_Byte(kal_uint8 send_byte) 
  58.     volatile signedchar i = 0; 
  59.     volatile kal_uint16 j = 0; 
  60.     kal_uint8 ack = 0; 
  61.  
  62.     for (i = 7; i >= 0; i--) 
  63.     { 
  64.         if (send_byte&(1 << i)) 
  65.         { 
  66.             I2C_SDA_Output(1); 
  67.         } 
  68.         else 
  69.         { 
  70.             I2C_SDA_Output(0); 
  71.         } 
  72.         for (j = 0; j < DELAY_TIME; j++); 
  73.         I2C_SCL_Output(1); 
  74.         for (j = 0; j < DELAY_TIME; j++); 
  75.         GPIO_SDA_OUTP; /* only for delay */ 
  76.         for (j = 0; j < DELAY_TIME; j++); 
  77.         I2C_SCL_Output(0); 
  78.         for (j = 0; j < DELAY_TIME; j++); 
  79.     } 
  80.     GPIO_SDA_INP; 
  81.     for (j = 0; j < DELAY_TIME; j++); 
  82.     I2C_SCL_Output(1); 
  83.     for (j = 0; j < DELAY_TIME; j++); 
  84.     ack = I2C_SDA_Read(); 
  85.     for (j = 0; j < DELAY_TIME; j++); 
  86.     I2C_SCL_Output(0); 
  87.     for (j = 0; j < DELAY_TIME; j++); 
  88.     GPIO_SDA_OUTP; 
  89.  
  90.     return ack; 
  91.  
  92.  
  93. static kal_uint8 I2C_Receive_Byte(void
  94.     volatile signedchar i = 0; 
  95.     volatile kal_uint16 j = 0; 
  96.     kal_uint8 get_byte = 0; 
  97.  
  98.     GPIO_SDA_INP; 
  99.  
  100.     for (j = 0; j < DELAY_TIME; j++); 
  101.  
  102.     for (i = 7; i >= 0; i--) {    // data bit 7~0 
  103.         I2C_SCL_Output(1); 
  104.         for (j = 0; j < DELAY_TIME; j++); 
  105.         if (I2C_SDA_Read()) { 
  106.             get_byte |= (1 << i); 
  107.         } 
  108.         for (j = 0; j < DELAY_TIME; j++); 
  109.         I2C_SCL_Output(0); 
  110.         for (j = 0; j < DELAY_TIME; j++); 
  111.     } 
  112.  
  113.     // don't care bit, 9th bit 
  114.     GPIO_SDA_OUTP; 
  115.     I2C_SDA_Output(1); 
  116.     for (j = 0; j < DELAY_TIME; j++); 
  117.     I2C_SCL_Output(1); 
  118.     for (j = 0; j < DELAY_TIME; j++); 
  119.     I2C_SCL_Output(0); 
  120.  
  121.     return get_byte; 
  122. }    
  123.  
  124.  
  125.  
  126. static kal_uint16 I2C_Receive_word(void
  127.     volatile signedchar i = 0; 
  128.     volatile kal_uint32 j = 0; 
  129.     kal_uint16 get_byte = 0; 
  130.  
  131.     for (i = 15; i >= 8; i--) 
  132.     { 
  133.         GPIO_SDA_INP; 
  134.         for (j = 0; j < DELAY_TIME; j++); 
  135.         I2C_SCL_Output(1); 
  136.         for (j = 0; j < DELAY_TIME; j++); 
  137.         if (I2C_SDA_Read()) get_byte |= (1 << i); 
  138.         for (j = 0; j < DELAY_TIME; j++); 
  139.         I2C_SCL_Output(0); 
  140.         for (j = 0; j < DELAY_TIME; j++); 
  141.     } 
  142.     I2C_SDA_Output(0); 
  143.     GPIO_SDA_OUTP; 
  144.     for (j = 0;j < DELAY_TIME; j++); 
  145.     I2C_SCL_Output(1); 
  146.     for (j = 0;j < DELAY_TIME; j++); 
  147.     GPIO_SDA_OUTP; /* just for delay */ 
  148.     for (j = 0;j < DELAY_TIME; j++); 
  149.     I2C_SCL_Output(0); 
  150.     for (j = 0;j < DELAY_TIME; j++); 
  151.     for (; i >= 0; i--) 
  152.     { 
  153.         GPIO_SDA_INP; 
  154.         for (j = 0; j < DELAY_TIME; j++); 
  155.         I2C_SCL_Output(1); 
  156.         for (j = 0; j < DELAY_TIME; j++); 
  157.         if (I2C_SDA_Read()) get_byte |= (1 << i); 
  158.         for (j = 0; j < DELAY_TIME; j++); 
  159.         I2C_SCL_Output(0); 
  160.         for (j = 0; j < DELAY_TIME; j++); 
  161.     } 
  162.     I2C_SDA_Output(1); 
  163.     GPIO_SDA_OUTP; 
  164.     for (j = 0;j < DELAY_TIME; j++); 
  165.     I2C_SCL_Output(1); 
  166.     for (j = 0;j < DELAY_TIME; j++); 
  167.     GPIO_SDA_OUTP; /* just for delay */ 
  168.     for (j = 0;j < DELAY_TIME; j++); 
  169.     I2C_SCL_Output(0); 
  170.     for (j = 0;j < DELAY_TIME; j++); 
  171.  
  172.     return get_byte; 
  173.  
  174. u8 I2C_Byte_Write(u8 * a_puBuff , u8 len , u8 i2c_addr) 
  175. {    
  176.        kal_uint8 fail_try_no = 4; 
  177.     volatile signedchar i = 0 ; 
  178.     u8 ack_flag = 0; 
  179.     while (--fail_try_no > 0) 
  180.     { 
  181.         ack_flag = 0; 
  182.         I2C_START_TRANSMISSION; 
  183.         if (I2C_Send_Byte(i2c_addr))continue
  184.         for(i = 0 ;i < len;i++){ 
  185.             if (I2C_Send_Byte(a_puBuff[i])){ 
  186.                 ack_flag = 1; 
  187.                 break
  188.             }  
  189.         } 
  190.         if(ack_flag) 
  191.             continue
  192.         break
  193.     } 
  194.     I2C_STOP_TRANSMISSION; 
  195.        return 0; 
  196.  
  197. u8 I2C_Bytes_Read(u8 *a_puBuff, u8 reglen ,u8 *byteget,u8 bytelen,u8 i2c_addr) 
  198. {    
  199.  
  200.     kal_uint16 get_byte = 0xFFFF; 
  201.     kal_uint8 fail_try_no = 4; 
  202.     volatile kal_uint32 i = 0; 
  203.     u8 ack_flag = 0; 
  204.  
  205.     while (--fail_try_no > 0) 
  206.     { 
  207.         ack_flag = 0; 
  208.         I2C_START_TRANSMISSION; 
  209.         if (I2C_Send_Byte(i2c_addr))continue
  210.          
  211.         //send reg 
  212.            for(i = 0 ;i < reglen;i++){ 
  213.             if (I2C_Send_Byte(a_puBuff[i])){ 
  214.                 ack_flag = 1; 
  215.                 break
  216.             }  
  217.         } 
  218.         if(ack_flag) 
  219.             continue
  220.          
  221.         I2C_START_TRANSMISSION; 
  222.         if (I2C_Send_Byte(i2c_addr | 1))continue
  223.          
  224.         if(bytelen == 1) 
  225.             byteget[0] = get_byte = I2C_Receive_Byte();  //读单个字节,不需要再发应答 
  226.         else if(bytelen > 1) 
  227.         { 
  228.             get_byte=I2C_Receive_word(); 
  229.              byteget[1] = get_byte & 0x00ff; 
  230.              byteget[0] = (get_byte & 0xff00) >> 8; 
  231.          } 
  232.         break
  233.     } 
  234.     I2C_STOP_TRANSMISSION; 
  235.  
  236.     printk("----%s---read data %x---\n",__func__,get_byte); 
  237.  
  238.     return get_byte; 
  239.  
  240. }    
  241.  
  242. int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId) 
  243.     I2C_Byte_Write(a_pSendData,a_sizeSendData,i2cId); 
  244.     return 0; 
  245.  
  246. int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId) 
  247.     I2C_Bytes_Read(a_pSendData,a_sizeSendData,a_pRecvData,a_sizeRecvData,i2cId); 
  248.      return 0; 
  249. #endif 


原创粉丝点击