普通GPIO口线模拟I2C

ARM编程:ARM普通GPIO口线模拟I2C 

请教个问题:
因为需要很多EEPROM进行点对点控制,所以我现在要用ARM的GPIO模拟I2C,管脚方向我设
置的是向外的。我用网上的RW24C08的万能程序修改了一下,先进行两根线的模拟,SDA6,
SCL6,但是读出来的数不对。我做了一个简单的实验,模拟SDA6,SCL6输出方波,在示波
器上看到正确方波,也就是说,我的输出控制是没问题的。
哪位大哥能指点一下,是否在接收时管脚方向要设为向内?(不过IOPIN不管什么方向都可
以读出当前状态值的阿)

附修改的RW24C08()程序:

    1. #define SomeNOP() delay(300);  
    2. /**//**********************************  RW24C08   
    3. *****************************************/  
    4. /**//*----------------------------------------------------------------------------- 
    5. --- 
    6.  调用方式:void I2CInit(void)  
    7.  函数说明:私有函数,I2C专用 
    8. ------------------------------------------------------------------------------- 
    9. --*/  
    10. void I2CInit(void)  
    11. ...{  
    12.  IO0CLR = SCL6;     //初始状态关闭总线  
    13.  SomeNOP(); //延时   
    14.  I2CStop(); //确保初始化,此时数据线是高电平  
    15. }  
    16.   
    17.  /**//*---------------------------------------------------------------------------- 
    18. ---- 
    19.  调用方式:void I2CStart(void)  
    20.  函数说明:私有函数,I2C专用 
    21. ------------------------------------------------------------------------------- 
    22. --*/  
    23. void I2CStart(void)  
    24. ...{  
    25.   
    26.  SomeNOP();  
    27.  IO0SET = SCL6;   
    28.  SomeNOP();//INI  
    29.  IO2CLR = SDA6;  
    30.  SomeNOP(); //START  
    31.  IO0CLR = SCL6;  
    32.  SomeNOP();  
    33. }  
    34. /**//*----------------------------------------------------------------------------- 
    35. --- 
    36.  调用方式:void I2CStop(void)  
    37.  函数说明:私有函数,I2C专用 
    38.  ------------------------------------------------------------------------------ 
    39. ---*/  
    40.  void I2CStop(void)  
    41.  ...{  
    42.   IO2CLR = SDA6;  
    43.   SomeNOP(); //INI  
    44.   IO0SET = SCL6;   
    45.   SomeNOP();   
    46.   IO2SET = SDA6;  
    47.   SomeNOP();   
    48.   IO0CLR = SCL6;  
    49.  }  
    50.   
    51.    
    52. /**//*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    53. I2CClock:    发送总线时钟信号,并返回时钟电平为高期间SDA上的状态,低为 ACK,高失败 
    54. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/  
    55.   
    56. INT8U I2CClock(void)  
    57. ...{  
    58.     INT8U sample;  
    59.     SomeNOP();  
    60.     IO0SET = SCL6;   
    61.     delay(180);  
    62.     sample = (INT8U)((IO2PIN & 0x2000)>>13);  
    63.     delay(120);  
    64.     IO0CLR = SCL6;  
    65.     SomeNOP();  
    66.     //return (sample);  
    67.     if(sample==1) return(1);  
    68.     else          return(0);  
    69. }  
    70. /**//*----------------------------------------------------------------------------- 
    71. --- 
    72.  调用方式:void SendAck(void) 
    73.  函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,应答信号。 
    74.  ------------------------------------------------------------------------------ 
    75. ---*/  
    76.  void SendAck(void)  
    77.  ...{  
    78.     IO2CLR = SDA6;  
    79.     I2CClock();  
    80.     IO2SET = SDA6;  
    81.  }  
    82.   
    83.  /**//*---------------------------------------------------------------------------- 
    84. ---- 
    85.  调用方式:void SendAck(void)  
    86.  函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,非应答信号。 
    87. **----------------------------------------------------------------------------- 
    88. ---*/  
    89.  void SendNotAck(void)  
    90.  ...{  
    91.      IO2SET = SDA6;  
    92.     I2CClock();  
    93.  }  
    94.   
    95.  /**//*---------------------------------------------------------------------------- 
    96. ---- 
    97.  调用方式:void I2CSend(uchar ch)  
    98.  函数说明:私有函数,I2C专用 
    99.  ------------------------------------------------------------------------------ 
    100. ---*/  
    101. INT8U I2CSendByte(INT8U ch)  
    102.  ...{  
    103.  register INT8U i;  
    104.  INT8U statue;  
    105.  for (i=0; i<8; i++)...{  
    106.      statue = (INT8U) ((ch&0x80)>>7);  
    107.      if(statue==1)  
    108.      IO2SET = SDA6;  
    109.      else  
    110.      IO2CLR = SDA6;  
    111.     ch <<= 1;  
    112.     I2CClock();  
    113.     }  
    114.  IO2SET = SDA6;  
    115.  return (~I2CClock());  
    116.  }  
    117.   
    118.  /**//*---------------------------------------------------------------------------- 
    119. ---- 
    120.  调用方式:uchar I2CReceive(void)  
    121.  函数说明:私有函数,I2C专用 
    122.  ------------------------------------------------------------------------------ 
    123. ---*/  
    124. INT8U I2CReceiveByte(void)  
    125.  ...{  
    126.     register INT8U i;  
    127.     INT8U ddata=0;  
    128.     for (i=0;i<8;i++)...{  
    129.         ddata<<=1;  
    130.         if(I2CClock()) ddata++;  
    131.     }  
    132.     return (ddata);  
    133.  }  
    134.   
    135. /**//*------------------------------------------------ 
    136. RW2408 Function 
    137. ------------------------------------------------*/  
    138. //DataBuff 为读写数据输入/输出缓冲区的首址  
    139. //Length 为要读写数据的字节数量  
    140. //Address 为EEPROM的片内地址  
    141. //ControlByte 为EEPROM的控制字节,具体形式为(1)(0)(1)(0)(A2)(A1)(A0)(R/W),  
    142. //             其中R/W=1,表示读操作,R/W=0为写操作,A2,A1,A0为EEPROM的页选或片选  
    143. 地址;  
    144. void  RW2408(INT8U *DataBuff,INT8U Length,INT32U Addr,INT8U Wr)  
    145. ...{   
    146.     INT8U j;                            // 发送字节索引                      
    147.   //  EA=0;                                           // 发送期间禁止中断,防止干扰  
    148.     I2CInit();    
    149.     I2CStart();                                     // 启动总线     
    150.     I2CSendByte(0xa0);                              // 向IIC总线发送2408写地址  
    151.     I2CSendByte(Addr);                              // 向IIC总线发送要操作的RAM地址  
    152.         
    153.     if(Wr==0)                           // 如果是写操作    
    154.     ...{   
    155.       for(j=0;j<Length;j++)  
    156.        ...{  
    157.          I2CSendByte(*DataBuff++);                   // 每个循环送1个数据  
    158.        }  
    159.     }  
    160.   /**//*---------------------------如果是读操作 ----------------------*/  
    161.     else if(Wr==1)                        
    162.     ...{  
    163.       I2CStart();                                   // 启动总线   
    164.       I2CSendByte(0xa1);                            // 向IIC总线发送2408读地址  
    165.   
    166.       for(j=0;j<Length-1;j++)    
    167.       ...{   
    168.         IO2SET = SDA6;                                     // 写之前把数据线置高  
    169.         *DataBuff++=I2CReceiveByte();               // 每次读1个字节  
    170.         SendAck();                                  // 发送应答信号   
    171.       }  
    172.       *DataBuff=I2CReceiveByte();                 // 读最后一个数据  
    173.       SendNotAck();                                 // 发送非应答信号    
    174.     }  
    175.    I2CStop();                                       //  停止IIC总线   
    176.  //  EA=1;  
    177. } 
posted @ 2013-03-17 18:43  天涯海角路  阅读(235)  评论(0)    收藏  举报